@aneuhold/be-ts-db-lib 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Personal Backend Database Library
2
+
3
+ This is used to actually interact with databases in personal projects.
4
+
5
+ ## Dependencies
6
+
7
+ - [`core-ts-db-lib`](https://github.com/aneuhold/core-ts-db-lib)
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export {};
2
+ export type {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC;AAGV,YAAY,EAAE,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,31 @@
1
+ import { BaseDocument } from '@aneuhold/core-ts-db-lib';
2
+ import { Collection, DeleteResult, UpdateResult } from 'mongodb';
3
+ import { ObjectId } from 'bson';
4
+ import IValidator from '../validators/BaseValidator';
5
+ /**
6
+ * A base repository that implements a lot of the normal CRUD operations.
7
+ */
8
+ export default abstract class BaseRepository<TBasetype extends BaseDocument> {
9
+ private validator;
10
+ protected collectionName: string;
11
+ private collection?;
12
+ constructor(collectionName: string, validator: IValidator<TBasetype>);
13
+ protected getCollection(): Promise<Collection<import("bson").Document>>;
14
+ insertNew(newDoc: TBasetype): Promise<TBasetype | null>;
15
+ get(filter: Partial<TBasetype>): Promise<TBasetype | null>;
16
+ getAll(): Promise<TBasetype[]>;
17
+ getList(docIds: ObjectId[]): Promise<TBasetype[]>;
18
+ delete(docId: ObjectId): Promise<DeleteResult>;
19
+ deleteList(docIds: ObjectId[]): Promise<DeleteResult>;
20
+ /**
21
+ * This should not be used except for testing purposes
22
+ */
23
+ deleteAll(): Promise<DeleteResult>;
24
+ /**
25
+ * Updates the provided doc in the DB.
26
+ *
27
+ * This base method strips the `_id` before updating.
28
+ */
29
+ update(updatedDoc: Partial<TBasetype>): Promise<UpdateResult>;
30
+ }
31
+ //# sourceMappingURL=BaseRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseRepository.d.ts","sourceRoot":"","sources":["../../src/repositories/BaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC,OAAO,UAAU,MAAM,6BAA6B,CAAC;AAErD;;GAEG;AACH,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,cAAc,CAAC,SAAS,SAAS,YAAY;IAOvE,OAAO,CAAC,SAAS;IANnB,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IAEjC,OAAO,CAAC,UAAU,CAAC,CAAa;gBAG9B,cAAc,EAAE,MAAM,EACd,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC;cAK1B,aAAa;IAOvB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAUvD,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAM1D,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAO9B,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMjD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAK9C,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAK3D;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAKxC;;;;OAIG;IACG,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;CAYpE"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const DocumentDb_1 = __importDefault(require("../util/DocumentDb"));
7
+ /**
8
+ * A base repository that implements a lot of the normal CRUD operations.
9
+ */
10
+ class BaseRepository {
11
+ validator;
12
+ collectionName;
13
+ collection;
14
+ constructor(collectionName, validator) {
15
+ this.validator = validator;
16
+ this.collectionName = collectionName;
17
+ }
18
+ async getCollection() {
19
+ if (!this.collection) {
20
+ this.collection = await DocumentDb_1.default.getCollection(this.collectionName);
21
+ }
22
+ return this.collection;
23
+ }
24
+ async insertNew(newDoc) {
25
+ const collection = await this.getCollection();
26
+ await this.validator.validateNewObject(newDoc);
27
+ const insertResult = await collection.insertOne(newDoc);
28
+ if (!insertResult.acknowledged) {
29
+ return null;
30
+ }
31
+ return newDoc;
32
+ }
33
+ async get(filter) {
34
+ const collection = await this.getCollection();
35
+ const result = await collection.findOne(filter);
36
+ return result;
37
+ }
38
+ async getAll() {
39
+ const collection = await this.getCollection();
40
+ const result = await collection.find().toArray();
41
+ // Set to unknown first because of some weird type things.
42
+ return result;
43
+ }
44
+ async getList(docIds) {
45
+ const collection = await this.getCollection();
46
+ const result = await collection.find({ _id: { $in: docIds } }).toArray();
47
+ return result;
48
+ }
49
+ async delete(docId) {
50
+ const collection = await this.getCollection();
51
+ return collection.deleteOne({ _id: docId });
52
+ }
53
+ async deleteList(docIds) {
54
+ const collection = await this.getCollection();
55
+ return collection.deleteMany({ _id: { $in: docIds } });
56
+ }
57
+ /**
58
+ * This should not be used except for testing purposes
59
+ */
60
+ async deleteAll() {
61
+ const collection = await this.getCollection();
62
+ return collection.deleteMany({});
63
+ }
64
+ /**
65
+ * Updates the provided doc in the DB.
66
+ *
67
+ * This base method strips the `_id` before updating.
68
+ */
69
+ async update(updatedDoc) {
70
+ const collection = await this.getCollection();
71
+ await this.validator.validateUpdateObject(updatedDoc);
72
+ const docId = updatedDoc._id;
73
+ // Create a copy so that there aren't side-effects
74
+ const docCopy = { ...updatedDoc };
75
+ delete docCopy._id;
76
+ return collection.updateOne({ _id: docId }, { $set: docCopy });
77
+ }
78
+ }
79
+ exports.default = BaseRepository;
@@ -0,0 +1,27 @@
1
+ import { User } from '@aneuhold/core-ts-db-lib';
2
+ import BaseRepository from '../BaseRepository';
3
+ /**
4
+ * The repository that contains {@link User} documents.
5
+ */
6
+ export default class UserRepository extends BaseRepository<User> {
7
+ private static COLLECTION_NAME;
8
+ private static singletonInstance;
9
+ private constructor();
10
+ /**
11
+ * Gets the singleton instance of the {@link UserRepository}.
12
+ */
13
+ static getRepo(): UserRepository;
14
+ /**
15
+ * Inserts a new user.
16
+ *
17
+ * This will add the default team that consists of just the user if it
18
+ * doesn't already exist. If it does exist, it will add that team to the
19
+ * user's {@link User.currentTeamsIncludingUser} array.
20
+ *
21
+ * @override
22
+ *
23
+ * @returns The user with the additional team, or null if the insert failed.
24
+ */
25
+ insertNew(newUser: User): Promise<User | null>;
26
+ }
27
+ //# sourceMappingURL=UserRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/UserRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,cAAc,MAAM,mBAAmB,CAAC;AAG/C;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,cAAc,CAAC,IAAI,CAAC;IAC9D,OAAO,CAAC,MAAM,CAAC,eAAe,CAAW;IAEzC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAiB;IAEjD,OAAO;IAIP;;OAEG;WACW,OAAO;IAOrB;;;;;;;;;;OAUG;IACG,SAAS,CAAC,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;CAQrD"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const BaseRepository_1 = __importDefault(require("../BaseRepository"));
7
+ const UserValidator_1 = __importDefault(require("../../validators/common/UserValidator"));
8
+ /**
9
+ * The repository that contains {@link User} documents.
10
+ */
11
+ class UserRepository extends BaseRepository_1.default {
12
+ static COLLECTION_NAME = 'users';
13
+ static singletonInstance;
14
+ constructor() {
15
+ super(UserRepository.COLLECTION_NAME, new UserValidator_1.default());
16
+ }
17
+ /**
18
+ * Gets the singleton instance of the {@link UserRepository}.
19
+ */
20
+ static getRepo() {
21
+ if (!UserRepository.singletonInstance) {
22
+ UserRepository.singletonInstance = new UserRepository();
23
+ }
24
+ return UserRepository.singletonInstance;
25
+ }
26
+ /**
27
+ * Inserts a new user.
28
+ *
29
+ * This will add the default team that consists of just the user if it
30
+ * doesn't already exist. If it does exist, it will add that team to the
31
+ * user's {@link User.currentTeamsIncludingUser} array.
32
+ *
33
+ * @override
34
+ *
35
+ * @returns The user with the additional team, or null if the insert failed.
36
+ */
37
+ async insertNew(newUser) {
38
+ // Insert the new user first
39
+ const insertResult = await super.insertNew(newUser);
40
+ if (!insertResult) {
41
+ return null;
42
+ }
43
+ return newUser;
44
+ }
45
+ }
46
+ exports.default = UserRepository;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=BaseRepository.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseRepository.spec.d.ts","sourceRoot":"","sources":["../../../src/tests/repositories/BaseRepository.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const crypto_1 = __importDefault(require("crypto"));
7
+ const core_ts_db_lib_1 = require("@aneuhold/core-ts-db-lib");
8
+ const UserRepository_1 = __importDefault(require("../../repositories/common/UserRepository"));
9
+ const testsUtil_1 = require("../testsUtil");
10
+ const DocumentDb_1 = __importDefault(require("../../util/DocumentDb"));
11
+ it('can create a new document and delete it', async () => {
12
+ const userRepository = UserRepository_1.default.getRepo();
13
+ const newUser = new core_ts_db_lib_1.User(crypto_1.default.randomUUID());
14
+ const createResult = await userRepository.insertNew(newUser);
15
+ expect(createResult).toBeTruthy();
16
+ await (0, testsUtil_1.cleanupDoc)(userRepository, newUser);
17
+ });
18
+ afterAll(async () => {
19
+ return DocumentDb_1.default.closeDbConnection();
20
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=UserRepository.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserRepository.spec.d.ts","sourceRoot":"","sources":["../../../src/tests/repositories/UserRepository.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const crypto_1 = __importDefault(require("crypto"));
7
+ const core_ts_db_lib_1 = require("@aneuhold/core-ts-db-lib");
8
+ const testsUtil_1 = require("../testsUtil");
9
+ const UserRepository_1 = __importDefault(require("../../repositories/common/UserRepository"));
10
+ const DocumentDb_1 = __importDefault(require("../../util/DocumentDb"));
11
+ const userRepo = UserRepository_1.default.getRepo();
12
+ describe('Create operations', () => {
13
+ it('throws if the username is a duplicate username', async () => {
14
+ const duplicateUserName = `${crypto_1.default.randomUUID()}`;
15
+ const newUser1 = new core_ts_db_lib_1.User(duplicateUserName);
16
+ const newUser2 = new core_ts_db_lib_1.User(duplicateUserName);
17
+ const insertResult = await userRepo.insertNew(newUser1);
18
+ expect(insertResult).toBeTruthy();
19
+ await (0, testsUtil_1.expectToThrow)(async () => {
20
+ await userRepo.insertNew(newUser2);
21
+ });
22
+ await (0, testsUtil_1.cleanupDoc)(userRepo, newUser1);
23
+ });
24
+ });
25
+ describe('Update operations', () => {
26
+ it('succeeds in updating the username if the username doesnt already exist', async () => {
27
+ const userName1 = crypto_1.default.randomUUID();
28
+ const userName2 = crypto_1.default.randomUUID();
29
+ const newUser = new core_ts_db_lib_1.User(userName1);
30
+ // Insert the user
31
+ const insertResult = await userRepo.insertNew(newUser);
32
+ expect(insertResult).toBeTruthy();
33
+ // Try to update the user
34
+ newUser.userName = userName2;
35
+ const updateResult = await userRepo.update(newUser);
36
+ expect(updateResult.acknowledged).toBeTruthy();
37
+ await (0, testsUtil_1.cleanupDoc)(userRepo, newUser);
38
+ });
39
+ it('throws if no id is defined', async () => {
40
+ const newUser = new core_ts_db_lib_1.User(crypto_1.default.randomUUID());
41
+ delete newUser._id;
42
+ await (0, testsUtil_1.expectToThrow)(async () => {
43
+ await userRepo.update(newUser);
44
+ });
45
+ });
46
+ it('throws if the username is updated and already exists', async () => {
47
+ const userName1 = crypto_1.default.randomUUID();
48
+ const userName2 = crypto_1.default.randomUUID();
49
+ const newUser = new core_ts_db_lib_1.User(userName1);
50
+ const userWithOtherUserName = new core_ts_db_lib_1.User(userName2);
51
+ // Insert the users
52
+ const insertResult1 = await userRepo.insertNew(newUser);
53
+ expect(insertResult1).toBeTruthy();
54
+ const insertResult2 = await userRepo.insertNew(userWithOtherUserName);
55
+ expect(insertResult2).toBeTruthy();
56
+ // Try to update the first user
57
+ newUser.userName = userName2;
58
+ await (0, testsUtil_1.expectToThrow)(async () => {
59
+ await userRepo.update(newUser);
60
+ });
61
+ await Promise.all([
62
+ (0, testsUtil_1.cleanupDoc)(userRepo, newUser),
63
+ (0, testsUtil_1.cleanupDoc)(userRepo, userWithOtherUserName)
64
+ ]);
65
+ });
66
+ it('throws if the user doesnt exist', async () => {
67
+ const newUser = new core_ts_db_lib_1.User(crypto_1.default.randomUUID());
68
+ // Try to update the user
69
+ await (0, testsUtil_1.expectToThrow)(async () => {
70
+ await userRepo.update(newUser);
71
+ });
72
+ });
73
+ });
74
+ /**
75
+ * Deletes all users!
76
+ *
77
+ * Make sure that the local DB you are working on doesn't have important
78
+ * state before turning skip off on this one.
79
+ *
80
+ * To just do a cleanup, put `only` after `it`. So `it.only('can delete all users'`
81
+ */
82
+ it.skip('can delete all users', async () => {
83
+ const result = await userRepo.deleteAll();
84
+ expect(result.acknowledged).toBeTruthy();
85
+ });
86
+ afterAll(async () => {
87
+ return DocumentDb_1.default.closeDbConnection();
88
+ });
@@ -0,0 +1,9 @@
1
+ import { BaseDocument } from '@aneuhold/core-ts-db-lib';
2
+ import BaseRepository from '../repositories/BaseRepository';
3
+ export declare function expectToThrow(func: () => Promise<void>): Promise<void>;
4
+ /**
5
+ * Removes the provided doc from the DB
6
+ */
7
+ export declare function cleanupDoc<TDocType extends BaseDocument>(repo: BaseRepository<TDocType>, doc: TDocType): Promise<void>;
8
+ export declare function cleanupDocs<TDocType extends BaseDocument>(repo: BaseRepository<TDocType>, docs: TDocType[]): Promise<void>;
9
+ //# sourceMappingURL=testsUtil.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testsUtil.d.ts","sourceRoot":"","sources":["../../src/tests/testsUtil.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,cAAc,MAAM,gCAAgC,CAAC;AAE5D,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,iBAQ5D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,SAAS,YAAY,EAC5D,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC9B,GAAG,EAAE,QAAQ,iBAMd;AAED,wBAAsB,WAAW,CAAC,QAAQ,SAAS,YAAY,EAC7D,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC9B,IAAI,EAAE,QAAQ,EAAE,iBAOjB"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanupDocs = exports.cleanupDoc = exports.expectToThrow = void 0;
4
+ async function expectToThrow(func) {
5
+ let threwError = false;
6
+ try {
7
+ await func();
8
+ }
9
+ catch {
10
+ threwError = true;
11
+ }
12
+ expect(threwError).toBeTruthy();
13
+ }
14
+ exports.expectToThrow = expectToThrow;
15
+ /**
16
+ * Removes the provided doc from the DB
17
+ */
18
+ async function cleanupDoc(repo, doc) {
19
+ const deleteResult = await repo.delete(doc._id);
20
+ expect(deleteResult.acknowledged).toBeTruthy();
21
+ const findResult = await repo.get({ _id: doc._id });
22
+ expect(findResult).toBeNull();
23
+ }
24
+ exports.cleanupDoc = cleanupDoc;
25
+ async function cleanupDocs(repo, docs) {
26
+ const idsToDelete = docs.map((doc) => doc._id);
27
+ const deleteResult = await repo.deleteList(idsToDelete);
28
+ expect(deleteResult.acknowledged).toBeTruthy();
29
+ const findResult = await repo.getList(idsToDelete);
30
+ expect(findResult.length).toBe(0);
31
+ }
32
+ exports.cleanupDocs = cleanupDocs;
@@ -0,0 +1,11 @@
1
+ import { Collection } from 'mongodb';
2
+ import { Document } from 'bson';
3
+ export default class DocumentDb {
4
+ private static DB_NAME;
5
+ private static mongoClient;
6
+ private static db;
7
+ private static getClient;
8
+ static getCollection<TDocType extends Document>(collectionName: string): Promise<Collection<TDocType>>;
9
+ static closeDbConnection(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=DocumentDb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentDb.d.ts","sourceRoot":"","sources":["../../src/util/DocumentDb.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhC,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,OAAO,CAAC,MAAM,CAAC,OAAO,CAAa;IAEnC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAc;IAExC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAK;mBAED,SAAS;WAiBjB,aAAa,CAAC,QAAQ,SAAS,QAAQ,EAClD,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;WAQnB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAKhD"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const be_ts_lib_1 = require("@aneuhold/be-ts-lib");
4
+ const mongodb_1 = require("mongodb");
5
+ class DocumentDb {
6
+ static DB_NAME = 'default';
7
+ static mongoClient;
8
+ static db;
9
+ static async getClient() {
10
+ if (!be_ts_lib_1.ConfigService.isInitialized) {
11
+ // Hard-coded local for now until there are move envs.
12
+ await be_ts_lib_1.ConfigService.useConfig('local');
13
+ }
14
+ const { config } = be_ts_lib_1.ConfigService;
15
+ if (!this.mongoClient) {
16
+ const mongoDbConnectionString = `mongodb+srv://${config.mongoRootUsername}:${config.mongoRootPassword}@${config.mongoUrl}/?retryWrites=true&w=majority`;
17
+ this.mongoClient = new mongodb_1.MongoClient(mongoDbConnectionString);
18
+ }
19
+ // Connecting every time is evidently the correct way to do it. This is
20
+ // because it will not do anything and just return if it is already
21
+ // connected.
22
+ await this.mongoClient.connect();
23
+ return this.mongoClient;
24
+ }
25
+ static async getCollection(collectionName) {
26
+ const client = await this.getClient();
27
+ if (!this.db) {
28
+ DocumentDb.db = client.db(DocumentDb.DB_NAME);
29
+ }
30
+ return DocumentDb.db.collection(collectionName);
31
+ }
32
+ static async closeDbConnection() {
33
+ if (DocumentDb.mongoClient) {
34
+ await DocumentDb.mongoClient.close();
35
+ }
36
+ }
37
+ }
38
+ exports.default = DocumentDb;
@@ -0,0 +1,19 @@
1
+ import { BaseDocument } from '@aneuhold/core-ts-db-lib';
2
+ export default abstract class IValidator<TBaseType extends BaseDocument> {
3
+ /**
4
+ * Validates that an object that is supposed to be inserted in to the database
5
+ * is correct.
6
+ */
7
+ abstract validateNewObject(object: TBaseType): Promise<void>;
8
+ /**
9
+ * Validates an object that is suppposed to be updated in the database.
10
+ *
11
+ * At this point, the fields that do not change should already be stripped.
12
+ */
13
+ abstract validateUpdateObject(partialObject: Partial<TBaseType>): Promise<void>;
14
+ /**
15
+ * Checks that all elements that exist in array1, exist in array2.
16
+ */
17
+ protected checkAllElementsExistInArr(array1: Array<unknown>, array2: Array<unknown>): boolean;
18
+ }
19
+ //# sourceMappingURL=BaseValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseValidator.d.ts","sourceRoot":"","sources":["../../src/validators/BaseValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,UAAU,CAAC,SAAS,SAAS,YAAY;IACrE;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAE5D;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAC3B,aAAa,EAAE,OAAO,CAAC,SAAS,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC;IAEhB;;OAEG;IACH,SAAS,CAAC,0BAA0B,CAClC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,EACtB,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC;CAIzB"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class IValidator {
4
+ /**
5
+ * Checks that all elements that exist in array1, exist in array2.
6
+ */
7
+ checkAllElementsExistInArr(array1, array2) {
8
+ return array1.every((value) => array2.includes(value));
9
+ }
10
+ }
11
+ exports.default = IValidator;
@@ -0,0 +1,11 @@
1
+ import { User } from '@aneuhold/core-ts-db-lib';
2
+ import IValidator from '../BaseValidator';
3
+ export default class UserValidator extends IValidator<User> {
4
+ validateNewObject(newUser: User): Promise<void>;
5
+ validateUpdateObject(userToUpdate: Partial<User>): Promise<void>;
6
+ /**
7
+ * Checks if the username exists already and throws an error if it does.
8
+ */
9
+ private checkIfUserNameExists;
10
+ }
11
+ //# sourceMappingURL=UserValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserValidator.d.ts","sourceRoot":"","sources":["../../../src/validators/common/UserValidator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEhD,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAG1C,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,UAAU,CAAC,IAAI,CAAC;IACnD,iBAAiB,CAAC,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/C,oBAAoB,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BtE;;OAEG;YACW,qBAAqB;CAWpC"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const core_ts_db_lib_1 = require("@aneuhold/core-ts-db-lib");
7
+ const core_ts_lib_1 = require("@aneuhold/core-ts-lib");
8
+ const BaseValidator_1 = __importDefault(require("../BaseValidator"));
9
+ const UserRepository_1 = __importDefault(require("../../repositories/common/UserRepository"));
10
+ class UserValidator extends BaseValidator_1.default {
11
+ async validateNewObject(newUser) {
12
+ // Check if the username already exists
13
+ const userRepo = UserRepository_1.default.getRepo();
14
+ await this.checkIfUserNameExists(userRepo, newUser.userName);
15
+ }
16
+ async validateUpdateObject(userToUpdate) {
17
+ // Check if an id is defined
18
+ if (!userToUpdate._id) {
19
+ core_ts_lib_1.ErrorUtils.throwError(`No _id defined for ${core_ts_db_lib_1.User.name} to update.`, userToUpdate);
20
+ }
21
+ // Check to see if the user exists
22
+ const userRepo = UserRepository_1.default.getRepo();
23
+ const userInDb = await userRepo.get({ _id: userToUpdate._id });
24
+ if (!userInDb) {
25
+ core_ts_lib_1.ErrorUtils.throwError(`${core_ts_db_lib_1.User.name} with ID: ${userToUpdate._id} does not exist in the database.`, userToUpdate);
26
+ return;
27
+ }
28
+ // Check if the username is being updated and, if it is, if it already
29
+ // exists
30
+ if (userToUpdate.userName && userInDb.userName !== userToUpdate.userName) {
31
+ await this.checkIfUserNameExists(userRepo, userToUpdate.userName);
32
+ }
33
+ }
34
+ /**
35
+ * Checks if the username exists already and throws an error if it does.
36
+ */
37
+ async checkIfUserNameExists(userRepo, userName) {
38
+ const userNameSearchResult = await userRepo.get({
39
+ userName
40
+ });
41
+ if (userNameSearchResult) {
42
+ core_ts_lib_1.ErrorUtils.throwError('Username already exists', { userName });
43
+ }
44
+ }
45
+ }
46
+ exports.default = UserValidator;
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@aneuhold/be-ts-db-lib",
3
+ "version": "1.0.1",
4
+ "description": "A backend database library meant to actually interact with various databases in personal projects",
5
+ "author": "Anton G Neuhold Jr <agneuhold@gmail.com>",
6
+ "license": "MIT",
7
+ "main": "lib/index.js",
8
+ "types": "lib/index.d.ts",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/aneuhold/be-ts-db-lib.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/aneuhold/be-ts-db-lib/issues"
15
+ },
16
+ "homepage": "https://github.com/aneuhold/be-ts-db-lib#readme",
17
+ "files": [
18
+ "lib/**/*"
19
+ ],
20
+ "keywords": [
21
+ "Scripting",
22
+ "Node.js"
23
+ ],
24
+ "scripts": {
25
+ "pushpub": "npm run build && npm version patch && git push && npm publish --access public",
26
+ "build": "tsc",
27
+ "watch": "tsc -w",
28
+ "link:local": "cd lib && yarn link",
29
+ "link:coredb": "yarn link @aneuhold/core-ts-db-lib",
30
+ "link:bets": "yarn link @aneuhold/be-ts-lib",
31
+ "unlink:local": "cd lib && yarn unlink",
32
+ "unlink:coredb": "yarn unlink @aneuhold/core-ts-db-lib && yarn install --force",
33
+ "unlink:bets": "yarn unlink @aneuhold/be-ts-lib && yarn install --force",
34
+ "upgrade:all": "yarn upgrade --latest",
35
+ "test": "jest"
36
+ },
37
+ "dependencies": {
38
+ "@aneuhold/be-ts-lib": "^1.0.2",
39
+ "@aneuhold/core-ts-db-lib": "^1.0.1",
40
+ "@aneuhold/core-ts-lib": "^1.1.6",
41
+ "bson": "^6.2.0",
42
+ "mongodb": "^6.3.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/jest": "^29.5.8",
46
+ "@types/node": "^20.10.4",
47
+ "@types/node-fetch": "^2.6.9",
48
+ "@typescript-eslint/eslint-plugin": "^6.14.0",
49
+ "@typescript-eslint/parser": "^6.14.0",
50
+ "eslint": "^8.35.0",
51
+ "eslint-config-airbnb-base": "^15.0.0",
52
+ "eslint-config-prettier": "^9.1.0",
53
+ "eslint-plugin-import": "^2.22.1",
54
+ "eslint-plugin-prettier": "^5.0.1",
55
+ "jest": "^29.7.0",
56
+ "prettier": "^3.1.1",
57
+ "ts-jest": "^29.1.1",
58
+ "ts-node": "^10.2.1",
59
+ "typescript": "^5.3.3"
60
+ }
61
+ }