@aneuhold/be-ts-db-lib 1.0.7 → 1.0.8

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.
Files changed (58) hide show
  1. package/README.md +21 -0
  2. package/lib/index.d.ts +1 -1
  3. package/lib/index.d.ts.map +1 -1
  4. package/lib/index.js +2 -2
  5. package/lib/repositories/BaseRepository.d.ts +21 -1
  6. package/lib/repositories/BaseRepository.d.ts.map +1 -1
  7. package/lib/repositories/BaseRepository.js +57 -1
  8. package/lib/repositories/common/ApiKeyRepository.d.ts +5 -6
  9. package/lib/repositories/common/ApiKeyRepository.d.ts.map +1 -1
  10. package/lib/repositories/common/ApiKeyRepository.js +21 -9
  11. package/lib/repositories/common/UserRepository.d.ts +1 -32
  12. package/lib/repositories/common/UserRepository.d.ts.map +1 -1
  13. package/lib/repositories/common/UserRepository.js +5 -63
  14. package/lib/repositories/dashboard/DashboardUserConfigRepository.d.ts +17 -0
  15. package/lib/repositories/dashboard/DashboardUserConfigRepository.d.ts.map +1 -0
  16. package/lib/repositories/dashboard/DashboardUserConfigRepository.js +48 -0
  17. package/lib/scripts/migrate.d.ts +2 -0
  18. package/lib/scripts/migrate.d.ts.map +1 -0
  19. package/lib/scripts/migrate.js +7 -0
  20. package/lib/scripts/migrateDry.d.ts +2 -0
  21. package/lib/scripts/migrateDry.d.ts.map +1 -0
  22. package/lib/scripts/migrateDry.js +7 -0
  23. package/lib/scripts/validateSchema.d.ts +2 -0
  24. package/lib/scripts/validateSchema.d.ts.map +1 -0
  25. package/lib/scripts/validateSchema.js +9 -0
  26. package/lib/scripts/validateSchemaDryRun.d.ts +2 -0
  27. package/lib/scripts/validateSchemaDryRun.d.ts.map +1 -0
  28. package/lib/scripts/validateSchemaDryRun.js +9 -0
  29. package/lib/services/MigrationService.d.ts +20 -0
  30. package/lib/services/MigrationService.d.ts.map +1 -0
  31. package/lib/services/MigrationService.js +57 -0
  32. package/lib/services/RepoSubscriptionService.d.ts +30 -0
  33. package/lib/services/RepoSubscriptionService.d.ts.map +1 -0
  34. package/lib/services/RepoSubscriptionService.js +21 -0
  35. package/lib/tests/repositories/BaseRepository.spec.js +4 -4
  36. package/lib/tests/repositories/common/UserRepository.spec.js +9 -10
  37. package/lib/tests/repositories/dashboard/UserConfigRepository.spec.js +3 -3
  38. package/lib/tests/testsUtil.d.ts +9 -0
  39. package/lib/tests/testsUtil.d.ts.map +1 -1
  40. package/lib/tests/testsUtil.js +19 -1
  41. package/lib/util/DbSchemaUpdater.d.ts +7 -0
  42. package/lib/util/DbSchemaUpdater.d.ts.map +1 -0
  43. package/lib/util/DbSchemaUpdater.js +19 -0
  44. package/lib/util/DocumentCleaner.d.ts +2 -2
  45. package/lib/util/DocumentCleaner.d.ts.map +1 -1
  46. package/lib/validators/BaseValidator.d.ts +36 -1
  47. package/lib/validators/BaseValidator.d.ts.map +1 -1
  48. package/lib/validators/BaseValidator.js +74 -0
  49. package/lib/validators/common/ApiKeyValidator.d.ts +1 -0
  50. package/lib/validators/common/ApiKeyValidator.d.ts.map +1 -1
  51. package/lib/validators/common/ApiKeyValidator.js +25 -0
  52. package/lib/validators/common/UserValidator.d.ts +1 -0
  53. package/lib/validators/common/UserValidator.d.ts.map +1 -1
  54. package/lib/validators/common/UserValidator.js +24 -0
  55. package/lib/validators/dashboard/UserConfigValidator.d.ts +1 -0
  56. package/lib/validators/dashboard/UserConfigValidator.d.ts.map +1 -1
  57. package/lib/validators/dashboard/UserConfigValidator.js +27 -2
  58. package/package.json +9 -5
