diff --git a/README.md b/README.md index 48c73a6..2c0dfbb 100644 --- a/README.md +++ b/README.md @@ -35,56 +35,39 @@ docker compose -f docker-compose.test.yml up --exit-code-from app --build Note: This will create a /coverage folder where you can review the coverage details. -### Schema for rawinfo + +### User interface ```ts -rawinfo { - type: number, - author: Snowflake, - content: string, - createdDate: Date, - user_mentions: Array, - role_mentions: Array, - reactions: Array, - replied_user: Snowflake | null | undefined, - messageId: Snowflake, - channelId: Snowflake, - channelName: string | null, - threadId: Snowflake | null, - threadName: string | null, - isGeneratedByWebhook: boolean +User { + discordId: Snowflake, + email?: string, + communities?: [Types.ObjectId] } ``` -### Schema for user +### Community interface ```ts -User { - discordId: Snowflake, - username?: string, - discriminator?: string, - avatar?: string, - bot?: boolean, - system?: boolean, - mfa_enabled?: boolean, - banner?: string, - accent_color?: number - locale?: string, - verified?: boolean - email?: string, - flags?: number, - premium_type?: number, - public_flags?: number, - twitterId?: string, - twitterUsername?: string, - twitterProfileImageUrl?: string, - twitterConnectedAt?:string, - twitterIsInProgress?:boolean - +Community { + name: string, + avatarURL?: string, + users?: [Types.ObjectId], + platforms?: [Types.ObjectId], } ``` -### Schema for heatmap +### Platform interface + +```ts +Platform { + name: string, + community: Types.ObjectId, + metadata?: Record, // dynamic object since structure can change + disconnectedAt?: Date | null, +} +``` +### Heatmap interface ```ts HeatMap { @@ -105,7 +88,7 @@ HeatMap { } ``` -### Schema for guildMembers +### GuildMembers interface ```ts GuildMember { @@ -124,7 +107,52 @@ GuildMember { ``` -### Schema for memberactivities +### Channel interface + +```ts +Channel { + id: Snowflake, + name?: string | null, + parent_id?: string | null, + permissionOverwrites?: IOverwrite[], + deletedAt?: Date | null +} +``` + + +### Role interface + +```ts +Role { + id: Snowflake, + name: string, + color: number, + deletedAt?: Date | null +} +``` + +### Rawinfo interface + +```ts +rawinfo { + type: number, + author: Snowflake, + content: string, + createdDate: Date, + user_mentions: Array, + role_mentions: Array, + reactions: Array, + replied_user: Snowflake | null | undefined, + messageId: Snowflake, + channelId: Snowflake, + channelName: string | null, + threadId: Snowflake | null, + threadName: string | null, + isGeneratedByWebhook: boolean +} +``` + +### Memberactivities interface ```ts memberactivities { @@ -153,7 +181,7 @@ memberactivities { } ``` -### Schema for token +### Token interface ```ts Token { @@ -163,51 +191,4 @@ Token { expires: Date, blacklisted?: boolean } -``` - -### Schema for guild - -```ts -Guild { - guildId: Snowflake, - user: Snowflake, - name?: string, - connectedAt?: Date, - isInProgress?: Boolean, - isDisconnected?: Boolean, - icon?: string, - selectedChannels?: Array [ - { - channelId: Snowflake, - channelName?: string - } - ], - period?: Date, - aciton: Array, - window: Array -} -``` - -### Schema for channel - -```ts -Channel { - id: Snowflake, - name?: string | null, - parent_id?: string | null, - permissionOverwrites?: IOverwrite[], - deletedAt?: Date | null -} -``` - - -### Schema for role - -```ts -Role { - id: Snowflake, - name: string, - color: number, - deletedAt?: Date | null -} -``` +``` \ No newline at end of file diff --git a/__tests__/unit/models/community.mode.test.ts b/__tests__/unit/models/community.mode.test.ts new file mode 100644 index 0000000..91e2599 --- /dev/null +++ b/__tests__/unit/models/community.mode.test.ts @@ -0,0 +1,19 @@ +import { Community } from '../../../src/models'; +import { ICommunity } from '../../../src/interfaces'; +import { Types } from 'mongoose'; + +describe('Community model', () => { + describe('Community validation', () => { + let community: ICommunity; + beforeEach(() => { + community = { + name: 'community1', + users: [new Types.ObjectId()], + }; + }); + + test('should correctly validate a valid community', async () => { + await expect(new Community(community).validate()).resolves.toBeUndefined(); + }); + }); +}); diff --git a/__tests__/unit/models/guild.model.test.ts b/__tests__/unit/models/guild.model.test.ts deleted file mode 100644 index 536a70a..0000000 --- a/__tests__/unit/models/guild.model.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Guild } from '../../../src/models'; -import { IGuild } from '../../../src/interfaces'; -import moment from 'moment'; - -describe('Guild model', () => { - describe('Guild validation', () => { - let guild: IGuild; - beforeEach(() => { - guild = { - guildId: '681946187490000906', - user: '681946187490000906', - name: 'guild', - selectedChannels: [ - { - channelId: '681946187490000906', - channelName: 'channel', - }, - ], - period: moment('2022-02-01 08:30:26.127Z').toDate(), - connectedAt: moment('2022-02-01 08:30:26.127Z').toDate(), - isDisconnected: true, - isInProgress: false, - icon: null, - window: [7, 1], - action: [1, 1, 1, 4, 3, 5, 5, 4, 3, 2, 2, 2, 1], - }; - }); - - test('should correctly validate a valid guild', async () => { - await expect(new Guild(guild).validate()).resolves.toBeUndefined(); - }); - }); -}); diff --git a/__tests__/unit/models/platform.model.test.ts b/__tests__/unit/models/platform.model.test.ts new file mode 100644 index 0000000..5ad4e9d --- /dev/null +++ b/__tests__/unit/models/platform.model.test.ts @@ -0,0 +1,19 @@ +import { Platfrom } from '../../../src/models'; +import { IPlatform } from '../../../src/interfaces'; +import { Types } from 'mongoose'; + +describe('Platfrom model', () => { + describe('Platform validation', () => { + let platfrom: IPlatform; + beforeEach(() => { + platfrom = { + name: 'Discord', + community: new Types.ObjectId(), + }; + }); + + test('should correctly validate a valid platfrom', async () => { + await expect(new Platfrom(platfrom).validate()).resolves.toBeUndefined(); + }); + }); +}); diff --git a/package.json b/package.json index b2a939c..e02ec31 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@togethercrew.dev/db", - "version": "2.5.02", + "version": "3.0.00", "description": "All interactions with DB", "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/src/interfaces/Community.interface.ts b/src/interfaces/Community.interface.ts new file mode 100644 index 0000000..6062137 --- /dev/null +++ b/src/interfaces/Community.interface.ts @@ -0,0 +1,19 @@ +import { type Model, type Types } from 'mongoose'; + +export interface ICommunity { + name: string; + avatarURL?: string; + users: [Types.ObjectId]; + platforms?: [Types.ObjectId]; +} + +export interface ICommunityUpdateBody { + name?: string; + avatarURL?: string; + users?: [Types.ObjectId]; + platforms?: [Types.ObjectId]; +} + +export interface CommunityModel extends Model { + paginate: (filter: object, options: object) => any; +} diff --git a/src/interfaces/Guild.interface.ts b/src/interfaces/Guild.interface.ts deleted file mode 100644 index 386403d..0000000 --- a/src/interfaces/Guild.interface.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { type Snowflake } from 'discord.js'; -import { type Model } from 'mongoose'; - -export interface IGuild { - guildId: Snowflake; - user: Snowflake; - name: string; - selectedChannels?: Array<{ - channelId: Snowflake; - channelName?: string; - }>; - period?: Date; - connectedAt: Date; - isDisconnected: boolean; - isInProgress: boolean; - icon: string | null; - window?: number[]; - action?: number[]; -} - -export interface IGuildUpdateBody { - selectedChannels?: Array<{ - channelId: Snowflake; - channelName?: string; - }>; - period?: Date; - isDisconnected?: boolean; - isInProgress?: boolean; - icon?: string | null; -} - -export interface GuildModel extends Model { - paginate: (filter: object, options: object) => any; -} diff --git a/src/interfaces/Platfrom.interface.ts b/src/interfaces/Platfrom.interface.ts new file mode 100644 index 0000000..38be003 --- /dev/null +++ b/src/interfaces/Platfrom.interface.ts @@ -0,0 +1,19 @@ +import { type Model, type Types } from 'mongoose'; + +export interface IPlatform { + name: string; + community: Types.ObjectId; + metadata?: Record; // dynamic object since structure can change + disconnectedAt?: Date | null; +} + +export interface IPlatformUpdateBody { + name?: string; + community?: Types.ObjectId; + metadata?: Record; + disconnectedAt?: Date | null; +} + +export interface PlatformModel extends Model { + paginate: (filter: object, options: object) => any; +} diff --git a/src/interfaces/User.interface.ts b/src/interfaces/User.interface.ts index 1f7555d..fa153c7 100644 --- a/src/interfaces/User.interface.ts +++ b/src/interfaces/User.interface.ts @@ -1,38 +1,15 @@ import { type Snowflake } from 'discord.js'; -import { type Model } from 'mongoose'; +import { type Model, type Types } from 'mongoose'; export interface IUser { discordId: Snowflake; - username?: string; - discriminator?: string; - avatar?: string; - bot?: boolean; - system?: boolean; - mfa_enabled?: boolean; - banner?: string; - accent_color?: number; - locale?: string; - verified?: boolean; email?: string; - flags?: number; - premium_type?: number; - public_flags?: number; - twitterId?: string | null; - twitterUsername?: string | null; - twitterProfileImageUrl?: string | null; - twitterConnectedAt?: Date | null; - twitterIsInProgress?: boolean | null; + communities?: [Types.ObjectId]; } export interface IUserUpdateBody { - avatar?: string; - twitterId?: string | null; - twitterUsername?: string | null; - twitterProfileImageUrl?: string | null; - twitterConnectedAt?: Date | null; - twitterIsInProgress?: boolean | null; email?: string; - verified?: boolean; + communities?: [Types.ObjectId]; } export interface UserModel extends Model { diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 69b6c38..61c7852 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -1,4 +1,3 @@ -export * from './Guild.interface'; export * from './RawInfo.interface'; export * from './HeatMap.interface'; export * from './Token.interface'; @@ -8,3 +7,5 @@ export * from './Channel.interface'; export * from './Role.interface'; export * from './User.interface'; export * from './Discord.interface'; +export * from './Community.interface'; +export * from './Platfrom.interface'; diff --git a/src/models/Community.model.ts b/src/models/Community.model.ts new file mode 100644 index 0000000..ad0fe1e --- /dev/null +++ b/src/models/Community.model.ts @@ -0,0 +1,5 @@ +import { model } from 'mongoose'; +import { communitySchema } from './schemas'; +import { type ICommunity } from '../interfaces'; + +export default model('Community', communitySchema); diff --git a/src/models/Guild.model.ts b/src/models/Guild.model.ts deleted file mode 100644 index 4c031fb..0000000 --- a/src/models/Guild.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { model } from 'mongoose'; -import { guildSchema } from './schemas'; -import { type IGuild, type GuildModel } from '../interfaces'; - -export default model('Guild', guildSchema); diff --git a/src/models/Platfrom.model.ts b/src/models/Platfrom.model.ts new file mode 100644 index 0000000..d3583cb --- /dev/null +++ b/src/models/Platfrom.model.ts @@ -0,0 +1,5 @@ +import { model } from 'mongoose'; +import { platformSchema } from './schemas'; +import { type IPlatform } from '../interfaces'; + +export default model('Platform', platformSchema); diff --git a/src/models/index.ts b/src/models/index.ts index d843e58..076f79b 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,11 +1,11 @@ import User from './User.model'; import Token from './Token.model'; -import Guild from './Guild.model'; import HeatMap from './HeatMap.model'; import RawInfo from './RawInfo.model'; import MemberActivity from './memberActivity.model'; import GuildMember from './GuildMember.model'; import Channel from './Channel.model'; import Role from './Role.model'; - -export { User, Token, Guild, HeatMap, RawInfo, MemberActivity, GuildMember, Channel, Role }; +import Community from './Community.model'; +import Platfrom from './Platfrom.model'; +export { User, Token, HeatMap, RawInfo, MemberActivity, GuildMember, Channel, Role, Community, Platfrom }; diff --git a/src/models/schemas/Community.schema.ts b/src/models/schemas/Community.schema.ts new file mode 100644 index 0000000..b18c012 --- /dev/null +++ b/src/models/schemas/Community.schema.ts @@ -0,0 +1,31 @@ +import { Schema } from 'mongoose'; +import { toJSON, paginate } from './plugins'; +import { type ICommunity, type CommunityModel } from '../../interfaces'; + +const communitySchema = new Schema( + { + name: { + type: String, + required: true, + maxlength: 50, + }, + avatarURL: { + type: String, + }, + users: [ + { + type: Schema.Types.ObjectId, + ref: 'User', + required: true, // A community must have at least one user + }, + ], + }, + + { timestamps: true }, +); + +// Plugins +communitySchema.plugin(toJSON); +communitySchema.plugin(paginate); + +export default communitySchema; diff --git a/src/models/schemas/Guild.schema.ts b/src/models/schemas/Guild.schema.ts deleted file mode 100644 index dd01b85..0000000 --- a/src/models/schemas/Guild.schema.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Schema } from 'mongoose'; -import { paginate, toJSON } from './plugins'; -import { type IGuild, type GuildModel } from '../../interfaces'; - -const guildSchema = new Schema({ - guildId: { - type: String, - required: true, - unique: true, - }, - user: { - type: String, - ref: 'User', - required: true, - }, - name: { - type: String, - }, - selectedChannels: [ - { - channelId: { - type: String, - }, - channelName: { - type: String, - }, - }, - ], - period: { - type: Date, - }, - connectedAt: { - type: Date, - default: new Date(), - }, - isInProgress: { - type: Boolean, - default: true, - }, - isDisconnected: { - type: Boolean, - default: false, - }, - icon: { - type: String, - }, - window: { - type: Array, - default: [7, 1], - validate: { - validator: function (arr: number[]) { - return arr.length === 2; - }, - message: 'Window must be an array with exactly 2 numbers', - }, - }, - action: { - type: Array, - default: [1, 1, 1, 4, 3, 5, 5, 4, 3, 2, 2, 2, 1], - validate: { - validator: function (arr: number[]) { - return arr.length === 13; - }, - message: 'Action must be an array with exactly 11 numbers', - }, - }, -}); - -// Plugins -guildSchema.plugin(toJSON); -guildSchema.plugin(paginate); - -export default guildSchema; diff --git a/src/models/schemas/Platform.schema.ts b/src/models/schemas/Platform.schema.ts new file mode 100644 index 0000000..3eab674 --- /dev/null +++ b/src/models/schemas/Platform.schema.ts @@ -0,0 +1,32 @@ +import { Schema } from 'mongoose'; +import { toJSON, paginate } from './plugins'; +import { type IPlatform, type PlatformModel } from '../../interfaces'; + +const platformSchema = new Schema( + { + name: { + type: String, + required: true, + }, + metadata: { + type: Schema.Types.Mixed, + }, + community: { + type: Schema.Types.ObjectId, + ref: 'Community', + required: true, + }, + disconnectedAt: { + type: Date, + default: null, + }, + }, + + { timestamps: true }, +); + +// Plugins +platformSchema.plugin(toJSON); +platformSchema.plugin(paginate); + +export default platformSchema; diff --git a/src/models/schemas/User.schema.ts b/src/models/schemas/User.schema.ts index 802b799..2d35d96 100644 --- a/src/models/schemas/User.schema.ts +++ b/src/models/schemas/User.schema.ts @@ -19,29 +19,12 @@ const userSchema = new Schema( }, unique: true, }, - verified: { - type: Boolean, - }, - avatar: { - type: String, - }, - twitterId: { - type: String, - }, - - twitterUsername: { - type: String, - }, - - twitterProfileImageUrl: { - type: String, - }, - twitterConnectedAt: { - type: Date, - }, - twitterIsInProgress: { - type: Boolean, - }, + communities: [ + { + type: Schema.Types.ObjectId, + ref: 'Community', + }, + ], }, { timestamps: true }, ); diff --git a/src/models/schemas/index.ts b/src/models/schemas/index.ts index efe38a0..85ca901 100644 --- a/src/models/schemas/index.ts +++ b/src/models/schemas/index.ts @@ -1,21 +1,23 @@ import userSchema from './User.schema'; import tokenSchema from './Token.schema'; -import guildSchema from './Guild.schema'; import heatMapSchema from './HeatMap.schema'; import rawInfoSchema from './RawInfo.schema'; import MemberActivitySchema from './MemberActivity.schema'; import guildMemberSchema from './GuildMember.schema'; import channelSchema from './Channel.schema'; import roleSchema from './Role.schema'; +import communitySchema from './Community.schema'; +import platformSchema from './Platform.schema'; export { userSchema, tokenSchema, - guildSchema, heatMapSchema, rawInfoSchema, MemberActivitySchema, guildMemberSchema, channelSchema, roleSchema, + communitySchema, + platformSchema, };