Dockerize Application
This commit is contained in:
parent
1d7d14bb85
commit
e9bc2958ad
8
frontend/.gitignore → .gitignore
vendored
8
frontend/.gitignore → .gitignore
vendored
@ -1,6 +1,12 @@
|
||||
.env
|
||||
|
||||
keys/
|
||||
node_modules/
|
||||
lib/
|
||||
logs/
|
||||
upload/
|
||||
|
||||
.DS_STORE
|
||||
node_modules
|
||||
scripts/flow/*/.flowconfig
|
||||
.flowconfig
|
||||
*~
|
28
README.md
28
README.md
@ -61,3 +61,31 @@ These setup instructions are in a primitive state, and may be improved in the fu
|
||||
|
||||
> Want a more basic version, that's more like Discord?
|
||||
> https://github.com/codea-live/dclone
|
||||
|
||||
---
|
||||
|
||||
`backend/.env`
|
||||
(dev with Docker)
|
||||
|
||||
```
|
||||
EMAIL_ADDRESS="...@gmail.com"
|
||||
EMAIL_PASSWORD="..."
|
||||
MONGO_URI="mongodb://database/accord"
|
||||
NODE_ENV="dev"
|
||||
PORT=3000
|
||||
WEBSITE_URL="http://localhost:4200"
|
||||
```
|
||||
|
||||
`backend/test/.env`
|
||||
(test without Docker)
|
||||
|
||||
```
|
||||
API_URL="http://localhost:3001/api"
|
||||
EMAIL_ADDRESS="...@gmail.com"
|
||||
EMAIL_PASSWORD="..."
|
||||
MONGO_URI="mongodb://localhost/accord-test"
|
||||
NODE_ENV="dev"
|
||||
PORT=3001
|
||||
ROOT_ENDPOINT="http://localhost:3001"
|
||||
WEBSITE_URL="http://localhost:4200"
|
||||
```
|
||||
|
1
backend/.dockerignore
Symbolic link
1
backend/.dockerignore
Symbolic link
@ -0,0 +1 @@
|
||||
../.gitignore
|
@ -1,7 +0,0 @@
|
||||
API_URL="http://localhost:3000"
|
||||
EMAIL_ADDRESS="example@gmail.com"
|
||||
EMAIL_PASSWORD="google_account_password"
|
||||
MONGO_URI="mongodb://localhost/accord"
|
||||
PORT=3000
|
||||
ROOT_ENDPOINT="http://localhost:3000"
|
||||
WEBSITE_URL="http://localhost:4200"
|
7
backend/.gitignore
vendored
7
backend/.gitignore
vendored
@ -1,7 +0,0 @@
|
||||
.env
|
||||
|
||||
keys/
|
||||
node_modules/
|
||||
lib/
|
||||
logs/
|
||||
upload/
|
13
backend/Dockerfile
Normal file
13
backend/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM node:16-alpine3.14
|
||||
RUN addgroup app && adduser -SG app app
|
||||
|
||||
WORKDIR /app
|
||||
COPY --chown=app:app package*.json ./
|
||||
RUN npm i
|
||||
COPY . .
|
||||
RUN unlink /app/src/types
|
||||
COPY --chown=app:app --from=accord_types:latest /app /app/src/types
|
||||
|
||||
EXPOSE 3000
|
||||
USER app
|
||||
CMD npm run start:dev
|
196
backend/package-lock.json
generated
196
backend/package-lock.json
generated
@ -7,9 +7,9 @@
|
||||
"": {
|
||||
"name": "accord-backend",
|
||||
"version": "0.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@accord/ion": "github:accord-dot-app/ion",
|
||||
"@accord/types": "file:../types",
|
||||
"body-parser": "^1.19.0",
|
||||
"chai-things": "^0.2.0",
|
||||
"colors": "^1.4.0",
|
||||
@ -75,12 +75,14 @@
|
||||
"mocha": "^8.2.1",
|
||||
"nodemon": "^2.0.14",
|
||||
"supertest": "^6.1.3",
|
||||
"ts-mocha": "^8.0.0"
|
||||
"ts-mocha": "^8.0.0",
|
||||
"ts-node-dev": "^1.1.8"
|
||||
}
|
||||
},
|
||||
"../types": {},
|
||||
"node_modules/@accord/ion": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "git+ssh://git@github.com/accord-dot-app/ion.git#c77ed01bbea93eeeff858004a7f6c6287a6d43de",
|
||||
"version": "1.0.2",
|
||||
"resolved": "git+ssh://git@github.com/accord-dot-app/ion.git#ea5ce8d2e2073e0260476f0ec96c6603fc502fd3",
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@ -276,6 +278,10 @@
|
||||
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz",
|
||||
"integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw=="
|
||||
},
|
||||
"node_modules/@accord/types": {
|
||||
"resolved": "../types",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.12.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
|
||||
@ -829,6 +835,18 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/strip-json-comments": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
|
||||
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/superagent": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.10.tgz",
|
||||
@ -2105,6 +2123,15 @@
|
||||
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dynamic-dedupe": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
|
||||
"integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
@ -5640,7 +5667,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
|
||||
"optional": true,
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
@ -5946,6 +5973,15 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tree-kill": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/triple-beam": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||
@ -6041,6 +6077,64 @@
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node-dev": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz",
|
||||
"integrity": "sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^3.5.1",
|
||||
"dynamic-dedupe": "^0.3.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"resolve": "^1.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"source-map-support": "^0.5.12",
|
||||
"tree-kill": "^1.2.2",
|
||||
"ts-node": "^9.0.0",
|
||||
"tsconfig": "^7.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"ts-node-dev": "lib/bin.js",
|
||||
"tsnd": "lib/bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"node-notifier": "*",
|
||||
"typescript": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"node-notifier": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node-dev/node_modules/rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
|
||||
"integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/strip-bom": "^3.0.0",
|
||||
"@types/strip-json-comments": "0.0.30",
|
||||
"strip-bom": "^3.0.0",
|
||||
"strip-json-comments": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz",
|
||||
@ -6053,6 +6147,15 @@
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig/node_modules/strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
||||
@ -6664,7 +6767,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@accord/ion": {
|
||||
"version": "git+ssh://git@github.com/accord-dot-app/ion.git#c77ed01bbea93eeeff858004a7f6c6287a6d43de",
|
||||
"version": "git+ssh://git@github.com/accord-dot-app/ion.git#ea5ce8d2e2073e0260476f0ec96c6603fc502fd3",
|
||||
"from": "@accord/ion@github:accord-dot-app/ion",
|
||||
"requires": {
|
||||
"@accord/ion": "github:accord-dot-app/ion",
|
||||
@ -6812,6 +6915,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@accord/types": {
|
||||
"version": "file:../types"
|
||||
},
|
||||
"@babel/helper-validator-identifier": {
|
||||
"version": "7.12.11",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
|
||||
@ -7339,6 +7445,18 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/strip-json-comments": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
|
||||
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/superagent": {
|
||||
"version": "4.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.10.tgz",
|
||||
@ -8357,6 +8475,15 @@
|
||||
"integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=",
|
||||
"dev": true
|
||||
},
|
||||
"dynamic-dedupe": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
|
||||
"integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"ecdsa-sig-formatter": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||
@ -11150,7 +11277,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
|
||||
"optional": true
|
||||
"devOptional": true
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
@ -11384,6 +11511,12 @@
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true
|
||||
},
|
||||
"triple-beam": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
|
||||
@ -11446,6 +11579,55 @@
|
||||
"yn": "3.1.1"
|
||||
}
|
||||
},
|
||||
"ts-node-dev": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz",
|
||||
"integrity": "sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": "^3.5.1",
|
||||
"dynamic-dedupe": "^0.3.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"resolve": "^1.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"source-map-support": "^0.5.12",
|
||||
"tree-kill": "^1.2.2",
|
||||
"ts-node": "^9.0.0",
|
||||
"tsconfig": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tsconfig": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
|
||||
"integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/strip-bom": "^3.0.0",
|
||||
"@types/strip-json-comments": "0.0.30",
|
||||
"strip-bom": "^3.0.0",
|
||||
"strip-json-comments": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tsconfig-paths": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz",
|
||||
|
@ -4,15 +4,16 @@
|
||||
"description": "",
|
||||
"main": "src/app.ts",
|
||||
"scripts": {
|
||||
"start": "ts-node src/app.ts",
|
||||
"dev": "ts-node-dev --transpile-only src/app.ts",
|
||||
"debug": "nodemon --exec 'node --inspect=0.0.0.0:9229 --require ts-node/register src/app.ts' --ext 'ts,yml'",
|
||||
"test": "ts-mocha --exit test/test.ts",
|
||||
"test:unit": "ts-mocha test/**/**.test.ts"
|
||||
"start": "npm run start:dev",
|
||||
"start:dev": "ts-node-dev --transpile-only src/app.ts",
|
||||
"start:debug": "nodemon --exec 'node --inspect=0.0.0.0:9229 --require ts-node/register src/app.ts' --ext 'ts,yml'",
|
||||
"start:prod": "ts-node-transpile-only src/app.ts",
|
||||
"test": "npm run test:int test:unit",
|
||||
"test:int": "ts-mocha test/int/test.ts",
|
||||
"test:unit": "ts-mocha --exit test/**/**.test.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "ADAMJR",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@accord/ion": "github:accord-dot-app/ion",
|
||||
"body-parser": "^1.19.0",
|
||||
@ -80,6 +81,7 @@
|
||||
"mocha": "^8.2.1",
|
||||
"nodemon": "^2.0.14",
|
||||
"supertest": "^6.1.3",
|
||||
"ts-mocha": "^8.0.0"
|
||||
"ts-mocha": "^8.0.0",
|
||||
"ts-node-dev": "^1.1.8"
|
||||
}
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ connect(process.env.MONGO_URI, {
|
||||
}, (error) => (error)
|
||||
? log.error(error.message, { uri: process.env.MONGO_URI })
|
||||
: log.info('Connected to database.', { uri: process.env.MONGO_URI })
|
||||
)
|
||||
)
|
@ -1,7 +1,5 @@
|
||||
import { APIError } from '../rest/modules/api-error';
|
||||
import { WS } from '../types/ws';
|
||||
import DBWrapper from './db-wrapper';
|
||||
import { Guild } from './models/guild';
|
||||
import { Invite, InviteDocument } from './models/invite';
|
||||
import generateInvite from './utils/generate-invite';
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import cluster from 'cluster';
|
||||
import patterns from '../types/patterns';
|
||||
|
||||
let inc = 0;
|
||||
let lastSnowflake: string;
|
||||
@ -36,6 +37,9 @@ function binary64(val: string) {
|
||||
// what this method does
|
||||
// -> https://discord.com/developers/docs/reference#convert-snowflake-to-datetime
|
||||
export function snowflakeToDate(snowflake: string) {
|
||||
if (!patterns.snowflake.test(snowflake))
|
||||
throw new TypeError('Invalid snowflake provided');
|
||||
|
||||
const sinceEpochMs = Number(
|
||||
binary64(snowflake).slice(0, 42 + 2)
|
||||
);
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { Router } from 'express';
|
||||
import { SelfUserDocument } from '../../data/models/user';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { APIError } from '../modules/api-error';
|
||||
import updateUser from '../middleware/update-user';
|
||||
import validateUser from '../middleware/validate-user';
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
export class WSCooldowns {
|
||||
public readonly active = new Map<string, EventLog[]>();
|
||||
|
||||
|
@ -3,10 +3,7 @@ import { Server as SocketServer } from 'socket.io';
|
||||
import { WSEvent } from './ws-events/ws-event';
|
||||
import { resolve } from 'path';
|
||||
import { readdirSync } from 'fs';
|
||||
import { WSCooldowns } from './modules/ws-cooldowns';
|
||||
|
||||
import { SessionManager } from './modules/session-manager';
|
||||
import { WS } from '../types/ws';
|
||||
|
||||
export class WebSocket {
|
||||
public events = new Map<keyof WS.To, WSEvent<keyof WS.To>>();
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import Channels from '../../data/channels';
|
||||
import { Guild } from '../../data/models/guild';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent } from './ws-event';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import { WS } from '../../types/ws';
|
||||
import { User } from '../../data/models/user';
|
||||
import { Channel, ChannelDocument } from '../../data/models/channel';
|
||||
|
||||
@ -16,13 +15,15 @@ export default class implements WSEvent<'CHANNEL_DELETE'> {
|
||||
{ voice: { channelId } },
|
||||
{ voice: {} },
|
||||
);
|
||||
ws.io.sockets.in(channelId).socketsLeave(channelId);
|
||||
ws.io.sockets
|
||||
.in(channelId)
|
||||
.socketsLeave(channelId);
|
||||
|
||||
await channel.deleteOne();
|
||||
await this.lowerHigherChannels(channel);
|
||||
|
||||
return [{
|
||||
emit: 'CHANNEL_DELETE',
|
||||
emit: this.on,
|
||||
to: [channel.guildId],
|
||||
send: { channelId, guildId: channel.guildId },
|
||||
}];
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { WS } from '../../types/ws';
|
||||
import { WSEvent } from './ws-event';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { Socket } from 'socket.io';
|
||||
|
@ -1,12 +1,6 @@
|
||||
import Channels from '../../data/channels';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WSEvent } from './ws-event';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { Socket } from 'socket.io';
|
||||
import { VoiceService } from '../../voice/voice-service';
|
||||
import Users from '../../data/users';
|
||||
import { SelfUserDocument } from '../../data/models/user';
|
||||
import { ChannelDocument } from '../../data/models/channel';
|
||||
|
||||
|
@ -2,7 +2,6 @@ import { Socket } from 'socket.io';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import { Channel, ChannelDocument } from '../../data/models/channel';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
export default class implements WSEvent<'CHANNEL_UPDATE'> {
|
||||
on = 'CHANNEL_UPDATE' as const;
|
||||
|
@ -1,28 +1,18 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import Channels from '../../data/channels';
|
||||
import { SelfUserDocument, UserDocument } from '../../data/models/user';
|
||||
import Users from '../../data/users';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
import ChannelLeave from './channel-leave';
|
||||
import { WSEvent } from './ws-event';
|
||||
|
||||
export default class implements WSEvent<'disconnect'> {
|
||||
on = 'disconnect' as const;
|
||||
|
||||
constructor(
|
||||
private channelLeaveEvent = deps.channelLeave,
|
||||
private users = deps.users,
|
||||
) {}
|
||||
|
||||
public async invoke(ws: WebSocket, client: Socket) {
|
||||
const userId = ws.sessions.get(client.id);
|
||||
const user = await this.users.getSelf(userId);
|
||||
const user = await deps.users.getSelf(userId);
|
||||
|
||||
|
||||
try {
|
||||
await this.channelLeaveEvent.invoke(ws, client);
|
||||
await deps.channelLeaveEvent.invoke(ws, client);
|
||||
} catch {}
|
||||
|
||||
ws.sessions.delete(client.id);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent } from './ws-event';
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { Invite } from '../../data/models/invite';
|
||||
import { Message } from '../../data/models/message';
|
||||
import { Role } from '../../data/models/role';
|
||||
import { User } from '../../data/models/user';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
|
@ -2,7 +2,7 @@ import { Socket } from 'socket.io';
|
||||
import { GuildDocument } from '../../data/models/guild';
|
||||
import { InviteDocument } from '../../data/models/invite';
|
||||
import { SelfUserDocument } from '../../data/models/user';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { GuildMember } from '../../data/models/guild-member';
|
||||
import { SelfUserDocument, User } from '../../data/models/user';
|
||||
import Users from '../../data/users';
|
||||
import { PermissionTypes } from '../../types/permission-types';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
|
@ -2,7 +2,7 @@ import { Socket } from 'socket.io';
|
||||
import GuildMembers from '../../data/guild-members';
|
||||
import Guilds from '../../data/guilds';
|
||||
import Roles from '../../data/roles';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
|
@ -8,7 +8,7 @@ import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import Roles from '../../data/roles';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
export default class implements WSEvent<'GUILD_ROLE_CREATE'> {
|
||||
on = 'GUILD_ROLE_CREATE' as const;
|
||||
|
@ -6,7 +6,7 @@ import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import { GuildMember } from '../../data/models/guild-member';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import Roles from '../../data/roles';
|
||||
|
||||
export default class implements WSEvent<'GUILD_ROLE_DELETE'> {
|
||||
|
@ -3,7 +3,7 @@ import { Socket } from 'socket.io';
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import Roles from '../../data/roles';
|
||||
import Guilds from '../../data/guilds';
|
||||
import GuildMembers from '../../data/guild-members';
|
||||
|
@ -3,7 +3,7 @@ import { Socket } from 'socket.io';
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
export default class implements WSEvent<'GUILD_UPDATE'> {
|
||||
on = 'GUILD_UPDATE' as const;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import Invites from '../../data/invites';
|
||||
import { PermissionTypes } from '../../types/permission-types';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { Channel } from '../../data/models/channel';
|
||||
import striptags from 'striptags';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { Message } from '../../data/models/message';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent } from './ws-event';
|
||||
|
||||
|
@ -6,7 +6,7 @@ import got from 'got';
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import Messages from '../../data/messages';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
export default class implements WSEvent<'MESSAGE_UPDATE'> {
|
||||
on = 'MESSAGE_UPDATE' as const;
|
||||
|
@ -2,7 +2,7 @@ import { Socket } from 'socket.io';
|
||||
import Channels from '../../data/channels';
|
||||
import { SelfUserDocument } from '../../data/models/user';
|
||||
import Users from '../../data/users';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WSRooms } from '../modules/ws-rooms';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WSEvent, } from './ws-event';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { WSEvent } from './ws-event';
|
||||
import { Socket } from 'socket.io';
|
||||
import { WebSocket } from '../websocket';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import generateInvite from '../../data/utils/generate-invite';
|
||||
|
||||
export default class implements WSEvent<'USER_DELETE'> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import Users from '../../data/users';
|
||||
import { EmailFunctions } from '../../email/email-functions';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { WSGuard } from '../modules/ws-guard';
|
||||
import { WebSocket } from '../websocket';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
|
||||
import { VoiceService } from '../../voice/voice-service';
|
||||
import { WebSocket } from '../websocket';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Socket } from 'socket.io';
|
||||
import { WS } from '../../types/ws';
|
||||
|
||||
import { WebSocket } from '../websocket';
|
||||
|
||||
type OnWS = WS.To & WS.On;
|
||||
|
@ -1,8 +0,0 @@
|
||||
# Special .env for integration testing. Rename to '.env'.
|
||||
API_URL="http://localhost:3001/api"
|
||||
EMAIL_ADDRESS="example@gmail.com"
|
||||
EMAIL_PASSWORD="google_account_password"
|
||||
MONGO_URI="mongodb://localhost/accord-test"
|
||||
PORT=3001
|
||||
ROOT_ENDPOINT="http://localhost:3001"
|
||||
WEBSITE_URL="http://localhost:4200"
|
@ -22,16 +22,6 @@ use(should);
|
||||
useFindAndModify: false,
|
||||
useCreateIndex: true,
|
||||
});
|
||||
|
||||
try {
|
||||
execSync(`kill -9 $(lsof -i :${process.env.PORT} | tail -n 1 | cut -d ' ' -f5) 2>> /dev/null`);
|
||||
} catch {}
|
||||
|
||||
await import('./ws/channel-delete.tests');
|
||||
})();
|
||||
|
||||
/**
|
||||
* e2e: testing the final product (i.e. app)
|
||||
* integration: testing full unit with dependencies
|
||||
* unit: testing one unit (i.e. one class, function etc.) - mocks dependencies
|
||||
*/
|
||||
import('./ws/channel-delete.test');
|
@ -1,18 +1,15 @@
|
||||
import ChannelDelete from '../../../src/ws/ws-events/channel-delete';
|
||||
import { given, test } from '@accord/ion';
|
||||
import { WebSocket } from '../../../src/ws/websocket';
|
||||
import { WS } from '../../../src/types/ws';
|
||||
|
||||
test(channelDelete, () => {
|
||||
before(() => console.log('before'));
|
||||
|
||||
given({}).rejectWith('Channel not found');
|
||||
|
||||
after(() => console.log('after'));
|
||||
given({}).rejectWith('Channel not found');
|
||||
});
|
||||
|
||||
async function channelDelete(args: WS.To['CHANNEL_DELETE']) {
|
||||
await import('../../../src/modules/deps');
|
||||
console.error = () => {};
|
||||
global['log'] = console;
|
||||
|
||||
const event = new ChannelDelete();
|
@ -15,7 +15,7 @@ describe('snowflake-entity', () => {
|
||||
});
|
||||
|
||||
test(snowflakeToDate, () => {
|
||||
given(generateSnowflake())
|
||||
.assert(d => d.toString() === new Date().toString());
|
||||
given(generateSnowflake()).assert(d => d.toString() === new Date().toString());
|
||||
given('invalid snowflake').throw('Invalid snowflake provided');
|
||||
});
|
||||
});
|
||||
|
22
docker-compose.dev.yml
Normal file
22
docker-compose.dev.yml
Normal file
@ -0,0 +1,22 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
database:
|
||||
image: mongo:4.4-focal
|
||||
ports: [27018:27017]
|
||||
volumes: [accord:/data/db]
|
||||
types:
|
||||
build: ./types
|
||||
backend:
|
||||
depends_on: [database]
|
||||
build: ./backend
|
||||
ports: [3000:3000]
|
||||
env_file: [./backend/.env]
|
||||
volumes: [./backend:/app]
|
||||
frontend:
|
||||
depends_on: [database]
|
||||
build: ./frontend
|
||||
ports: [4200:4200]
|
||||
env_file: [./frontend/env/.env.dev]
|
||||
volumes: [./frontend:/app]
|
||||
volumes:
|
||||
accord:
|
16
docker-compose.prod.yml
Normal file
16
docker-compose.prod.yml
Normal file
@ -0,0 +1,16 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
database:
|
||||
image: mongo:4.4-focal
|
||||
ports: [27017:27017]
|
||||
volumes: [accord:/data/db]
|
||||
types:
|
||||
build: ./types
|
||||
backend:
|
||||
depends_on: [database]
|
||||
build: ./backend
|
||||
ports: [3000:3000]
|
||||
env_file: [./backend/.env]
|
||||
volumes: [./backend:/app]
|
||||
volumes:
|
||||
accord:
|
1
frontend/.dockerignore
Symbolic link
1
frontend/.dockerignore
Symbolic link
@ -0,0 +1 @@
|
||||
../.gitignore
|
13
frontend/Dockerfile
Normal file
13
frontend/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM node:16-alpine3.14
|
||||
RUN addgroup app && adduser -SG app app
|
||||
|
||||
WORKDIR /app
|
||||
COPY --chown=app:app package*.json ./
|
||||
RUN npm i
|
||||
COPY . .
|
||||
RUN unlink /app/src/types
|
||||
COPY --chown=app:app --from=accord_types:latest /app /app/src/types
|
||||
|
||||
EXPOSE 4200
|
||||
USER app
|
||||
CMD npm run start:dev
|
5
frontend/env/.env.dev
vendored
Normal file
5
frontend/env/.env.dev
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
PORT=4200
|
||||
REACT_APP_API_URL="backend/v2"
|
||||
REACT_APP_CDN_URL="backend/assets"
|
||||
REACT_APP_REPO="https://github.com/accord-dot-app/app"
|
||||
REACT_APP_ROOT_API_URL="backend"
|
@ -48,10 +48,11 @@
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "dotenv -e src/env/.env.dev craco start",
|
||||
"start:prod": "dotenv -e src/env/.env.prod craco start",
|
||||
"build:dev": "dotenv -e src/env/.env.dev craco build",
|
||||
"build:prod": "dotenv -e src/env/.env.prod craco build",
|
||||
"start": "npm run start:dev",
|
||||
"start:dev": "craco start",
|
||||
"start:prod": "craco start",
|
||||
"build:dev": "dotenv -e env/.env.dev craco build",
|
||||
"build:prod": "dotenv -e env/.env.prod craco build",
|
||||
"test": "craco test",
|
||||
"test:unit": "craco test --watchAll=false",
|
||||
"test:e2e": "cypress open",
|
||||
|
5
frontend/src/env/.env.dev
vendored
5
frontend/src/env/.env.dev
vendored
@ -1,5 +0,0 @@
|
||||
PORT=4200
|
||||
REACT_APP_API_URL="http://localhost:3000/v2"
|
||||
REACT_APP_CDN_URL="http://localhost:3000/assets"
|
||||
REACT_APP_REPO="https://github.com/accord-dot-app/app"
|
||||
REACT_APP_ROOT_API_URL="http://localhost:3000"
|
@ -1,5 +1,4 @@
|
||||
import io from 'socket.io-client';
|
||||
import { WS } from '../types/ws';
|
||||
|
||||
const ws = (io as any).connect(process.env.REACT_APP_ROOT_API_URL, {
|
||||
secure: true,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { headers } from './utils/rest-headers';
|
||||
|
||||
export const actions = {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api } from './api';
|
||||
import { openDialog } from './ui';
|
||||
import { headers, token } from './utils/rest-headers';
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createSelector, createSlice } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api } from './api';
|
||||
import { notInArray } from './utils/filter';
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { createSelector, createSlice } from '@reduxjs/toolkit';
|
||||
import { byAscending } from '../components/utils/vanilla/sort';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api, uploadFile } from './api';
|
||||
import { notInArray } from './utils/filter';
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api } from './api';
|
||||
import { notInArray } from './utils/filter';
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createSelector, createSlice } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api } from './api';
|
||||
import { notInArray } from './utils/filter';
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createSlice, createSelector } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api, uploadFile } from './api';
|
||||
import { notInArray } from './utils/filter';
|
||||
import { headers } from './utils/rest-headers';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { createSelector, createSlice } from '@reduxjs/toolkit';
|
||||
import { notInArray } from './utils/filter';
|
||||
import { actions as api } from './api';
|
||||
import { WS } from '../types/ws';
|
||||
import { byMax } from './utils/reduce';
|
||||
|
||||
const slice = createSlice({
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { createSlice, createSelector } from '@reduxjs/toolkit';
|
||||
import { WS } from '../types/ws';
|
||||
import { actions as api, uploadFile } from './api';
|
||||
import { actions as meta } from './meta';
|
||||
import { notInArray } from './utils/filter';
|
||||
|
10
package.json
Normal file
10
package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"scripts": {
|
||||
"dc:up": "sudo docker-compose -f docker-compose.dev.yml up -d",
|
||||
"dc:down": "sudo docker-compose -f docker-compose.dev.yml down",
|
||||
"dc:ps": "sudo docker-compose -f docker-compose.dev.yml ps",
|
||||
"dc:build": "sudo docker-compose -f docker-compose.prod.yml build",
|
||||
"log:f": "sudo docker-compose -f docker-compose.dev.yml logs backend",
|
||||
"log:b": "sudo docker-compose -f docker-compose.dev.yml logs frontend"
|
||||
}
|
||||
}
|
4
types/Dockerfile
Normal file
4
types/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM node:16-alpine3.14
|
||||
|
||||
WORKDIR /app
|
||||
COPY . .
|
10
types/ws.d.ts
vendored
10
types/ws.d.ts
vendored
@ -376,14 +376,4 @@ declare namespace WS {
|
||||
voice: UserTypes.VoiceState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated In process of being replaced with Partial. */
|
||||
// FIXME: Removing this breaks react.
|
||||
export namespace PartialEntity {
|
||||
export type Guild = Partial<Entity.Guild>;
|
||||
export type GuildMember = Partial<Entity.GuildMember>;
|
||||
export type Message = Partial<Entity.Message>;
|
||||
export type Role = Partial<Entity.Role>;
|
||||
export type User = Partial<UserTypes.Self>;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user