package/README.md CHANGED
@@ -4,6 +4,27 @@
4
4
 
5
5
  This is used to actually interact with databases in personal projects.
6
6
 
7
+ ## Development
8
+
9
+ ### Creating a new Repository
10
+
11
+ 1. Copy an existing one over
12
+ 2. Make sure to register the repository in the `RepoSubscriptionService`, even if nothing needs to be setup, just as a future precaution.
13
+
14
+ ## Subscription System
15
+
16
+ ```mermaid
17
+ sequenceDiagram
18
+ Note over UserRepository: getRepo called
19
+ UserRepository->>ApiKeyRepository: getSubscribers called
20
+ ApiKeyRepository->>UserRepository: Subscribes
21
+ ```
22
+
23
+ ## Schema Validation for DB
24
+
25
+ If any of the base document types are updated, make sure to run `yarn validate`
26
+ to make sure that the DB is up-to-date as well.
27
+
7
28
  ## Manual Database Operations
8
29
 
9
30
  Go ahead and run these as code in a test in the BaseRepository.spec.ts file.
package/lib/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import ApiKeyRepository from './repositories/common/ApiKeyRepository';
2
2
  import UserRepository from './repositories/common/UserRepository';
3
- import DashboardUserConfigRepository from './repositories/dashboard/UserConfigRepository';
3
+ import DashboardUserConfigRepository from './repositories/dashboard/DashboardUserConfigRepository';
4
4
  import DocumentDb from './util/DocumentDb';
5
5
  export { UserRepository, ApiKeyRepository, DocumentDb, DashboardUserConfigRepository };
