@expressots/core 3.0.0-beta.1 → 3.0.0-beta.3

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/lib/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [3.0.0-beta.3](https://github.com/expressots/expressots/compare/3.0.0-beta.1...3.0.0) (2024-11-28)
2
+
3
+ ### Features
4
+
5
+ - implement in-memory data provider and repository interfaces ([09561fa](https://github.com/expressots/expressots/commit/09561fa1385e040bc235ba0d699f654f269c0a21))
6
+
7
+ ### Tests
8
+
9
+ - add unit tests for insert, update, delete, and find methods in InMemoryDataTable ([a96f4a6](https://github.com/expressots/expressots/commit/a96f4a6076ca7aebbac853317006f67de5daf9d2))
10
+
1
11
  ## [3.0.0-beta.1](https://github.com/expressots/expressots/compare/2.16.2...2.17.0) (2024-11-17)
2
12
 
3
13
  ### Features
@@ -32,6 +32,7 @@ const METADATA_KEY = __importStar(require("../constants/metadata_keys"));
32
32
  * @public API
33
33
  */
34
34
  function injectable() {
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
36
  return function (target) {
36
37
  if (Reflect.hasOwnMetadata(METADATA_KEY.PARAM_TYPES, target)) {
37
38
  throw new Error(ERRORS_MSGS.DUPLICATED_INJECTABLE_DECORATOR);
@@ -8,102 +8,48 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.BaseRepository = void 0;
13
16
  const inversify_1 = require("../../di/inversify");
14
- const db_in_memory_provider_1 = require("./db-in-memory.provider");
15
17
  /**
16
- * Base Repository Class
17
- *
18
- * This class provides the basic functionalities to interact with an in-memory database.
19
- *
20
- * @decorator @provide(BaseRepository)
18
+ * Base repository class using the repository pattern.
19
+ * @template T - The type of entity to be stored in the repository.
20
+ * @public API
21
21
  */
22
- class BaseRepository {
23
- /**
24
- * Constructor
25
- * @param tableName - The name of the table to interact with.
26
- *
27
- */
28
- constructor(tableName) {
29
- this.tableName = tableName;
22
+ let BaseRepository = class BaseRepository {
23
+ constructor(dataProvider, tableName) {
24
+ this.dataTable = dataProvider.getTable(tableName);
25
+ this.entityName = tableName;
26
+ }
27
+ async create(item) {
28
+ return this.dataTable.insert(item);
30
29
  }
31
- /**
32
- * Getter for the table
33
- * @returns {T[]} - An array of entities.
34
- */
35
- get table() {
36
- return [...this.inMemoryDB.getTable(this.tableName)];
30
+ async update(item) {
31
+ return this.dataTable.update(item);
37
32
  }
38
- /**
39
- * create Method
40
- * @param item - The entity to be created.
41
- * @returns {T | null} - The created entity or null if the entity already exists.
42
- * @throws {Error} - If the entity already exists.
43
- */
44
- create(item) {
45
- const existingItem = this.table.find((i) => i.id === item.id);
46
- if (existingItem) {
47
- throw new Error(`Object with id ${item.id} already exists`);
48
- }
49
- this.inMemoryDB.getTable(this.tableName).push(item);
50
- this.inMemoryDB.printTable(this.tableName);
51
- return item;
33
+ async delete(id) {
34
+ return this.dataTable.delete(id);
52
35
  }
53
- /**
54
- * delete Method
55
- * @param id - The id of the entity to be deleted.
56
- * @returns {boolean} - True if the entity was deleted, false otherwise.
57
- * @throws {Error} - If the entity does not exist.
58
- */
59
- delete(id) {
60
- const db = this.inMemoryDB.getTable(this.tableName);
61
- const index = db.findIndex((item) => item.id === id);
62
- if (index !== -1) {
63
- db.splice(index, 1);
64
- this.inMemoryDB.printTable(this.tableName);
65
- return true;
66
- }
67
- return false;
36
+ async find(id) {
37
+ return this.dataTable.find(id);
68
38
  }
69
- /**
70
- * update Method
71
- * @param item - The entity to be updated.
72
- * @returns {T | null} - The updated entity or null if the entity does not exist
73
- * @throws {Error} - If the entity does not exist.
74
- */
75
- update(item) {
76
- const db = this.inMemoryDB.getTable(this.tableName);
77
- const index = db.findIndex((i) => i.id === item.id);
78
- if (index !== -1) {
79
- db[index] = item;
80
- this.inMemoryDB.printTable(this.tableName);
81
- return item;
82
- }
83
- return null;
39
+ async findAll() {
40
+ return this.dataTable.findAll();
84
41
  }
85
- /**
86
- * find Method
87
- * @param id - The id of the entity to find.
88
- * @returns {T | null} - The entity if it exists, null otherwise
89
- * @throws {Error} - If the entity does not exist.
90
- */
91
- find(id) {
92
- const item = this.table.find((item) => item.id === id);
93
- this.inMemoryDB.printTable(this.tableName);
94
- return item || null;
42
+ async query(predicate) {
43
+ return this.dataTable.query(predicate);
95
44
  }
96
- /**
97
- * findAll Method
98
- * @returns {T[] | null} - An array of entities or null if the table is empty.
99
- */
100
- findAll() {
101
- this.inMemoryDB.printTable(this.tableName);
102
- return this.table;
45
+ async transaction(actions) {
46
+ await this.dataTable.transaction(actions);
103
47
  }
104
- }
48
+ };
105
49
  exports.BaseRepository = BaseRepository;
106
- __decorate([
107
- (0, inversify_1.inject)(db_in_memory_provider_1.InMemoryDB),
108
- __metadata("design:type", db_in_memory_provider_1.InMemoryDB)
109
- ], BaseRepository.prototype, "inMemoryDB", void 0);
50
+ exports.BaseRepository = BaseRepository = __decorate([
51
+ (0, inversify_1.injectable)(),
52
+ __param(0, (0, inversify_1.inject)("IDataProvider")),
53
+ __param(1, (0, inversify_1.unmanaged)()),
54
+ __metadata("design:paramtypes", [Object, String])
55
+ ], BaseRepository);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -6,80 +6,109 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
7
  };
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.InMemoryDB = void 0;
9
+ exports.InMemoryDataTable = exports.InMemoryDataProvider = void 0;
10
10
  const inversify_1 = require("../../di/inversify");
11
+ const db_in_memory_types_1 = require("./db-in-memory.types");
11
12
  /**
12
- * InMemoryDB Class
13
- *
14
- * This class and its methods offer functionalities to simulate an in-memory database.
15
- * It is particularly useful for developers starting with ExpressoTS without any database connection.
16
- *
17
- * @decorator @provideSingleton(InMemoryDB)
13
+ * In-memory data provider implementation.
18
14
  * @public API
19
15
  */
20
- let InMemoryDB = class InMemoryDB {
16
+ let InMemoryDataProvider = class InMemoryDataProvider {
21
17
  constructor() {
22
18
  this.name = "In Memory DB Provider";
23
19
  this.version = "3.0.0";
24
20
  this.author = "Richard Zampieri";
25
21
  this.repo = "https://github.com/expressots/expressots";
26
- this.tables = {};
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ this.tables = new Map();
27
24
  }
28
- /**
29
- * getTable Method
30
- *
31
- * Retrieves a table by its name from the in-memory database.
32
- *
33
- * @param tableName - The name of the table to retrieve.
34
- * @returns {IEntity[]} - An array of entities.
35
- * @public API
36
- */
37
25
  getTable(tableName) {
38
- if (!this.tables[tableName]) {
39
- this.tables[tableName] = [];
26
+ if (!this.tables.has(tableName)) {
27
+ this.tables.set(tableName, new InMemoryDataTable(tableName));
40
28
  }
41
- return this.tables[tableName];
29
+ return this.tables.get(tableName);
42
30
  }
43
- /**
44
- * showTables Method
45
- *
46
- * Prints a list of all tables in the in-memory database to the standard output.
47
- * @public API
48
- */
49
- showTables() {
50
- if (!this.tables) {
51
- process.stdout.write("No tables exist.");
52
- return;
31
+ };
32
+ exports.InMemoryDataProvider = InMemoryDataProvider;
33
+ exports.InMemoryDataProvider = InMemoryDataProvider = __decorate([
34
+ (0, inversify_1.injectable)()
35
+ ], InMemoryDataProvider);
36
+ /**
37
+ * In-memory data table implementation.
38
+ */
39
+ class InMemoryDataTable {
40
+ constructor(tableName) {
41
+ this.items = new Map();
42
+ this.transactionStack = [];
43
+ this.tableName = tableName;
44
+ }
45
+ async insert(item) {
46
+ if (this.items.has(item.id)) {
47
+ throw new db_in_memory_types_1.EntityAlreadyExistsError(this.tableName, item.id);
53
48
  }
54
- process.stdout.write("List of tables:");
55
- for (const tableName in this.tables) {
56
- process.stdout.write(`\n- ${tableName}`);
49
+ this.items.set(item.id, item);
50
+ return item;
51
+ }
52
+ async insertMany(items) {
53
+ const insertedItems = [];
54
+ for (const item of items) {
55
+ const insertedItem = await this.insert(item);
56
+ insertedItems.push(insertedItem);
57
57
  }
58
+ return insertedItems;
58
59
  }
59
- /**
60
- * printTable Method
61
- *
62
- * Prints all records in a specific table to the console.
63
- * If the table doesn't exist or is empty, it notifies the user.
64
- *
65
- * @param tableName - The name of the table to print.
66
- * @public API
67
- */
68
- printTable(tableName) {
69
- if (!this.tables) {
70
- process.stdout.write("No tables exist.");
71
- return;
60
+ async update(item) {
61
+ if (!this.items.has(item.id)) {
62
+ throw new db_in_memory_types_1.EntityNotFoundError(this.tableName, item.id);
72
63
  }
73
- const table = this.getTable(tableName);
74
- if (table.length === 0) {
75
- process.stdout.write(`Table '${tableName}' is empty.`);
76
- return;
64
+ this.items.set(item.id, item);
65
+ return item;
66
+ }
67
+ async delete(id) {
68
+ if (!this.items.has(id)) {
69
+ throw new db_in_memory_types_1.EntityNotFoundError(this.tableName, id);
77
70
  }
78
- process.stdout.write(`\nRecords in table '${tableName}':\n`);
79
- console.table(table);
71
+ return this.items.delete(id);
80
72
  }
81
- };
82
- exports.InMemoryDB = InMemoryDB;
83
- exports.InMemoryDB = InMemoryDB = __decorate([
84
- (0, inversify_1.injectable)()
85
- ], InMemoryDB);
73
+ async find(id) {
74
+ const item = this.items.get(id);
75
+ if (!item) {
76
+ throw new db_in_memory_types_1.EntityNotFoundError(this.tableName, id);
77
+ }
78
+ return item;
79
+ }
80
+ async findAll() {
81
+ return Array.from(this.items.values());
82
+ }
83
+ async query(predicate) {
84
+ return Array.from(this.items.values()).filter(predicate);
85
+ }
86
+ async transaction(actions) {
87
+ this.beginTransaction();
88
+ try {
89
+ await actions();
90
+ this.commitTransaction();
91
+ }
92
+ catch (error) {
93
+ this.rollbackTransaction();
94
+ throw error;
95
+ }
96
+ }
97
+ beginTransaction() {
98
+ const snapshot = new Map(this.items);
99
+ this.transactionStack.push(snapshot);
100
+ }
101
+ commitTransaction() {
102
+ this.transactionStack.pop();
103
+ }
104
+ rollbackTransaction() {
105
+ const snapshot = this.transactionStack.pop();
106
+ if (snapshot) {
107
+ this.items = snapshot;
108
+ }
109
+ else {
110
+ throw new Error("No transaction to rollback.");
111
+ }
112
+ }
113
+ }
114
+ exports.InMemoryDataTable = InMemoryDataTable;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityAlreadyExistsError = exports.EntityNotFoundError = void 0;
4
+ /**
5
+ * Error thrown when an entity is not found.
6
+ * @public API
7
+ */
8
+ class EntityNotFoundError extends Error {
9
+ constructor(entityName, id) {
10
+ super(`${entityName} with ID ${id} not found.`);
11
+ this.name = "EntityNotFoundError";
12
+ }
13
+ }
14
+ exports.EntityNotFoundError = EntityNotFoundError;
15
+ /**
16
+ * Error thrown when an entity already exists.
17
+ * @public API
18
+ */
19
+ class EntityAlreadyExistsError extends Error {
20
+ constructor(entityName, id) {
21
+ super(`${entityName} with ID ${id} already exists.`);
22
+ this.name = "EntityAlreadyExistsError";
23
+ }
24
+ }
25
+ exports.EntityAlreadyExistsError = EntityAlreadyExistsError;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseRepository = exports.EntityAlreadyExistsError = exports.EntityNotFoundError = exports.InMemoryDataTable = exports.InMemoryDataProvider = void 0;
4
+ var db_in_memory_provider_1 = require("./db-in-memory.provider");
5
+ Object.defineProperty(exports, "InMemoryDataProvider", { enumerable: true, get: function () { return db_in_memory_provider_1.InMemoryDataProvider; } });
6
+ Object.defineProperty(exports, "InMemoryDataTable", { enumerable: true, get: function () { return db_in_memory_provider_1.InMemoryDataTable; } });
7
+ var db_in_memory_types_1 = require("./db-in-memory.types");
8
+ Object.defineProperty(exports, "EntityNotFoundError", { enumerable: true, get: function () { return db_in_memory_types_1.EntityNotFoundError; } });
9
+ Object.defineProperty(exports, "EntityAlreadyExistsError", { enumerable: true, get: function () { return db_in_memory_types_1.EntityAlreadyExistsError; } });
10
+ var base_repo_repository_1 = require("./base-repo.repository");
11
+ Object.defineProperty(exports, "BaseRepository", { enumerable: true, get: function () { return base_repo_repository_1.BaseRepository; } });
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseRepository = exports.InMemoryDB = exports.ValidateDTO = exports.Env = exports.Logger = exports.ProviderManager = void 0;
17
+ exports.ValidateDTO = exports.Env = exports.Logger = exports.ProviderManager = void 0;
4
18
  var provider_manager_1 = require("./provider-manager");
5
19
  Object.defineProperty(exports, "ProviderManager", { enumerable: true, get: function () { return provider_manager_1.ProviderManager; } });
6
20
  var logger_provider_1 = require("./logger/logger.provider");
@@ -9,7 +23,4 @@ var env_validator_provider_1 = require("./environment/env-validator.provider");
9
23
  Object.defineProperty(exports, "Env", { enumerable: true, get: function () { return env_validator_provider_1.EnvValidatorProvider; } });
10
24
  var dto_validator_provider_1 = require("./dto-validator/dto-validator.provider");
11
25
  Object.defineProperty(exports, "ValidateDTO", { enumerable: true, get: function () { return dto_validator_provider_1.ValidateDTO; } });
12
- var db_in_memory_provider_1 = require("./db-in-memory/db-in-memory.provider");
13
- Object.defineProperty(exports, "InMemoryDB", { enumerable: true, get: function () { return db_in_memory_provider_1.InMemoryDB; } });
14
- var base_repo_repository_1 = require("./db-in-memory/base-repo.repository");
15
- Object.defineProperty(exports, "BaseRepository", { enumerable: true, get: function () { return base_repo_repository_1.BaseRepository; } });
26
+ __exportStar(require("./db-in-memory"), exports);
@@ -14,40 +14,79 @@ class ProviderManager {
14
14
  }
15
15
  /**
16
16
  * Register a provider with the container.
17
- * @param serviceIdentifier - The service identifier for the provider.
18
- * @param scope - The binding scope for the provider.
19
17
  * @public API
20
18
  */
21
- register(serviceIdentifier, scope = inversify_1.BindingScopeEnum.Request) {
19
+ register(serviceIdentifier, constructorOrScope, scope = inversify_1.BindingScopeEnum.Request) {
22
20
  if (this.container.isBound(serviceIdentifier)) {
23
21
  this.logger.warn(`${serviceIdentifier.name} already registered`, "provider-manager");
24
22
  return;
25
23
  }
24
+ let binding;
25
+ if (typeof constructorOrScope === "function") {
26
+ // Overload where constructor is provided
27
+ const constructor = constructorOrScope;
28
+ const scopeDefinition = scope || inversify_1.BindingScopeEnum.Transient;
29
+ binding = this.container.bind(serviceIdentifier).to(constructor);
30
+ this.applyScope(binding, scopeDefinition);
31
+ }
32
+ else {
33
+ const scopeDefinition = constructorOrScope ||
34
+ inversify_1.BindingScopeEnum.Transient;
35
+ binding = this.container.bind(serviceIdentifier).toSelf();
36
+ this.applyScope(binding, scopeDefinition);
37
+ }
38
+ }
39
+ /**
40
+ * Get a provider from the container.
41
+ * @param serviceIdentifier - The service identifier to get from the container.
42
+ * @returns An instance of the provider.
43
+ * @public API
44
+ */
45
+ get(serviceIdentifier) {
46
+ if (!this.container.isBound(serviceIdentifier)) {
47
+ this.logger.error(`${this.getServiceIdentifierName(serviceIdentifier)} not registered`, "ProviderManager");
48
+ throw new Error(`Provider ${this.getServiceIdentifierName(serviceIdentifier)} not registered`);
49
+ }
50
+ return this.container.get(serviceIdentifier);
51
+ }
52
+ /**
53
+ * Apply the scope to the binding.
54
+ * @param binding - The binding to apply the scope to.
55
+ * @param scope - The scope to apply.
56
+ * @private
57
+ */
58
+ applyScope(binding, scope) {
26
59
  switch (scope) {
27
60
  case inversify_1.BindingScopeEnum.Singleton:
28
- this.container.bind(serviceIdentifier).toSelf().inSingletonScope();
29
- break;
30
- case inversify_1.BindingScopeEnum.Transient:
31
- this.container.bind(serviceIdentifier).toSelf().inTransientScope();
61
+ binding.inSingletonScope();
32
62
  break;
33
63
  case inversify_1.BindingScopeEnum.Request:
34
- this.container.bind(serviceIdentifier).toSelf().inRequestScope();
64
+ binding.inRequestScope();
65
+ break;
66
+ case inversify_1.BindingScopeEnum.Transient:
67
+ default:
68
+ binding.inTransientScope();
35
69
  break;
36
70
  }
37
71
  }
38
72
  /**
39
- * Get a provider from the container.
40
- * @param provider - The provider class to get from the container.
41
- * @returns An instance of the provider.
42
- * @public API
73
+ * Get the name of the service identifier for logging purposes.
74
+ * @param serviceIdentifier - The service identifier.
75
+ * @returns The name of the service identifier.
76
+ * @private
43
77
  */
44
- get(provider) {
45
- const serviceIdentifier = this.container.get(provider);
46
- if (!serviceIdentifier) {
47
- this.logger.error(`${provider.name} not registered`, "provider-manager");
48
- throw new Error(`Provider ${provider.name} not registered`);
78
+ getServiceIdentifierName(
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
+ serviceIdentifier) {
81
+ if (typeof serviceIdentifier === "function") {
82
+ return serviceIdentifier.name;
83
+ }
84
+ else if (typeof serviceIdentifier === "symbol") {
85
+ return serviceIdentifier.toString();
86
+ }
87
+ else {
88
+ return serviceIdentifier;
49
89
  }
50
- return serviceIdentifier;
51
90
  }
52
91
  }
53
92
  exports.ProviderManager = ProviderManager;
@@ -3,5 +3,5 @@
3
3
  * @returns A decorator function
4
4
  * @public API
5
5
  */
6
- declare function injectable(): <T extends abstract new (...args: Array<unknown>) => unknown>(target: T) => T;
6
+ declare function injectable(): <T extends abstract new (...args: any) => unknown>(target: T) => T;
7
7
  export { injectable };
@@ -1,63 +1,18 @@
1
- import { IMemoryDBEntity } from "./db-in-memory.provider";
2
- export interface IBaseRepository<T extends IMemoryDBEntity> {
3
- create(item: T): T | null;
4
- update(item: T): T | null;
5
- delete(id: string): boolean;
6
- find(id: string): T | null;
7
- findAll(): Array<T> | null;
8
- }
1
+ import { IDataProvider, IDataTable, IEntity, IRepository } from "./db-in-memory.interface";
9
2
  /**
10
- * Base Repository Class
11
- *
12
- * This class provides the basic functionalities to interact with an in-memory database.
13
- *
14
- * @decorator @provide(BaseRepository)
3
+ * Base repository class using the repository pattern.
4
+ * @template T - The type of entity to be stored in the repository.
5
+ * @public API
15
6
  */
16
- export declare class BaseRepository<T extends IMemoryDBEntity> implements IBaseRepository<T> {
17
- private inMemoryDB;
18
- private tableName;
19
- /**
20
- * Constructor
21
- * @param tableName - The name of the table to interact with.
22
- *
23
- */
24
- constructor(tableName: string);
25
- /**
26
- * Getter for the table
27
- * @returns {T[]} - An array of entities.
28
- */
29
- protected get table(): Array<T>;
30
- /**
31
- * create Method
32
- * @param item - The entity to be created.
33
- * @returns {T | null} - The created entity or null if the entity already exists.
34
- * @throws {Error} - If the entity already exists.
35
- */
36
- create(item: T): T | null;
37
- /**
38
- * delete Method
39
- * @param id - The id of the entity to be deleted.
40
- * @returns {boolean} - True if the entity was deleted, false otherwise.
41
- * @throws {Error} - If the entity does not exist.
42
- */
43
- delete(id: string): boolean;
44
- /**
45
- * update Method
46
- * @param item - The entity to be updated.
47
- * @returns {T | null} - The updated entity or null if the entity does not exist
48
- * @throws {Error} - If the entity does not exist.
49
- */
50
- update(item: T): T | null;
51
- /**
52
- * find Method
53
- * @param id - The id of the entity to find.
54
- * @returns {T | null} - The entity if it exists, null otherwise
55
- * @throws {Error} - If the entity does not exist.
56
- */
57
- find(id: string): T | null;
58
- /**
59
- * findAll Method
60
- * @returns {T[] | null} - An array of entities or null if the table is empty.
61
- */
62
- findAll(): Array<T> | null;
7
+ export declare class BaseRepository<T extends IEntity> implements IRepository<T> {
8
+ protected dataTable: IDataTable<T>;
9
+ protected entityName: string;
10
+ constructor(dataProvider: IDataProvider, tableName: string);
11
+ create(item: T): Promise<T>;
12
+ update(item: T): Promise<T>;
13
+ delete(id: string): Promise<boolean>;
14
+ find(id: string): Promise<T>;
15
+ findAll(): Promise<Array<T>>;
16
+ query(predicate: (item: T) => boolean): Promise<Array<T>>;
17
+ transaction(actions: () => Promise<void>): Promise<void>;
63
18
  }
@@ -0,0 +1,43 @@
1
+ import { IProvider } from "../provider-manager";
2
+ export interface IEntity {
3
+ id?: string;
4
+ }
5
+ /**
6
+ * IRepository Interface
7
+ * Generic interface that defines the structure of a repository.
8
+ * @template T - The type of entity to be stored in the repository.
9
+ * @public API
10
+ */
11
+ export interface IRepository<T extends IEntity> {
12
+ create(item: T): Promise<T>;
13
+ update(item: T): Promise<T>;
14
+ delete(id: string): Promise<boolean>;
15
+ find(id: string): Promise<T>;
16
+ findAll(): Promise<Array<T>>;
17
+ query(predicate: (item: T) => boolean): Promise<Array<T>>;
18
+ transaction(actions: () => Promise<void>): Promise<void>;
19
+ }
20
+ /**
21
+ * IDataTable Interface for CRUD operations
22
+ * Generic interface that defines the structure of a data table.
23
+ * @template T - The type of entity to be stored in the data table.
24
+ * @public API
25
+ */
26
+ export interface IDataTable<T extends IEntity> {
27
+ insert(item: T): Promise<T>;
28
+ insertMany(items: Array<T>): Promise<Array<T>>;
29
+ update(item: T): Promise<T>;
30
+ delete(id: string): Promise<boolean>;
31
+ find(id: string): Promise<T>;
32
+ findAll(): Promise<Array<T>>;
33
+ query(predicate: (item: T) => boolean): Promise<Array<T>>;
34
+ transaction(actions: () => Promise<void>): Promise<void>;
35
+ }
36
+ /**
37
+ * IDataProvider Interface for obtaining data tables
38
+ * Generic interface that defines the structure of a data provider.
39
+ * @public API
40
+ */
41
+ export interface IDataProvider extends IProvider {
42
+ getTable<T extends IEntity>(tableName: string): IDataTable<T>;
43
+ }
@@ -1,47 +1,33 @@
1
- import { IProvider } from "../provider-manager";
2
- export interface IMemoryDBEntity {
3
- id: string;
4
- }
1
+ import { IDataProvider, IEntity, IDataTable } from "./db-in-memory.interface";
5
2
  /**
6
- * InMemoryDB Class
7
- *
8
- * This class and its methods offer functionalities to simulate an in-memory database.
9
- * It is particularly useful for developers starting with ExpressoTS without any database connection.
10
- *
11
- * @decorator @provideSingleton(InMemoryDB)
3
+ * In-memory data provider implementation.
12
4
  * @public API
13
5
  */
14
- export declare class InMemoryDB implements IProvider {
6
+ export declare class InMemoryDataProvider implements IDataProvider {
15
7
  name: string;
16
8
  version: string;
17
9
  author: string;
18
10
  repo: string;
19
11
  private tables;
20
- /**
21
- * getTable Method
22
- *
23
- * Retrieves a table by its name from the in-memory database.
24
- *
25
- * @param tableName - The name of the table to retrieve.
26
- * @returns {IEntity[]} - An array of entities.
27
- * @public API
28
- */
29
- getTable(tableName: string): Array<IMemoryDBEntity>;
30
- /**
31
- * showTables Method
32
- *
33
- * Prints a list of all tables in the in-memory database to the standard output.
34
- * @public API
35
- */
36
- showTables(): void;
37
- /**
38
- * printTable Method
39
- *
40
- * Prints all records in a specific table to the console.
41
- * If the table doesn't exist or is empty, it notifies the user.
42
- *
43
- * @param tableName - The name of the table to print.
44
- * @public API
45
- */
46
- printTable(tableName: string): void;
12
+ getTable<T extends IEntity>(tableName: string): IDataTable<T>;
13
+ }
14
+ /**
15
+ * In-memory data table implementation.
16
+ */
17
+ export declare class InMemoryDataTable<T extends IEntity> implements IDataTable<T> {
18
+ private items;
19
+ private tableName;
20
+ private transactionStack;
21
+ constructor(tableName: string);
22
+ insert(item: T): Promise<T>;
23
+ insertMany(items: Array<T>): Promise<Array<T>>;
24
+ update(item: T): Promise<T>;
25
+ delete(id: string): Promise<boolean>;
26
+ find(id: string): Promise<T>;
27
+ findAll(): Promise<Array<T>>;
28
+ query(predicate: (item: T) => boolean): Promise<Array<T>>;
29
+ transaction(actions: () => Promise<void>): Promise<void>;
30
+ private beginTransaction;
31
+ private commitTransaction;
32
+ private rollbackTransaction;
47
33
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Error thrown when an entity is not found.
3
+ * @public API
4
+ */
5
+ export declare class EntityNotFoundError extends Error {
6
+ constructor(entityName: string, id: string);
7
+ }
8
+ /**
9
+ * Error thrown when an entity already exists.
10
+ * @public API
11
+ */
12
+ export declare class EntityAlreadyExistsError extends Error {
13
+ constructor(entityName: string, id: string);
14
+ }
@@ -0,0 +1,4 @@
1
+ export { InMemoryDataProvider, InMemoryDataTable, } from "./db-in-memory.provider";
2
+ export { EntityNotFoundError, EntityAlreadyExistsError, } from "./db-in-memory.types";
3
+ export { BaseRepository } from "./base-repo.repository";
4
+ export { IEntity, IRepository, IDataTable, IDataProvider, } from "./db-in-memory.interface";
@@ -2,5 +2,4 @@ export { IProvider, ProviderManager } from "./provider-manager";
2
2
  export { Logger } from "./logger/logger.provider";
3
3
  export { EnvValidatorProvider as Env } from "./environment/env-validator.provider";
4
4
  export { ValidateDTO } from "./dto-validator/dto-validator.provider";
5
- export { InMemoryDB, IMemoryDBEntity, } from "./db-in-memory/db-in-memory.provider";
6
- export { BaseRepository, IBaseRepository, } from "./db-in-memory/base-repo.repository";
5
+ export * from "./db-in-memory";
@@ -9,7 +9,6 @@ export interface IProvider {
9
9
  author: string;
10
10
  repo: string;
11
11
  }
12
- type ClassType<T> = new () => T;
13
12
  /**
14
13
  * ProviderManager Class - A class for managing dependency injection providers.
15
14
  * @public API
@@ -19,18 +18,39 @@ export declare class ProviderManager {
19
18
  private logger;
20
19
  constructor(container: interfaces.Container);
21
20
  /**
22
- * Register a provider with the container.
21
+ * Register a provider by binding it to itself with optional scope.
23
22
  * @param serviceIdentifier - The service identifier for the provider.
24
- * @param scope - The binding scope for the provider.
23
+ * @param scope - The binding scope.
25
24
  * @public API
26
25
  */
27
- register(serviceIdentifier: interfaces.ServiceIdentifier<unknown>, scope?: interfaces.BindingScope): void;
26
+ register<T>(serviceIdentifier: interfaces.ServiceIdentifier<T>, scope?: interfaces.BindingScope): void;
27
+ /**
28
+ * Overload: Register a provider by binding a service identifier to a specific implementation with optional scope.
29
+ * @param serviceIdentifier - The service identifier for the provider.
30
+ * @param constructor - The implementation class.
31
+ * @param scope - The binding scope.
32
+ * @public API
33
+ */
34
+ register<T>(serviceIdentifier: interfaces.ServiceIdentifier<T>, constructor: interfaces.Newable<T>, scope?: interfaces.BindingScope): void;
28
35
  /**
29
36
  * Get a provider from the container.
30
- * @param provider - The provider class to get from the container.
37
+ * @param serviceIdentifier - The service identifier to get from the container.
31
38
  * @returns An instance of the provider.
32
39
  * @public API
33
40
  */
34
- get<P>(provider: ClassType<P>): P;
41
+ get<T>(serviceIdentifier: interfaces.ServiceIdentifier<T>): T;
42
+ /**
43
+ * Apply the scope to the binding.
44
+ * @param binding - The binding to apply the scope to.
45
+ * @param scope - The scope to apply.
46
+ * @private
47
+ */
48
+ private applyScope;
49
+ /**
50
+ * Get the name of the service identifier for logging purposes.
51
+ * @param serviceIdentifier - The service identifier.
52
+ * @returns The name of the service identifier.
53
+ * @private
54
+ */
55
+ private getServiceIdentifierName;
35
56
  }
36
- export {};
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressots/core",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.0-beta.3",
4
4
  "description": "Expressots - modern, fast, lightweight nodejs web framework (@core)",
5
5
  "author": "Richard Zampieri",
6
6
  "main": "./lib/cjs/index.js",
@@ -71,7 +71,7 @@
71
71
  "@codecov/vite-plugin": "^0.0.1-beta.5",
72
72
  "@commitlint/cli": "19.2.1",
73
73
  "@commitlint/config-conventional": "19.1.0",
74
- "@expressots/shared": "0.2.0",
74
+ "@expressots/shared": "3.0.0-beta.3",
75
75
  "@release-it/conventional-changelog": "8.0.1",
76
76
  "@types/express": "4.17.21",
77
77
  "@types/jest": "^29.5.14",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressots/core",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.0-beta.3",
4
4
  "description": "Expressots - modern, fast, lightweight nodejs web framework (@core)",
5
5
  "author": "Richard Zampieri",
6
6
  "main": "./lib/cjs/index.js",
@@ -71,7 +71,7 @@
71
71
  "@codecov/vite-plugin": "^0.0.1-beta.5",
72
72
  "@commitlint/cli": "19.2.1",
73
73
  "@commitlint/config-conventional": "19.1.0",
74
- "@expressots/shared": "0.2.0",
74
+ "@expressots/shared": "3.0.0-beta.3",
75
75
  "@release-it/conventional-changelog": "8.0.1",
76
76
  "@types/express": "4.17.21",
77
77
  "@types/jest": "^29.5.14",