@smartsoft001/mongo 2.75.0 → 2.80.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartsoft001/mongo",
3
- "version": "2.75.0",
3
+ "version": "2.80.0",
4
4
  "description": "Utils to mongo",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,5 +16,25 @@
16
16
  "bugs": {
17
17
  "url": "https://github.com/emiljuchnikowski/smartsoft/issues"
18
18
  },
19
- "homepage": "https://github.com/emiljuchnikowski/smartsoft#readme"
20
- }
19
+ "homepage": "https://github.com/emiljuchnikowski/smartsoft#readme",
20
+ "dependencies": {
21
+ "@angular/core": "20.1.0",
22
+ "@jest/globals": "29.7.0",
23
+ "@nestjs/common": "^11.1.5",
24
+ "flatted": "3.3.3",
25
+ "guid-typescript": "^1.0.9",
26
+ "lodash": "4.17.21",
27
+ "md5": "^2.3.0",
28
+ "mongodb": "^5.9.2",
29
+ "reflect-metadata": "^0.2.1",
30
+ "rxjs": "^7.8.1",
31
+ "tslib": "^2.3.0"
32
+ },
33
+ "resolutions": {
34
+ "paypal-rest-sdk": "1.8.1",
35
+ "tslib": "^2.3.0",
36
+ "zone.js": "~0.15.0"
37
+ },
38
+ "main": "./index.cjs",
39
+ "type": "commonjs"
40
+ }
@@ -0,0 +1,10 @@
1
+ export declare class MongoConfig {
2
+ host?: string;
3
+ port?: number;
4
+ database: string;
5
+ username?: string;
6
+ password?: string;
7
+ collection?: string;
8
+ url?: string;
9
+ type?: any;
10
+ }
@@ -0,0 +1,7 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { MongoConfig } from './mongo.config';
3
+ export declare class MongoModule {
4
+ static forRoot(config: MongoConfig): DynamicModule;
5
+ }
6
+ export { MongoConfig } from './mongo.config';
7
+ export { MongoItemRepository } from './repositories/item.repository';
@@ -0,0 +1,12 @@
1
+ import { ClientSession } from 'mongodb';
2
+ import { ITransaction, IUnitOfWork } from '@smartsoft001/domain-core';
3
+ import { MongoConfig } from './mongo.module';
4
+ export interface IMongoTransaction extends ITransaction {
5
+ session: ClientSession;
6
+ }
7
+ export declare class MongoUnitOfWork extends IUnitOfWork {
8
+ private config;
9
+ constructor(config: MongoConfig);
10
+ scope(definition: (transaction: ITransaction) => Promise<void>): Promise<void>;
11
+ private getUrl;
12
+ }
@@ -0,0 +1,2 @@
1
+ import { MongoConfig } from './mongo.module';
2
+ export declare function getMongoUrl(config: MongoConfig): string;
@@ -0,0 +1,27 @@
1
+ import { IEntity, IAttachmentRepository } from '@smartsoft001/domain-core';
2
+ import { Readable, Stream } from 'stream';
3
+ import { MongoConfig } from '../mongo.module';
4
+ export declare class MongoAttachmentRepository<T extends IEntity<string>> extends IAttachmentRepository<T> {
5
+ private config;
6
+ constructor(config: MongoConfig);
7
+ upload(data: {
8
+ id: string;
9
+ fileName: string;
10
+ stream: Stream;
11
+ mimeType: string;
12
+ encoding: string;
13
+ }, options?: {
14
+ streamCallback?: (r: any) => void;
15
+ }): Promise<void>;
16
+ getInfo(id: string): Promise<{
17
+ fileName: string;
18
+ contentType: string;
19
+ length: number;
20
+ }>;
21
+ getStream(id: string, options: {
22
+ start: number;
23
+ end: number;
24
+ } | undefined): Promise<Readable>;
25
+ delete(id: string): Promise<void>;
26
+ private getUrl;
27
+ }
@@ -0,0 +1,21 @@
1
+ export interface IItemCreateData {
2
+ id: string;
3
+ type: 'create';
4
+ data: any;
5
+ }
6
+ export interface IItemUpdateData {
7
+ id: string;
8
+ type: 'update';
9
+ data: {
10
+ removedFields: Array<string>;
11
+ updatedFields: {
12
+ [key: string]: any;
13
+ };
14
+ };
15
+ }
16
+ export interface IItemDeleteData {
17
+ id: string;
18
+ type: 'delete';
19
+ }
20
+ export type ItemChangedData = IItemCreateData | IItemUpdateData | IItemDeleteData;
21
+ export type ItemChangedDataType = 'create' | 'update' | 'delete';
@@ -0,0 +1,51 @@
1
+ import { Collection, Db } from 'mongodb';
2
+ import { Observable } from 'rxjs';
3
+ import { IEntity, IItemRepository, IItemRepositoryOptions, ISpecification } from '@smartsoft001/domain-core';
4
+ import { IUser } from '@smartsoft001/users';
5
+ import { MongoConfig } from '../mongo.module';
6
+ import { ItemChangedData } from './interfaces';
7
+ export declare class MongoItemRepository<T extends IEntity<string>> extends IItemRepository<T> {
8
+ protected config: MongoConfig;
9
+ constructor(config: MongoConfig);
10
+ create(item: T, user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
11
+ clear(user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
12
+ createMany(list: T[], user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
13
+ update(item: T, user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
14
+ updatePartial(item: Partial<T> & {
15
+ id: string;
16
+ }, user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
17
+ updatePartialManyByCriteria(criteria: any, set: Partial<T>, user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
18
+ updatePartialManyBySpecification(spec: ISpecification, set: Partial<T>, user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
19
+ delete(id: string, user: IUser, repoOptions?: IItemRepositoryOptions): Promise<void>;
20
+ getById(id: string, repoOptions?: IItemRepositoryOptions): Promise<T>;
21
+ getByCriteria(criteria: any, options?: any): Promise<{
22
+ data: T[];
23
+ totalCount: number;
24
+ }>;
25
+ getBySpecification(spec: ISpecification, options?: any): Promise<{
26
+ data: T[];
27
+ totalCount: number;
28
+ }>;
29
+ countByCriteria(criteria: any): Promise<number>;
30
+ countBySpecification(spec: ISpecification): Promise<number>;
31
+ changesByCriteria(criteria: {
32
+ id?: string;
33
+ }): Observable<ItemChangedData>;
34
+ protected getContext<TResult>(handler: (db: Db) => Promise<TResult>): Promise<TResult>;
35
+ protected getCount(criteria: any, collection: any): Promise<any>;
36
+ protected getInfo(id: string, collection: Collection<any>): Promise<any>;
37
+ protected getModelToCreate(item: T, user: IUser): T;
38
+ protected mapChangeType(dbType: string): any;
39
+ protected getModelToUpdate(item: {
40
+ id: string;
41
+ }, user: IUser, info: any): {
42
+ id: string;
43
+ };
44
+ protected getModelToResult(item: T): T;
45
+ protected getUrl(): string;
46
+ protected logChange(type: any, item: any, options: any, user: any, error: any): Promise<void>;
47
+ protected generateSearch(criteria: any): void;
48
+ protected convertIdInCriteria(criteria: any): void;
49
+ protected convertRegex(val: string): string;
50
+ protected collectionContext<T>(callback: (collection: Collection) => Promise<any>, repoOptions?: IItemRepositoryOptions): Promise<any>;
51
+ }
package/.eslintrc DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "extends": "../../../.eslintrc",
3
- "rules": {
4
-
5
- },
6
- "ignorePatterns": ["!**/*"],
7
- "overrides": [
8
- {
9
- "files": ["*.json"],
10
- "parser": "jsonc-eslint-parser"
11
- }
12
- ]
13
- }
package/jest.config.ts DELETED
@@ -1,27 +0,0 @@
1
- /* eslint-disable */
2
- export default {
3
- globals: {},
4
- transform: {
5
- '^.+\\.[tj]sx?$': [
6
- 'ts-jest',
7
- {
8
- tsconfig: '<rootDir>/tsconfig.spec.json',
9
- },
10
- ],
11
- },
12
- moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
13
- coverageDirectory: '../../../coverage/packages/shared/mongo',
14
- displayName: 'shared-mongo',
15
- testEnvironment: 'node',
16
- preset: '../../../jest.preset.js',
17
- /* TODO: Update to latest Jest snapshotFormat
18
- * By default Nx has kept the older style of Jest Snapshot formats
19
- * to prevent breaking of any existing tests with snapshots.
20
- * It's recommend you update to the latest format.
21
- * You can do this by removing snapshotFormat property
22
- * and running tests with --update-snapshot flag.
23
- * Example: From within the project directory, run "nx test --update-snapshot"
24
- * More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format
25
- */
26
- snapshotFormat: { escapeString: true, printBasicPrototype: true },
27
- };
package/project.json DELETED
@@ -1,48 +0,0 @@
1
- {
2
- "name": "shared-mongo",
3
- "$schema": "../../../node_modules/nx/schemas/project-schema.json",
4
- "sourceRoot": "packages/shared/mongo/src",
5
- "projectType": "library",
6
- "tags": ["scope:shared", "type:util"],
7
- "generators": {},
8
- "targets": {
9
- "lint": {
10
- "executor": "@nx/eslint:lint",
11
- "outputs": ["{options.outputFile}"],
12
- "options": {
13
- "lintFilePatterns": [
14
- "packages/shared/mongo/**/*.{ts,tsx,js,jsx}",
15
- "packages/shared/mongo/package.json"
16
- ]
17
- }
18
- },
19
- "test": {
20
- "executor": "@nx/jest:jest",
21
- "options": {
22
- "jestConfig": "packages/shared/mongo/jest.config.ts"
23
- },
24
- "outputs": ["{workspaceRoot}/coverage/packages/shared/mongo"]
25
- },
26
- "build": {
27
- "executor": "@nx/esbuild:esbuild",
28
- "outputs": ["{options.outputPath}"],
29
- "options": {
30
- "outputPath": "dist/packages/shared/mongo",
31
- "tsConfig": "packages/shared/mongo/tsconfig.lib.json",
32
- "packageJson": "packages/shared/mongo/package.json",
33
- "main": "packages/shared/mongo/src/index.ts",
34
- "assets": ["packages/shared/mongo/*.md"],
35
- "generatePackageJson": true,
36
- "format": ["cjs"]
37
- }
38
- },
39
- "deploy": {
40
- "executor": "ngx-deploy-npm:deploy",
41
- "options": {
42
- "access": "public",
43
- "distFolderPath": "dist/packages/shared/mongo"
44
- },
45
- "dependsOn": ["build"]
46
- }
47
- }
48
- }
@@ -1,10 +0,0 @@
1
- export class MongoConfig {
2
- host?: string;
3
- port?: number;
4
- database: string;
5
- username?: string;
6
- password?: string;
7
- collection?: string;
8
- url?: string;
9
- type?: any;
10
- }
@@ -1,32 +0,0 @@
1
- import { DynamicModule } from '@nestjs/common';
2
-
3
- import {
4
- IAttachmentRepository,
5
- IItemRepository,
6
- IUnitOfWork,
7
- } from '@smartsoft001/domain-core';
8
-
9
- import { MongoConfig } from './mongo.config';
10
- import { MongoUnitOfWork } from './mongo.unitofwork';
11
- import { MongoAttachmentRepository } from './repositories/attachment.repository';
12
- import { MongoItemRepository } from './repositories/item.repository';
13
-
14
- export class MongoModule {
15
- static forRoot(config: MongoConfig): DynamicModule {
16
- const providers = [
17
- { provide: MongoConfig, useValue: config },
18
- { provide: IItemRepository, useClass: MongoItemRepository },
19
- { provide: IAttachmentRepository, useClass: MongoAttachmentRepository },
20
- { provide: IUnitOfWork, useClass: MongoUnitOfWork },
21
- ];
22
-
23
- return {
24
- module: MongoModule,
25
- providers: providers,
26
- exports: providers,
27
- };
28
- }
29
- }
30
-
31
- export { MongoConfig } from './mongo.config';
32
- export { MongoItemRepository } from './repositories/item.repository';
@@ -1,84 +0,0 @@
1
- import { jest } from '@jest/globals';
2
- import { MongoClient, ClientSession, TransactionOptions } from 'mongodb';
3
-
4
- import { MongoConfig } from './mongo.config';
5
- import { IMongoTransaction, MongoUnitOfWork } from './mongo.unitofwork';
6
-
7
- const mockData: {
8
- config: MongoConfig;
9
- url: string;
10
- } = {
11
- config: {
12
- host: 'host',
13
- port: 4200,
14
- database: 'db-string',
15
- },
16
- url: 'mongodb://host:4200?authSource=db-string',
17
- };
18
-
19
- describe('shared-mongo: MongoUnitOfWork scope function', () => {
20
- let mockClient: Partial<MongoClient>;
21
- let mockSession: Partial<ClientSession>;
22
- let model: MongoUnitOfWork;
23
-
24
- beforeEach(() => {
25
- model = new MongoUnitOfWork(mockData.config);
26
-
27
- mockSession = {
28
- withTransaction: jest.fn(
29
- async <T>(
30
- callback: (session: ClientSession) => Promise<T>,
31
- options: TransactionOptions,
32
- ): Promise<T> => {
33
- return callback(mockSession as ClientSession); // Pass the mocked session
34
- },
35
- ) as ClientSession['withTransaction'],
36
- endSession: jest.fn(() => Promise.resolve()),
37
- };
38
-
39
- mockClient = {
40
- startSession: jest.fn(() => mockSession as ClientSession),
41
- close: jest.fn(() => Promise.resolve()),
42
- };
43
-
44
- jest
45
- .spyOn(MongoClient, 'connect')
46
- .mockResolvedValue(mockClient as MongoClient);
47
- });
48
-
49
- afterEach(() => {
50
- jest.restoreAllMocks();
51
- });
52
-
53
- it('should execute the definition within a transaction', async () => {
54
- const mockDefinition = jest.fn(async (transaction: IMongoTransaction) => {
55
- expect(transaction.session).toBe(mockSession);
56
- expect(transaction.connection).toBe(mockClient);
57
- });
58
-
59
- await expect(model.scope(mockDefinition)).resolves.not.toThrow();
60
-
61
- expect(MongoClient.connect).toHaveBeenCalledWith(mockData.url);
62
- expect(mockClient.startSession).toHaveBeenCalled();
63
- expect(mockSession.withTransaction).toHaveBeenCalled();
64
- expect(mockDefinition).toHaveBeenCalled();
65
- expect(mockSession.endSession).toHaveBeenCalled();
66
- expect(mockClient.close).toHaveBeenCalled();
67
- });
68
-
69
- it('should throw an error if the definition throws an error', async () => {
70
- const mockError = new Error('Test error');
71
- const mockDefinition = jest.fn(async () => {
72
- throw mockError;
73
- });
74
-
75
- await expect(model.scope(mockDefinition)).rejects.toThrow(mockError);
76
-
77
- expect(MongoClient.connect).toHaveBeenCalledWith(mockData.url);
78
- expect(mockClient.startSession).toHaveBeenCalled();
79
- expect(mockSession.withTransaction).toHaveBeenCalled();
80
- expect(mockDefinition).toHaveBeenCalled();
81
- expect(mockSession.endSession).toHaveBeenCalled();
82
- expect(mockClient.close).toHaveBeenCalled();
83
- });
84
- });
@@ -1,58 +0,0 @@
1
- import { Injectable } from '@nestjs/common';
2
- import { ClientSession, MongoClient, TransactionOptions } from 'mongodb';
3
-
4
- import { ITransaction, IUnitOfWork } from '@smartsoft001/domain-core';
5
-
6
- import { MongoConfig } from './mongo.module';
7
- import { getMongoUrl } from './mongo.utils';
8
-
9
- export interface IMongoTransaction extends ITransaction {
10
- session: ClientSession;
11
- }
12
-
13
- @Injectable()
14
- export class MongoUnitOfWork extends IUnitOfWork {
15
- constructor(private config: MongoConfig) {
16
- super();
17
- }
18
-
19
- async scope(
20
- definition: (transaction: ITransaction) => Promise<void>,
21
- ): Promise<void> {
22
- const client = await MongoClient.connect(this.getUrl());
23
-
24
- // Step 1: Start a Client Session
25
- const session = client.startSession();
26
-
27
- // Step 2: Optional. Define options to use for the transaction
28
- const transactionOptions: TransactionOptions = {
29
- readPreference: 'primary',
30
- readConcern: { level: 'local' },
31
- writeConcern: { w: 'majority' },
32
- };
33
-
34
- // Step 3: Use withTransaction to start a transaction, execute the callback, and commit (or abort on error)
35
- // Note: The callback for withTransaction MUST be async and/or return a Promise.
36
-
37
- let error = null;
38
- try {
39
- await session.withTransaction(async () => {
40
- await definition({
41
- session,
42
- connection: client,
43
- } as IMongoTransaction);
44
- }, transactionOptions);
45
- } catch (e) {
46
- error = e;
47
- } finally {
48
- await session.endSession();
49
- await client.close();
50
- }
51
-
52
- if (error) throw error;
53
- }
54
-
55
- private getUrl(): string {
56
- return getMongoUrl(this.config);
57
- }
58
- }
@@ -1,53 +0,0 @@
1
- import { MongoConfig } from './mongo.module';
2
- import { getMongoUrl } from './mongo.utils';
3
-
4
- const mockData: (MongoConfig & { result: string; testName: string })[] = [
5
- {
6
- host: 'host',
7
- port: 4200,
8
- database: 'db-string',
9
- result: 'mongodb://host:4200?authSource=db-string',
10
- testName: 'Basic',
11
- },
12
- {
13
- host: 'ondigitalocean.com',
14
- port: 4200,
15
- database: 'db-string',
16
- result:
17
- 'mongodb+srv://ondigitalocean.com:4200?authSource=db-string&tls=true',
18
- testName: 'Specific host',
19
- },
20
- {
21
- host: 'host',
22
- port: 4200,
23
- database: 'db-string',
24
- result: 'mongodb://host:4200?authSource=db-string',
25
- testName: 'Only username',
26
- username: 'username',
27
- },
28
- {
29
- host: 'host',
30
- port: 4200,
31
- database: 'db-string',
32
- result: 'mongodb://host:4200?authSource=db-string',
33
- testName: 'Only password',
34
- password: 'password',
35
- },
36
- {
37
- host: 'host',
38
- port: 4200,
39
- database: 'db-string',
40
- result: 'mongodb://username:password@host:4200?authSource=db-string',
41
- testName: 'Username and Password',
42
- username: 'username',
43
- password: 'password',
44
- },
45
- ];
46
-
47
- describe('shared-mongo: utils getMongoUrl function', () => {
48
- for (const data of mockData) {
49
- it(data.testName, () => {
50
- expect(getMongoUrl(data)).toBe(data.result);
51
- });
52
- }
53
- });
@@ -1,17 +0,0 @@
1
- import { MongoConfig } from './mongo.module';
2
-
3
- export function getMongoUrl(config: MongoConfig): string {
4
- let url;
5
- if (config.username && config.password)
6
- url = `mongodb://${config.username}:${config.password}@${config.host}:${config.port}`;
7
- else url = `mongodb://${config.host}:${config.port}`;
8
-
9
- url = url + '?authSource=' + config.database;
10
-
11
- if (config.host.indexOf('ondigitalocean.com') > -1) {
12
- url = url.replace('mongodb://', 'mongodb+srv://');
13
- url = url + '&tls=true';
14
- }
15
-
16
- return url;
17
- }