6
6
  export type {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,wCAAwC,CAAC;AACtE,OAAO,cAAc,MAAM,sCAAsC,CAAC;AAClE,OAAO,6BAA6B,MAAM,+CAA+C,CAAC;AAC1F,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,6BAA6B,EAC9B,CAAC;AAGF,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,wCAAwC,CAAC;AACtE,OAAO,cAAc,MAAM,sCAAsC,CAAC;AAClE,OAAO,6BAA6B,MAAM,wDAAwD,CAAC;AACnG,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,6BAA6B,EAC9B,CAAC;AAGF,YAAY,EAAE,CAAC"}
package/lib/index.js CHANGED
@@ -8,7 +8,7 @@ const ApiKeyRepository_1 = __importDefault(require("./repositories/common/ApiKey
8
8
  exports.ApiKeyRepository = ApiKeyRepository_1.default;
9
9
  const UserRepository_1 = __importDefault(require("./repositories/common/UserRepository"));
10
10
  exports.UserRepository = UserRepository_1.default;
11
- const UserConfigRepository_1 = __importDefault(require("./repositories/dashboard/UserConfigRepository"));
12
- exports.DashboardUserConfigRepository = UserConfigRepository_1.default;
11
+ const DashboardUserConfigRepository_1 = __importDefault(require("./repositories/dashboard/DashboardUserConfigRepository"));
12
+ exports.DashboardUserConfigRepository = DashboardUserConfigRepository_1.default;
13
13
  const DocumentDb_1 = __importDefault(require("./util/DocumentDb"));
14
14
  exports.DocumentDb = DocumentDb_1.default;
@@ -1,7 +1,8 @@
1
1
  import { BaseDocument } from '@aneuhold/core-ts-db-lib';
2
- import { Collection, DeleteResult, UpdateResult } from 'mongodb';
2
+ import { BulkWriteResult, Collection, DeleteResult, UpdateResult } from 'mongodb';
3
3
  import { Document, ObjectId } from 'bson';
4
4
  import IValidator from '../validators/BaseValidator';
5
+ import { RepoListeners } from '../services/RepoSubscriptionService';
5
6
  /**
6
7
  * A base repository that implements a lot of the normal CRUD operations.
7
8
  */
@@ -11,6 +12,7 @@ export default abstract class BaseRepository<TBasetype extends BaseDocument> {
11
12
  private defaultUpdateCleaner?;
12
13
  protected collectionName: string;
13
14
  private collection?;
15
+ protected subscribers: import("../services/RepoSubscriptionService").RepoSubscribers<TBasetype>;
14
16
  /**
15
17
  * Constructs a new base repository.
16
18
  *
@@ -21,9 +23,21 @@ export default abstract class BaseRepository<TBasetype extends BaseDocument> {
21
23
  */
22
24
  constructor(collectionName: string, validator: IValidator<TBasetype>, defaultFilter?: Partial<TBasetype> | undefined, defaultUpdateCleaner?: ((doc: Partial<TBasetype>) => Partial<TBasetype>) | undefined);
23
25
  protected getCollection(): Promise<Collection<Document>>;
26
+ protected abstract setupSubscribers(): void;
27
+ /**
28
+ * Registers a set of functions that will be called when a change happens
29
+ * in this repository.
30
+ */
31
+ subscribeToChanges(listeners: RepoListeners<TBasetype>): void;
24
32
  insertNew(newDoc: TBasetype): Promise<TBasetype | null>;
25
33
  get(filter: Partial<TBasetype>): Promise<TBasetype | null>;
26
34
  getAll(): Promise<TBasetype[]>;
35
+ /**
36
+ * Gets all the IDs in the collection as a hash for performant lookups.
37
+ */
38
+ getAllIdsAsHash(): Promise<{
39
+ [id: string]: boolean;
40
+ }>;
27
41
  getList(docIds: ObjectId[]): Promise<TBasetype[]>;
28
42
  delete(docId: ObjectId): Promise<DeleteResult>;
29
43
  deleteList(docIds: ObjectId[]): Promise<DeleteResult>;
@@ -37,6 +51,12 @@ export default abstract class BaseRepository<TBasetype extends BaseDocument> {
37
51
  * This base method strips the `_id` before updating.
38
52
  */
39
53
  update(updatedDoc: Partial<TBasetype>): Promise<UpdateResult>;
54
+ /**
55
+ * Updates the provided docs in the DB.
56
+ *
57
+ * This base method strips the `_id` before updating.
58
+ */
59
+ updateMany(updatedDocs: Array<Partial<TBasetype>>): Promise<BulkWriteResult>;
40
60
  /**
41
61
  * Gets the filter with the default filter applied if there is one.
42
62
  *
@@ -1 +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,EAAU,YAAY,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,UAAU,MAAM,6BAA6B,CAAC;AAGrD;;GAEG;AACH,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,cAAc,CAAC,SAAS,SAAS,YAAY;IAevE,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,aAAa,CAAC;IACtB,OAAO,CAAC,oBAAoB,CAAC;IAhB/B,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IAEjC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC;;;;;;;OAOG;gBAED,cAAc,EAAE,MAAM,EACd,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,EAChC,aAAa,CAAC,gCAAoB,EAClC,oBAAoB,CAAC,SACtB,QAAQ,SAAS,CAAC,KACpB,QAAQ,SAAS,CAAC,aAAA;cAKT,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;IAQjD,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;IAWnE;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;CAO1B"}
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,EACL,eAAe,EACf,UAAU,EACV,YAAY,EAEZ,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,UAAU,MAAM,6BAA6B,CAAC;AAErD,OAAgC,EAC9B,aAAa,EACd,MAAM,qCAAqC,CAAC;AAE7C;;GAEG;AACH,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,cAAc,CAAC,SAAS,SAAS,YAAY;IAkBvE,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,aAAa,CAAC;IACtB,OAAO,CAAC,oBAAoB,CAAC;IAnB/B,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC;IAEjC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,SAAS,CAAC,WAAW,2EACwC;IAE7D;;;;;;;OAOG;gBAED,cAAc,EAAE,MAAM,EACd,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,EAChC,aAAa,CAAC,gCAAoB,EAClC,oBAAoB,CAAC,SACtB,QAAQ,SAAS,CAAC,KACpB,QAAQ,SAAS,CAAC,aAAA;cAKT,aAAa;IAQ7B,SAAS,CAAC,QAAQ,CAAC,gBAAgB,IAAI,IAAI;IAE3C;;;OAGG;IACH,kBAAkB,CAAC,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC;IAgBhD,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAavD,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAM1D,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAOpC;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC;QAAE,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAQrD,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAQjD,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ9C,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAS3D;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;IAKxC;;;;OAIG;IACG,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAWnE;;;;OAIG;IACG,UAAU,CACd,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,GACrC,OAAO,CAAC,eAAe,CAAC;IAoB3B;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;CAO1B"}
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const DocumentDb_1 = __importDefault(require("../util/DocumentDb"));
7
7
  const DocumentCleaner_1 = __importDefault(require("../util/DocumentCleaner"));
8
+ const RepoSubscriptionService_1 = __importDefault(require("../services/RepoSubscriptionService"));
8
9
  /**
9
10
  * A base repository that implements a lot of the normal CRUD operations.
10
11
  */
@@ -14,6 +15,7 @@ class BaseRepository {
14
15
  defaultUpdateCleaner;
15
16
  collectionName;
16
17
  collection;
18
+ subscribers = RepoSubscriptionService_1.default.getDefaultSubscribers();
17
19
  /**
18
20
  * Constructs a new base repository.
19
21
  *
@@ -31,9 +33,29 @@ class BaseRepository {
31
33
  async getCollection() {
32
34
  if (!this.collection) {
33
35
  this.collection = await DocumentDb_1.default.getCollection(this.collectionName);
36
+ this.setupSubscribers();
34
37
  }
35
38
  return this.collection;
36
39
  }
40
+ /**
41
+ * Registers a set of functions that will be called when a change happens
42
+ * in this repository.
43
+ */
44
+ subscribeToChanges(listeners) {
45
+ const { insertNew, updateMany, deleteOne, deleteList } = listeners;
46
+ if (insertNew) {
47
+ this.subscribers.insertNew.push(insertNew);
48
+ }
49
+ if (updateMany) {
50
+ this.subscribers.updateMany.push(updateMany);
51
+ }
52
+ if (deleteOne) {
53
+ this.subscribers.deleteOne.push(deleteOne);
54
+ }
55
+ if (deleteList) {
56
+ this.subscribers.deleteList.push(deleteList);
57
+ }
58
+ }
37
59
  async insertNew(newDoc) {
38
60
  const collection = await this.getCollection();
39
61
  await this.validator.validateNewObject(newDoc);
@@ -41,6 +63,7 @@ class BaseRepository {
41
63
  if (!insertResult.acknowledged) {
42
64
  return null;
43
65
  }
66
+ await Promise.all(this.subscribers.insertNew.map((subscriber) => subscriber(newDoc)));
44
67
  return newDoc;
45
68
  }
46
69
  async get(filter) {
@@ -54,6 +77,16 @@ class BaseRepository {
54
77
  // Set to unknown first because of some weird type things.
55
78
  return result;
56
79
  }
80
+ /**
81
+ * Gets all the IDs in the collection as a hash for performant lookups.
82
+ */
83
+ async getAllIdsAsHash() {
84
+ const allDocs = await this.getAll();
85
+ return allDocs.reduce((acc, doc) => {
86
+ acc[doc._id.toString()] = true;
87
+ return acc;
88
+ }, {});
89
+ }
57
90
  async getList(docIds) {
58
91
  const collection = await this.getCollection();
59
92
  const result = await collection
@@ -63,11 +96,14 @@ class BaseRepository {
63
96
  }
64
97
  async delete(docId) {
65
98
  const collection = await this.getCollection();
99
+ await Promise.all(this.subscribers.deleteOne.map((subscriber) => subscriber(docId)));
66
100
  return collection.deleteOne({ _id: docId });
67
101
  }
68
102
  async deleteList(docIds) {
69
103
  const collection = await this.getCollection();
70
- return collection.deleteMany({ _id: { $in: docIds } });
104
+ const deleteResult = collection.deleteMany({ _id: { $in: docIds } });
105
+ await Promise.all(this.subscribers.deleteList.map((subscriber) => subscriber(docIds)));
106
+ return deleteResult;
71
107
  }
72
108
  /**
73
109
  * This should not be used except for testing purposes
@@ -88,6 +124,26 @@ class BaseRepository {
88
124
  const cleanedDoc = this.cleanUpdateObject(updatedDoc);
89
125
  return collection.updateOne({ _id: docId }, { $set: cleanedDoc });
90
126
  }
127
+ /**
128
+ * Updates the provided docs in the DB.
129
+ *
130
+ * This base method strips the `_id` before updating.
131
+ */
132
+ async updateMany(updatedDocs) {
133
+ const collection = await this.getCollection();
134
+ await Promise.all(updatedDocs.map((doc) => this.validator.validateUpdateObject(doc)));
135
+ const bulkOps = updatedDocs.map((doc) => {
136
+ const docId = doc._id;
137
+ const cleanedDoc = this.cleanUpdateObject(doc);
138
+ return {
139
+ updateOne: {
140
+ filter: { _id: docId },
141
+ update: { $set: cleanedDoc }
142
+ }
143
+ };
144
+ });
145
+ return collection.bulkWrite(bulkOps);
146
+ }
91
147
  /**
92
148
  * Gets the filter with the default filter applied if there is one.
93
149
  *
@@ -1,19 +1,18 @@
1
- import { ApiKey } from '@aneuhold/core-ts-db-lib';
2
- import { DeleteResult } from 'mongodb';
3
- import { ObjectId } from 'bson';
1
+ import { ApiKey, User } from '@aneuhold/core-ts-db-lib';
4
2
  import BaseRepository from '../BaseRepository';
3
+ import { RepoListeners } from '../../services/RepoSubscriptionService';
5
4
  /**
6
- * The repository that contains {@link User} documents.
5
+ * The repository that contains {@link ApiKey} documents.
7
6
  */
8
7
  export default class ApiKeyRepository extends BaseRepository<ApiKey> {
9
8
  private static COLLECTION_NAME;
10
9
  private static singletonInstance;
10
+ static getListenersForUserRepo(): RepoListeners<User>;
11
11
  private constructor();
12
+ protected setupSubscribers(): void;
12
13
  /**
13
14
  * Gets the singleton instance of the {@link ApiKeyRepository}.
14
15
  */
15
16
  static getRepo(): ApiKeyRepository;
16
- deleteByUserId(userId: ObjectId): Promise<DeleteResult>;
17
- deleteByUserIds(userIds: ObjectId[]): Promise<DeleteResult>;
18
17
  }
19
18
  //# sourceMappingURL=ApiKeyRepository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ApiKeyRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/ApiKeyRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,cAAc,MAAM,mBAAmB,CAAC;AAG/C;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,cAAc,CAAC,MAAM,CAAC;IAClE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAa;IAE3C,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAmB;IAEnD,OAAO;IAIP;;OAEG;WACW,OAAO;IAOf,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAKvD,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAIlE"}
1
+ {"version":3,"file":"ApiKeyRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/ApiKeyRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,cAAc,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAEvE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,cAAc,CAAC,MAAM,CAAC;IAClE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAa;IAE3C,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAmB;IAEnD,MAAM,CAAC,uBAAuB,IAAI,aAAa,CAAC,IAAI,CAAC;IAmBrD,OAAO;IAIP,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAElC;;OAEG;WACW,OAAO;CAMtB"}
@@ -3,17 +3,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const core_ts_db_lib_1 = require("@aneuhold/core-ts-db-lib");
6
7
  const BaseRepository_1 = __importDefault(require("../BaseRepository"));
7
8
  const ApiKeyValidator_1 = __importDefault(require("../../validators/common/ApiKeyValidator"));
8
9
  /**
9
- * The repository that contains {@link User} documents.
10
+ * The repository that contains {@link ApiKey} documents.
10
11
  */
11
12
  class ApiKeyRepository extends BaseRepository_1.default {
12
13
  static COLLECTION_NAME = 'apiKeys';
13
14
  static singletonInstance;
15
+ static getListenersForUserRepo() {
16
+ const apiKeyRepo = ApiKeyRepository.getRepo();
17
+ return {
18
+ deleteOne: async (userId) => {
19
+ (await apiKeyRepo.getCollection()).deleteOne({
20
+ userId
21
+ });
22
+ },
23
+ deleteList: async (userIds) => {
24
+ (await apiKeyRepo.getCollection()).deleteMany({
25
+ userId: { $in: userIds }
26
+ });
27
+ },
28
+ insertNew: async (user) => {
29
+ await apiKeyRepo.insertNew(new core_ts_db_lib_1.ApiKey(user._id));
30
+ }
31
+ };
32
+ }
14
33
  constructor() {
15
34
  super(ApiKeyRepository.COLLECTION_NAME, new ApiKeyValidator_1.default());
16
35
  }
36
+ setupSubscribers() { }
17
37
  /**
18
38
  * Gets the singleton instance of the {@link ApiKeyRepository}.
19
39
  */
@@ -23,13 +43,5 @@ class ApiKeyRepository extends BaseRepository_1.default {
23
43
  }
24
44
  return ApiKeyRepository.singletonInstance;
25
45
  }
26
- async deleteByUserId(userId) {
27
- const collection = await this.getCollection();
28
- return collection.deleteOne({ userId });
29
- }
30
- async deleteByUserIds(userIds) {
31
- const collection = await this.getCollection();
32
- return collection.deleteMany({ userId: { $in: userIds } });
33
- }
34
46
  }
35
47
  exports.default = ApiKeyRepository;
@@ -1,6 +1,4 @@
1
1
  import { User } from '@aneuhold/core-ts-db-lib';
2
- import { DeleteResult } from 'mongodb';
3
- import { ObjectId } from 'bson';
4
2
  import BaseRepository from '../BaseRepository';
5
3
  /**
6
4
  * The repository that contains {@link User} documents.
@@ -9,39 +7,10 @@ export default class UserRepository extends BaseRepository<User> {
9
7
  private static COLLECTION_NAME;
10
8
  private static singletonInstance;
11
9
  private constructor();
10
+ protected setupSubscribers(): void;
12
11
  /**
13
12
  * Gets the singleton instance of the {@link UserRepository}.
14
13
  */
15
14
  static getRepo(): UserRepository;
16
- /**
17
- * Inserts a new user.
18
- *
19
- * This will create a new API key for the user as well.
20
- *
21
- * @override
22
- */
23
- insertNew(newUser: User): Promise<User | null>;
24
- /**
25
- * Deletes a user.
26
- *
27
- * This will delete the API key for the user as well if there is one.
28
- *
29
- * @override
30
- */
31
- delete(userId: ObjectId): Promise<DeleteResult>;
32
- /**
33
- * Deletes a list of users.
34
- *
35
- * This will delete the API keys for the users as well if there are any.
36
- *
37
- * @override
38
- */
39
- deleteList(userIds: ObjectId[]): Promise<DeleteResult>;
40
- /**
41
- * This should not be used except for testing purposes
42
- *
43
- * @override
44
- */
45
- deleteAll(): Promise<DeleteResult>;
46
15
  }
47
16
  //# sourceMappingURL=UserRepository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/common/UserRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,cAAc,MAAM,mBAAmB,CAAC;AAK/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;;;;;;OAMG;IACG,SAAS,CAAC,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAcpD;;;;;;OAMG;IACG,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IASrD;;;;;;OAMG;IACG,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAS5D;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;CAQzC"}
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;AAK/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,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAOlC;;OAEG;IACH,MAAM,CAAC,OAAO;CAMf"}
@@ -3,11 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const core_ts_db_lib_1 = require("@aneuhold/core-ts-db-lib");
7
6
  const BaseRepository_1 = __importDefault(require("../BaseRepository"));
8
7
  const UserValidator_1 = __importDefault(require("../../validators/common/UserValidator"));
9
8
  const ApiKeyRepository_1 = __importDefault(require("./ApiKeyRepository"));
10
- const UserConfigRepository_1 = __importDefault(require("../dashboard/UserConfigRepository"));
9
+ const DashboardUserConfigRepository_1 = __importDefault(require("../dashboard/DashboardUserConfigRepository"));
11
10
  /**
12
11
  * The repository that contains {@link User} documents.
13
12
  */
@@ -17,6 +16,10 @@ class UserRepository extends BaseRepository_1.default {
17
16
  constructor() {
18
17
  super(UserRepository.COLLECTION_NAME, new UserValidator_1.default());
19
18
  }
19
+ setupSubscribers() {
20
+ this.subscribeToChanges(ApiKeyRepository_1.default.getListenersForUserRepo());
21
+ this.subscribeToChanges(DashboardUserConfigRepository_1.default.getListenersForUserRepo());
22
+ }
20
23
  /**
21
24
  * Gets the singleton instance of the {@link UserRepository}.
22
25
  */
@@ -26,66 +29,5 @@ class UserRepository extends BaseRepository_1.default {
26
29
  }
27
30
  return UserRepository.singletonInstance;
28
31
  }
29
- /**
30
- * Inserts a new user.
31
- *
32
- * This will create a new API key for the user as well.
33
- *
34
- * @override
35
- */
36
- async insertNew(newUser) {
37
- const insertResult = await super.insertNew(newUser);
38
- if (!insertResult) {
39
- return null;
40
- }
41
- await ApiKeyRepository_1.default.getRepo().insertNew(new core_ts_db_lib_1.ApiKey(newUser._id));
42
- if (insertResult.projectAccess.dashboard) {
43
- await UserConfigRepository_1.default.getRepo().insertNew(new core_ts_db_lib_1.DashboardUserConfig(newUser._id));
44
- }
45
- return newUser;
46
- }
47
- /**
48
- * Deletes a user.
49
- *
50
- * This will delete the API key for the user as well if there is one.
51
- *
52
- * @override
53
- */
54
- async delete(userId) {
55
- const [deleteResult] = await Promise.all([
56
- super.delete(userId),
57
- ApiKeyRepository_1.default.getRepo().deleteByUserId(userId),
58
- UserConfigRepository_1.default.getRepo().deleteByUserId(userId)
59
- ]);
60
- return deleteResult;
61
- }
62
- /**
63
- * Deletes a list of users.
64
- *
65
- * This will delete the API keys for the users as well if there are any.
66
- *
67
- * @override
68
- */
69
- async deleteList(userIds) {
70
- const [deleteResult] = await Promise.all([
71
- super.deleteList(userIds),
72
- ApiKeyRepository_1.default.getRepo().deleteByUserIds(userIds),
73
- UserConfigRepository_1.default.getRepo().deleteByUserIds(userIds)
74
- ]);
75
- return deleteResult;
76
- }
77
- /**
78
- * This should not be used except for testing purposes
79
- *
80
- * @override
81
- */
82
- async deleteAll() {
83
- const [deleteResult] = await Promise.all([
84
- super.deleteAll(),
85
- ApiKeyRepository_1.default.getRepo().deleteAll(),
86
- UserConfigRepository_1.default.getRepo().deleteAll()
87
- ]);
88
- return deleteResult;
89
- }
90
32
  }
91
33
  exports.default = UserRepository;
@@ -0,0 +1,17 @@
1
+ import { DashboardUserConfig, User } from '@aneuhold/core-ts-db-lib';
2
+ import DashboardBaseRepository from './DashboardBaseRepository';
3
+ import { RepoListeners } from '../../services/RepoSubscriptionService';
4
+ /**
5
+ * The repository that contains {@link DashboardUserConfig} documents.
6
+ */
7
+ export default class DashboardUserConfigRepository extends DashboardBaseRepository<DashboardUserConfig> {
8
+ private static singletonInstance;
9
+ private constructor();
10
+ static getListenersForUserRepo(): RepoListeners<User>;
11
+ protected setupSubscribers(): void;
12
+ /**
13
+ * Gets the singleton instance of the {@link DashboardUserConfigRepository}.
14
+ */
15
+ static getRepo(): DashboardUserConfigRepository;
16
+ }
17
+ //# sourceMappingURL=DashboardUserConfigRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardUserConfigRepository.d.ts","sourceRoot":"","sources":["../../../src/repositories/dashboard/DashboardUserConfigRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,uBAAuB,MAAM,2BAA2B,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAEvE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,6BAA8B,SAAQ,uBAAuB,CAAC,mBAAmB,CAAC;IACrG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAgC;IAEhE,OAAO;IAQP,MAAM,CAAC,uBAAuB,IAAI,aAAa,CAAC,IAAI,CAAC;IAmBrD,SAAS,CAAC,gBAAgB,IAAI,IAAI;IAElC;;OAEG;WACW,OAAO;CAOtB"}
@@ -0,0 +1,48 @@
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 DashboardBaseRepository_1 = __importDefault(require("./DashboardBaseRepository"));
8
+ const UserConfigValidator_1 = __importDefault(require("../../validators/dashboard/UserConfigValidator"));
9
+ const DocumentCleaner_1 = __importDefault(require("../../util/DocumentCleaner"));
10
+ /**
11
+ * The repository that contains {@link DashboardUserConfig} documents.
12
+ */
13
+ class DashboardUserConfigRepository extends DashboardBaseRepository_1.default {
14
+ static singletonInstance;
15
+ constructor() {
16
+ super(core_ts_db_lib_1.DashboardUserConfig.docType, new UserConfigValidator_1.default(), DocumentCleaner_1.default.userId);
17
+ }
18
+ static getListenersForUserRepo() {
19
+ const userConfigRepo = DashboardUserConfigRepository.getRepo();
20
+ return {
21
+ deleteOne: async (userId) => {
22
+ (await userConfigRepo.getCollection()).deleteOne({ userId });
23
+ },
24
+ deleteList: async (userIds) => {
25
+ (await userConfigRepo.getCollection()).deleteMany({
26
+ userId: { $in: userIds }
27
+ });
28
+ },
29
+ insertNew: async (user) => {
30
+ if (user.projectAccess.dashboard) {
31
+ await userConfigRepo.insertNew(new core_ts_db_lib_1.DashboardUserConfig(user._id));
32
+ }
33
+ }
34
+ };
35
+ }
36
+ setupSubscribers() { }
37
+ /**
38
+ * Gets the singleton instance of the {@link DashboardUserConfigRepository}.
39
+ */
40
+ static getRepo() {
41
+ if (!DashboardUserConfigRepository.singletonInstance) {
42
+ DashboardUserConfigRepository.singletonInstance =
43
+ new DashboardUserConfigRepository();
44
+ }
45
+ return DashboardUserConfigRepository.singletonInstance;
46
+ }
47
+ }
48
+ exports.default = DashboardUserConfigRepository;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/scripts/migrate.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
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 MigrationService_1 = __importDefault(require("../services/MigrationService"));
7
+ MigrationService_1.default.migrateDb().then(() => process.exit(0));
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=migrateDry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrateDry.d.ts","sourceRoot":"","sources":["../../src/scripts/migrateDry.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
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 MigrationService_1 = __importDefault(require("../services/MigrationService"));
7
+ MigrationService_1.default.migrateDb(true).then(() => process.exit(0));
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validateSchema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateSchema.d.ts","sourceRoot":"","sources":["../../src/scripts/validateSchema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
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 DbSchemaUpdater_1 = __importDefault(require("../util/DbSchemaUpdater"));
7
+ DbSchemaUpdater_1.default.updateSchemaForAllRepos().then(() => {
8
+ process.exit(0);
9
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validateSchemaDryRun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateSchemaDryRun.d.ts","sourceRoot":"","sources":["../../src/scripts/validateSchemaDryRun.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
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 DbSchemaUpdater_1 = __importDefault(require("../util/DbSchemaUpdater"));
7
+ DbSchemaUpdater_1.default.updateSchemaForAllRepos(true).then(() => {
8
+ process.exit(0);
9
+ });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A service for migrating the DB to a new state after an existing document
3
+ * change.
4
+ *
5
+ * This entire class is ignored from ESLint and TypeScript to allow for
6
+ * manipulating the DB in any way necessary.
7
+ */
8
+ export default class MigrationService {
9
+ /**
10
+ * A function that can be used to migrate the DB to a new state after an
11
+ * existing document change.
12
+ *
13
+ * ❗️ BEWARE!!! ❗️
14
+ * TRIPLE CHECK THAT THIS IS WHAT YOU WANT TO DO BEFORE RUNNING THIS FUNCTION.
15
+ *
16
+ * @param dryRun Whether or not to actually make the changes or just log them.
17
+ */
18
+ static migrateDb(dryRun?: boolean): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=MigrationService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MigrationService.d.ts","sourceRoot":"","sources":["../../src/services/MigrationService.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAgB;IACnC;;;;;;;;OAQG;WACU,SAAS,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CA6BtD"}