diff --git a/Common/Models/Index.ts b/Common/Models/Index.ts index 22afd6b24b..decdf38337 100644 --- a/Common/Models/Index.ts +++ b/Common/Models/Index.ts @@ -1,5 +1,6 @@ -import User from './User'; +// import User from './User'; +import Probe from './Probe'; export default [ - User + Probe ] \ No newline at end of file diff --git a/Common/Models/Probe.ts b/Common/Models/Probe.ts index 4bc21675b4..d8088b5890 100755 --- a/Common/Models/Probe.ts +++ b/Common/Models/Probe.ts @@ -19,7 +19,7 @@ export default class Probe extends BaseModel { type: 'text', nullable: false, unique: true, - // transformer: ObjectID.getDatabaseTransformer() + transformer: ObjectID.getDatabaseTransformer() }) public key!: ObjectID; @@ -33,7 +33,11 @@ export default class Probe extends BaseModel { public slug!: string; @RequiredColumn() - @Column({ nullable: false }) + @Column({ + nullable: false, + type: "text", + transformer: Version.getDatabaseTransformer() + }) public probeVersion!: Version; @RequiredColumn() diff --git a/Common/Types/AppEnvironment.ts b/Common/Types/AppEnvironment.ts new file mode 100644 index 0000000000..0076918172 --- /dev/null +++ b/Common/Types/AppEnvironment.ts @@ -0,0 +1,8 @@ +enum AppEnvironment { + Production = "production", + Development = "development", + Test = "test" +} + + +export default AppEnvironment; \ No newline at end of file diff --git a/Common/Types/DatabaseProperty.ts b/Common/Types/DatabaseProperty.ts index 2607924493..d737b976d8 100644 --- a/Common/Types/DatabaseProperty.ts +++ b/Common/Types/DatabaseProperty.ts @@ -1,3 +1,4 @@ +import { FindOperator } from "typeorm"; import { ValueTransformer } from "typeorm/decorator/options/ValueTransformer"; import NotImplementedException from "./Exception/NotImplementedException"; @@ -6,7 +7,18 @@ export default class DatabaseProperty { } - public static getDatabaseTransformer(): ValueTransformer { + protected static fromDatabase(_value: string | number): DatabaseProperty { throw new NotImplementedException(); } + + protected static toDatabase(_value: DatabaseProperty | FindOperator): string | number { + throw new NotImplementedException(); + } + + public static getDatabaseTransformer(): ValueTransformer { + return { + to: this.toDatabase, + from: this.fromDatabase + }; + } } \ No newline at end of file diff --git a/Common/Types/DatabaseType.ts b/Common/Types/DatabaseType.ts new file mode 100644 index 0000000000..cfff74214f --- /dev/null +++ b/Common/Types/DatabaseType.ts @@ -0,0 +1,6 @@ +enum DatabaseType { + Postgres = "postgres" +} + + +export default DatabaseType; \ No newline at end of file diff --git a/Common/Types/Exception/DatabaseNotConnectedException.ts b/Common/Types/Exception/DatabaseNotConnectedException.ts new file mode 100644 index 0000000000..5da4aabd6f --- /dev/null +++ b/Common/Types/Exception/DatabaseNotConnectedException.ts @@ -0,0 +1,11 @@ +import Exception from './Exception'; +import ExceptionCode from './ExceptionCode'; + +export default class DatabaseNotConnectedException extends Exception { + public constructor() { + super( + ExceptionCode.DatabaseNotConnected, + 'Database not connected' + ); + } +} diff --git a/Common/Types/Exception/ExceptionCode.ts b/Common/Types/Exception/ExceptionCode.ts index 3446d03c8f..135633b4e1 100644 --- a/Common/Types/Exception/ExceptionCode.ts +++ b/Common/Types/Exception/ExceptionCode.ts @@ -2,6 +2,7 @@ enum ExceptionCode { NotImplementedException = 0, GeneralException = 1, APIException = 2, + DatabaseNotConnected = 3, BadDataException = 400, } diff --git a/Common/Types/ObjectID.ts b/Common/Types/ObjectID.ts index e4ce34ded5..00cd93fc60 100644 --- a/Common/Types/ObjectID.ts +++ b/Common/Types/ObjectID.ts @@ -1,5 +1,5 @@ // This is for Object ID for all the things in our database. -import { FindOperator, ValueTransformer } from 'typeorm'; +import { FindOperator } from 'typeorm'; import UUID from '../Utils/UUID'; import DatabaseProperty from './DatabaseProperty'; @@ -25,17 +25,11 @@ export default class ObjectID extends DatabaseProperty { return new this(UUID.generate()); } - public static override getDatabaseTransformer(): ValueTransformer { - return { - to(value: ObjectID | FindOperator): string { - if (value instanceof FindOperator) { - return value.value.toString(); - } - return value.toString(); - }, - from(value: string): ObjectID { - return new ObjectID(value); - } - }; + protected static override toDatabase(_value: ObjectID | FindOperator): string { + return _value.toString(); + } + + protected static override fromDatabase(_value: string): ObjectID { + return new ObjectID(_value); } } diff --git a/Common/Types/Version.ts b/Common/Types/Version.ts index ab301e5020..b3676acfb1 100644 --- a/Common/Types/Version.ts +++ b/Common/Types/Version.ts @@ -1,3 +1,4 @@ +import { FindOperator } from 'typeorm'; import DatabaseProperty from './DatabaseProperty'; import BadDataException from './Exception/BadDataException'; @@ -24,4 +25,12 @@ export default class Version extends DatabaseProperty { public override toString(): string { return this.version; } + + protected static override toDatabase(_value: Version | FindOperator): string { + return _value.toString(); + } + + protected static override fromDatabase(_value: string): Version { + return new Version(_value); + } } diff --git a/CommonServer/.env b/CommonServer/.env new file mode 100644 index 0000000000..7e54d1af0a --- /dev/null +++ b/CommonServer/.env @@ -0,0 +1,6 @@ +CLUSTER_KEY=cluster-test +DATABASE_PORT=5400 +DATABASE_USERNAME=postgres +DATABASE_PASSWORD=postgres +DATABASE_NAME=oneuptimedb +ENCRYPTIOJN_SECRET=encryption-test \ No newline at end of file diff --git a/CommonServer/Config.ts b/CommonServer/Config.ts index 9cdafe2c33..c89d90fbf7 100644 --- a/CommonServer/Config.ts +++ b/CommonServer/Config.ts @@ -7,7 +7,7 @@ export const DatabaseHost: Hostname = new Hostname( process.env['DATABASE_HOST'] || '' ); -export const DatabasePort: Port = new Port(process.env['DATABASE_Port'] || ''); +export const DatabasePort: Port = new Port(process.env['DATABASE_PORT'] || ''); export const DatabaseUsername: string = process.env['DATABASE_USERNAME'] || 'oneuptimedbuser'; @@ -43,9 +43,10 @@ export const DataIngestorHostname: Hostname = new Hostname( process.env['DATA_INGESTOR_HOSTNAME'] || '' ); -export const Version: string = process.env['npm_package_version'] || ''; +export const Env: string = + process.env['NODE_ENV'] || '' -export const Env: string = process.env['NODE_ENV'] || ''; +export const Version: string = process.env['npm_package_version'] || ''; export const HttpProtocol: Protocol = ( process.env['HTTP_PROTOCOL'] || '' diff --git a/CommonServer/Infrastructure/PostgresDatabase.ts b/CommonServer/Infrastructure/PostgresDatabase.ts index b0e5a4ae51..a29d333fdf 100644 --- a/CommonServer/Infrastructure/PostgresDatabase.ts +++ b/CommonServer/Infrastructure/PostgresDatabase.ts @@ -5,25 +5,31 @@ import { DatabasePassword, DatabasePort, DatabaseUsername, + Env, } from '../Config'; import Entities from 'Common/Models/Index'; +import AppEnvironment from 'Common/Types/AppEnvironment'; +import DatabaseType from 'Common/Types/DatabaseType'; -const PostgresDataSource: DataSource = new DataSource({ - type: 'postgres', +export const DataSourceOptions = { + type: DatabaseType.Postgres, host: DatabaseHost.toString(), port: DatabasePort.toNumber(), username: DatabaseUsername, password: DatabasePassword, database: DatabaseName, - entities: Entities -}); + entities: Entities, + synchronize: Env === AppEnvironment.Test || Env === AppEnvironment.Development +}; + +const PostgresDataSource: DataSource = new DataSource(DataSourceOptions); export default class Database { - private static dataSource: DataSource; + private static dataSource: DataSource | null; - public static getDataSource(): DataSource { + public static getDataSource(): DataSource | null { return this.dataSource; } @@ -34,4 +40,11 @@ export default class Database { this.dataSource = await PostgresDataSource.initialize(); return this.dataSource; } + + public static async disconnect(): Promise { + if (!this.getDataSource()) { + await this.getDataSource()?.destroy(); + this.dataSource = null; + } + } } diff --git a/CommonServer/Services/DatabaseService.ts b/CommonServer/Services/DatabaseService.ts index d8461ada16..4a149ddc6d 100644 --- a/CommonServer/Services/DatabaseService.ts +++ b/CommonServer/Services/DatabaseService.ts @@ -11,6 +11,7 @@ import UpdateBy from '../Types/DB/UpdateBy'; import Query from '../Types/DB/Query'; import CreateBy from '../Types/DB/CreateBy'; import BadDataException from 'Common/Types/Exception/BadDataException'; +import DatabaseNotConnectedException from 'Common/Types/Exception/DatabaseNotConnectedException'; import Exception from 'Common/Types/Exception/Exception'; import SearchResult from '../Types/DB/SearchResult'; import Encryption from '../Utils/Encryption'; @@ -31,8 +32,12 @@ class DatabaseService { } public getRepository(): Repository { - const dataSource: DataSource = PostgresDatabase.getDataSource(); - return dataSource.getRepository(this.entityName); + const dataSource: DataSource | null = PostgresDatabase.getDataSource(); + if (dataSource) { + return dataSource.getRepository(this.entityName); + } else { + throw new DatabaseNotConnectedException() + } } protected isValid(data: TBaseModel): boolean { @@ -60,7 +65,7 @@ class DatabaseService { } protected encrypt(data: TBaseModel): TBaseModel { - + const iv: Buffer = Encryption.getIV(); (data as any)['iv'] = iv; @@ -203,20 +208,16 @@ class DatabaseService { try { - for (const key in data) { - (data as any)(key, data[key]); - } - if (data.getSlugifyColumn()) { (data as any)['slug'] = Slug.getSlug( (data as any)[data.getSlugifyColumn() as string] as string ) } + const savedData = await this.getRepository().create(data); + await this.onCreateSuccess(savedData); + return savedData; - await this.onCreateSuccess(data); - - return await data.save(); } catch (error) { await this.onCreateError(error as Exception); throw this.getException(error as Exception); @@ -351,7 +352,7 @@ class DatabaseService { skip: onBeforeFind.skip.toNumber(), take: onBeforeFind.limit.toNumber(), where: onBeforeFind.query as any, - order: onBeforeFind.sort as any, + order: onBeforeFind.sort as any, relations: onBeforeFind.populate as any }); diff --git a/CommonServer/Tests/Services/ProbeService.test.ts b/CommonServer/Tests/Services/ProbeService.test.ts index 36dfd8e473..caedb1a9f3 100644 --- a/CommonServer/Tests/Services/ProbeService.test.ts +++ b/CommonServer/Tests/Services/ProbeService.test.ts @@ -1,3 +1,4 @@ +import '../TestingUtils/Init'; import ProbeService from '../../Services/ProbeService'; import Probe from 'Common/Models/Probe'; import Database from '../TestingUtils/Database'; @@ -5,9 +6,11 @@ import ObjectID from 'Common/Types/ObjectID'; import Version from 'Common/Types/Version'; describe('ProbeService', () => { + beforeAll(async () => { - await Database.connect(); - }) + await Database.createAndConnect(); + }); + test('create a new probe', async () => { const probe: Probe = new Probe(); @@ -18,8 +21,14 @@ describe('ProbeService', () => { expect(savedProbe.name).toEqual(probe.name); expect(savedProbe.probeVersion.toString()).toEqual(probe.probeVersion.toString()); - expect(probe.id).toBeTruthy(); + expect(probe.createdAt).toBeTruthy(); + expect(probe.version).toBeTruthy(); + expect(probe._id).toBeTruthy(); expect(probe.key.toString()).toEqual(probe.key.toString()); }); + + afterAll(async () => { + await Database.disconnectAndDropDatabase(); + }); }); diff --git a/CommonServer/Tests/TestingUtils/Database.ts b/CommonServer/Tests/TestingUtils/Database.ts index 7d17b2b101..e90612bc7d 100644 --- a/CommonServer/Tests/TestingUtils/Database.ts +++ b/CommonServer/Tests/TestingUtils/Database.ts @@ -1,11 +1,32 @@ -import PostgresDatabase from '../../Infrastructure/PostgresDatabase'; +import PostgresDatabase, { DataSourceOptions} from '../../Infrastructure/PostgresDatabase'; +import { dropDatabase, createDatabase } from 'typeorm-extension'; export default class DatabaseConnect { - public static async connect() { + public static async createAndConnect() { + await this.createDatabase(); + await this.connectDatabase(); + } + + public static async disconnectAndDropDatabase() { + await this.disconnectDatabase(); + await this.dropDatabase(); + } + + public static async createDatabase() { + await createDatabase({ + options: DataSourceOptions, + ifNotExist: true + }); + } + public static async connectDatabase() { await PostgresDatabase.connect(); } - public static async drop() { - // do ntohing + public static async disconnectDatabase() { + await PostgresDatabase.disconnect(); + } + + public static async dropDatabase() { + await PostgresDatabase.getDataSource()?.dropDatabase(); } } \ No newline at end of file diff --git a/CommonServer/Tests/TestingUtils/Init.ts b/CommonServer/Tests/TestingUtils/Init.ts new file mode 100644 index 0000000000..9b72c141c9 --- /dev/null +++ b/CommonServer/Tests/TestingUtils/Init.ts @@ -0,0 +1,2 @@ +process.env['NODE_ENV'] = 'test'; +import '../../Utils/Envrionment'; \ No newline at end of file diff --git a/CommonServer/Utils/Env.ts b/CommonServer/Utils/Env.ts deleted file mode 100644 index 930fe6114d..0000000000 --- a/CommonServer/Utils/Env.ts +++ /dev/null @@ -1,10 +0,0 @@ -import dotenv from 'dotenv'; -import { Env } from '../Config'; - -if (Env === 'development') { - /* - * Load env vars from /.env, do this only on development. - * Production values are supplied by Kubernetes Helm charts. - */ - dotenv.config(); -} diff --git a/CommonServer/Utils/Envrionment.ts b/CommonServer/Utils/Envrionment.ts new file mode 100644 index 0000000000..a624b1a681 --- /dev/null +++ b/CommonServer/Utils/Envrionment.ts @@ -0,0 +1,19 @@ +import dotenv from 'dotenv'; +import AppEnvironment from 'Common/Types/AppEnvironment'; + +const Env: string = process.env['NODE_ENV'] || ''; + + +if (Env === AppEnvironment.Development || Env === AppEnvironment.Test) { + /* + * Load env vars from /.env, do this only on development. + * Production values are supplied by Kubernetes Helm charts or docker compose files. + */ + dotenv.config(); + + if (Env === AppEnvironment.Test) { + dotenv.config({ + path: '../test.env' + }) + } +} diff --git a/CommonServer/Utils/StartServer.ts b/CommonServer/Utils/StartServer.ts index 0308ea0624..927a44c3e4 100644 --- a/CommonServer/Utils/StartServer.ts +++ b/CommonServer/Utils/StartServer.ts @@ -1,4 +1,4 @@ -import './Env'; +import './Envrionment'; import './Process'; import logger from './Logger'; import cors from 'cors'; diff --git a/CommonServer/jest.config.json b/CommonServer/jest.config.json index 156b5cd9e4..03e2b0db21 100644 --- a/CommonServer/jest.config.json +++ b/CommonServer/jest.config.json @@ -14,6 +14,7 @@ "testEnvironment": "node", "collectCoverage": true, "coverageReporters": ["text"], + "testRegex": "./Tests/(.*).test.ts", "collectCoverageFrom": ["./**/*.(tsx||ts)"], "coverageThreshold": { "global": { diff --git a/CommonServer/package-lock.json b/CommonServer/package-lock.json index 46cdca0782..c404fcfdf5 100644 --- a/CommonServer/package-lock.json +++ b/CommonServer/package-lock.json @@ -23,8 +23,10 @@ "node-device-detector": "^2.0.0", "nodemailer": "^6.7.3", "nodemailer-express-handlebars": "^5.0.0", + "pg": "^8.7.3", "socket.io": "^4.4.1", "typeorm": "^0.3.6", + "typeorm-extension": "^2.1.0", "winston": "^3.6.0" }, "devDependencies": { @@ -735,6 +737,15 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/@faker-js/faker": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-6.3.1.tgz", + "integrity": "sha512-8YXBE2ZcU/pImVOHX7MWrSR/X5up7t6rPWZlk34RwZEcdr3ua6X+32pSd6XuOQRN+vbuvYNfA6iey8NbrjuMFQ==", + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1109,6 +1120,33 @@ "node": ">= 6" } }, + "node_modules/@trapi/query": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@trapi/query/-/query-2.1.3.tgz", + "integrity": "sha512-qOG7X1BUlxJ339lsmA8voTCHzLEz0JPmBobXDzseg/nAeNMbkvRAAPq1itAM6yqqhEGFxuuYxsWM1Cn6qIwEMA==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/@trapi/query/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@trapi/query/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@types/babel__core": { "version": "7.1.19", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", @@ -1896,6 +1934,14 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -4703,6 +4749,11 @@ "node": ">=6" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -4784,6 +4835,80 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/pg": { + "version": "8.7.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz", + "integrity": "sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.5.1", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "pg-native": ">=2.0.0" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", + "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -4823,6 +4948,41 @@ "node": ">=8" } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -5325,6 +5485,14 @@ "memory-pager": "^1.0.2" } }, + "node_modules/split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -5835,6 +6003,62 @@ } } }, + "node_modules/typeorm-extension": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typeorm-extension/-/typeorm-extension-2.1.0.tgz", + "integrity": "sha512-ixnQRLnEVwetxRtVGmaTFPU5mE7sXbykBOrgQBL+/b7JtQnD6vx98+KpBOActFiuDYZjqI3irbp83TWwIiaTxQ==", + "dependencies": { + "@faker-js/faker": "^6.2.0", + "@trapi/query": "^2.1.2", + "glob": "^8.0.1", + "reflect-metadata": "^0.1.13", + "yargs": "^17.4.1" + }, + "bin": { + "typeorm-extension": "dist/cli/index.js" + }, + "peerDependencies": { + "typeorm": "~0.3.0" + } + }, + "node_modules/typeorm-extension/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typeorm-extension/node_modules/glob": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.1.tgz", + "integrity": "sha512-cF7FYZZ47YzmCu7dDy50xSRRfO3ErRfrXuLZcNIuyiJEco0XSrGtuilG19L5xp3NcwTx7Gn+X6Tv3fmsUPTbow==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm-extension/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/typeorm/node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -6197,6 +6421,14 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -6733,6 +6965,11 @@ } } }, + "@faker-js/faker": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-6.3.1.tgz", + "integrity": "sha512-8YXBE2ZcU/pImVOHX7MWrSR/X5up7t6rPWZlk34RwZEcdr3ua6X+32pSd6XuOQRN+vbuvYNfA6iey8NbrjuMFQ==" + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -7036,6 +7273,32 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, + "@trapi/query": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@trapi/query/-/query-2.1.3.tgz", + "integrity": "sha512-qOG7X1BUlxJ339lsmA8voTCHzLEz0JPmBobXDzseg/nAeNMbkvRAAPq1itAM6yqqhEGFxuuYxsWM1Cn6qIwEMA==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "@types/babel__core": { "version": "7.1.19", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", @@ -7693,6 +7956,11 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -9862,6 +10130,11 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9927,6 +10200,61 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "pg": { + "version": "8.7.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz", + "integrity": "sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.5.1", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", + "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", + "requires": {} + }, + "pg-protocol": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "requires": { + "split2": "^4.1.0" + } + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -9954,6 +10282,29 @@ "find-up": "^4.0.0" } }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -10330,6 +10681,11 @@ "memory-pager": "^1.0.2" } }, + "split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -10663,6 +11019,49 @@ } } }, + "typeorm-extension": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typeorm-extension/-/typeorm-extension-2.1.0.tgz", + "integrity": "sha512-ixnQRLnEVwetxRtVGmaTFPU5mE7sXbykBOrgQBL+/b7JtQnD6vx98+KpBOActFiuDYZjqI3irbp83TWwIiaTxQ==", + "requires": { + "@faker-js/faker": "^6.2.0", + "@trapi/query": "^2.1.2", + "glob": "^8.0.1", + "reflect-metadata": "^0.1.13", + "yargs": "^17.4.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.1.tgz", + "integrity": "sha512-cF7FYZZ47YzmCu7dDy50xSRRfO3ErRfrXuLZcNIuyiJEco0XSrGtuilG19L5xp3NcwTx7Gn+X6Tv3fmsUPTbow==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "typescript": { "version": "4.6.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz", @@ -10896,6 +11295,11 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/CommonServer/package.json b/CommonServer/package.json index 77ddf32a56..4e35756396 100644 --- a/CommonServer/package.json +++ b/CommonServer/package.json @@ -5,7 +5,7 @@ "main": "index.ts", "scripts": { "compile": "tsc", - "test": "jest ./Tests", + "test": "jest", "debug:test": "node --inspect node_modules/.bin/jest --runInBand ./Tests" }, "author": "", @@ -26,8 +26,10 @@ "node-device-detector": "^2.0.0", "nodemailer": "^6.7.3", "nodemailer-express-handlebars": "^5.0.0", + "pg": "^8.7.3", "socket.io": "^4.4.1", "typeorm": "^0.3.6", + "typeorm-extension": "^2.1.0", "winston": "^3.6.0" }, "devDependencies": { diff --git a/CommonServer/test.env b/CommonServer/test.env new file mode 100644 index 0000000000..c6b61f14fb --- /dev/null +++ b/CommonServer/test.env @@ -0,0 +1 @@ +DATABASE_NAME=oneuptimedbtest \ No newline at end of file diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml index 442de84c8e..86fe2943f7 100644 --- a/docker-compose.ci.yml +++ b/docker-compose.ci.yml @@ -221,25 +221,7 @@ services: - ./ApiDocs/.env environment: - IS_SAAS_SERVICE=${IS_SAAS_SERVICE} - init-script: - build: - context: . - dockerfile: ./InitScript/Dockerfile - ports: - - '1447:1447' - env_file: - - ./InitScript/.env - environment: - - - REDIS_HOST=redis - - IS_SAAS_SERVICE=${IS_SAAS_SERVICE} - - NODE_ENV=${NODE_ENV} - depends_on: - - - redis - ##IMPORTANT: - ## This container is an SMTP server used to send emails. - ## Setup private, tls_cert and tls_key keys before running this part + haraka: ports: - '2525:2525' diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 59c2756906..e24d62d739 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -29,7 +29,7 @@ services: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres ports: - - '5432:5432' + - '5400:5432' volumes: - postgres:/var/lib/postgresql/data @@ -195,31 +195,7 @@ services: # https://stackoverflow.com/questions/29181032/add-a-volume-to-docker-but-exclude-a-sub-folder - /usr/src/app/node_modules/ - init-script: - build: - network: host - context: . - dockerfile: ./InitScript/Dockerfile.dev - ports: - - '1447:1447' - - '9237:9229' # Debugging port. - env_file: - - ./InitScript/.env - environment: - - - REDIS_HOST=redis - - REDIS_PORT=6379 - - IS_SAAS_SERVICE=${IS_SAAS_SERVICE} - - NODE_ENV=development - depends_on: - - - redis - volumes: - - ./init-script:/usr/src/app - # Use node modules of the container and not host system. - # https://stackoverflow.com/questions/29181032/add-a-volume-to-docker-but-exclude-a-sub-folder - - /usr/src/app/node_modules/ - + script-runner: ports: - '3009:3009' diff --git a/docker-compose.yml b/docker-compose.yml index 46c322673f..2700ebf3ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -188,21 +188,7 @@ services: - ./ApiDocs/.env environment: - IS_SAAS_SERVICE=${IS_SAAS_SERVICE} - init-script: - image: oneuptime/init-script:latest - ports: - - '1447:1447' - env_file: - - ./InitScript/.env - environment: - - REDIS_HOST=redis - - IS_SAAS_SERVICE=${IS_SAAS_SERVICE} - - NODE_ENV=${NODE_ENV} - depends_on: - - redis - ##IMPORTANT: - ## This container is an SMTP server used to send emails. - ## Setup private, tls_cert and tls_key keys before running this part + haraka: ports: - '2525:2525'