@hvedinich/utils 0.0.59 → 0.0.61

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/.eslintrc.js CHANGED
@@ -13,4 +13,12 @@ module.exports = {
13
13
  'arrow-body-style': 'off',
14
14
  'prefer-arrow-callback': 'off',
15
15
  },
16
+ overrides: [
17
+ {
18
+ files: ['**/*.test.js', '**/*.spec.js'],
19
+ env: {
20
+ jest: true,
21
+ },
22
+ },
23
+ ],
16
24
  };
@@ -0,0 +1,28 @@
1
+ name: run unit tests
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ pull_request:
6
+ branches:
7
+ - main
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+
12
+ strategy:
13
+ matrix:
14
+ node-version: [18]
15
+ steps:
16
+ - name: Checkout repository
17
+ uses: actions/checkout@v3
18
+
19
+ - name: Set up Node.js
20
+ uses: actions/setup-node@v3
21
+ with:
22
+ node-version: ${{ matrix.node-version }}
23
+
24
+ - name: Install dependencies
25
+ run: npm install
26
+
27
+ - name: Run tests
28
+ run: npm test
@@ -0,0 +1,57 @@
1
+ name: Publish utils
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ update-version-publish-and-release:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v2
15
+
16
+ - name: Setup Node.js
17
+ uses: actions/setup-node@v3
18
+ with:
19
+ node-version: 18
20
+ registry-url: 'https://registry.npmjs.org/'
21
+
22
+ - name: Install dependencies
23
+ run: npm ci
24
+
25
+ - name: Update patch version
26
+ run: |
27
+ npm version patch --no-git-tag-version
28
+ git config --local user.email "rooolik@gmail.com"
29
+ git config --local user.name "hvedinich"
30
+ git commit -am "Update version to $(node -p "require('./package.json').version")"
31
+ git push
32
+
33
+ - name: Publish to npm
34
+ uses: JS-DevTools/npm-publish@v3
35
+ with:
36
+ token: ${{ secrets.NPM_TOKEN }}
37
+
38
+ - name: Read Changelog
39
+ id: changelog
40
+ run: echo "::set-output name=body::$(cat CHANGELOG.md)"
41
+
42
+ - name: Get package.json version
43
+ id: package_version
44
+ run: echo "::set-output name=version::$(node -p "require('./package.json').version")"
45
+ shell: bash
46
+
47
+ - name: Set the version in the env
48
+ run: echo "VERSION=${{ steps.package_version.outputs.version }}" >> $GITHUB_ENV
49
+
50
+ - name: Create release
51
+ env:
52
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53
+ run: |
54
+ gh release create "$VERSION" \
55
+ --repo="$GITHUB_REPOSITORY" \
56
+ --title="${GITHUB_REPOSITORY#*/} ${VERSION#v}" \
57
+ --generate-notes
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@hvedinich/utils",
3
- "version": "0.0.59",
3
+ "version": "0.0.61",
4
4
  "description": "utils module",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "test": "jest"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
@@ -32,7 +32,7 @@
32
32
  "eslint-plugin-import": "^2.26.0",
33
33
  "eslint-plugin-prettier": "^4.0.0",
34
34
  "husky": "^8.0.1",
35
- "jest": "^29.1.2",
35
+ "jest": "^29.7.0",
36
36
  "prettier": "^2.5.1"
37
37
  },
38
38
  "publishConfig": {
@@ -0,0 +1,129 @@
1
+ const { buildDBModel } = require('../index');
2
+
3
+ // Mock Mongoose schema methods
4
+ const mockSchema = {
5
+ findOneAndUpdate: jest.fn(),
6
+ findOne: jest.fn(),
7
+ find: jest.fn(),
8
+ create: jest.fn(),
9
+ deleteOne: jest.fn(),
10
+ countDocuments: jest.fn(),
11
+ };
12
+
13
+ // Create the model using the mocked schema
14
+ const dbModel = buildDBModel(mockSchema);
15
+
16
+ describe('buildDBModel', () => {
17
+ beforeEach(() => {
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ it('should create a new document', async () => {
22
+ const mockData = { name: 'Test' };
23
+ const createdDoc = { ...mockData, _id: '1' };
24
+ mockSchema.create.mockResolvedValue(createdDoc);
25
+
26
+ const result = await dbModel.create(mockData);
27
+ expect(result).toEqual(createdDoc);
28
+ expect(mockSchema.create).toHaveBeenCalledWith(mockData);
29
+ });
30
+
31
+ it('should read a single document', async () => {
32
+ const mockFilter = { _id: '1' };
33
+ const foundDoc = { _id: '1', name: 'Test' };
34
+ mockSchema.findOne.mockReturnValue({
35
+ lean: jest.fn().mockResolvedValue(foundDoc),
36
+ });
37
+
38
+ const result = await dbModel.read(mockFilter);
39
+ expect(result).toEqual(foundDoc);
40
+ expect(mockSchema.findOne).toHaveBeenCalledWith(mockFilter);
41
+ });
42
+
43
+ it('should read multiple documents', async () => {
44
+ const mockFilter = { name: 'Test' };
45
+ const foundDocs = [
46
+ { _id: '1', name: 'Test' },
47
+ { _id: '2', name: 'Test2' },
48
+ ];
49
+ mockSchema.find.mockReturnValue({
50
+ lean: jest.fn().mockReturnValue({
51
+ exec: jest.fn().mockResolvedValue(foundDocs),
52
+ }),
53
+ });
54
+
55
+ const result = await dbModel.readAll(mockFilter);
56
+ expect(result).toEqual(foundDocs);
57
+ expect(mockSchema.find).toHaveBeenCalledWith(mockFilter);
58
+ });
59
+
60
+ it('should find one and update a document', async () => {
61
+ const mockFilter = { _id: '1' };
62
+ const mockAction = { $set: { name: 'Updated' } };
63
+ const options = { new: true };
64
+ const updatedDoc = { _id: '1', name: 'Updated' };
65
+ mockSchema.findOneAndUpdate.mockReturnValue({
66
+ lean: jest.fn().mockResolvedValue(updatedDoc),
67
+ });
68
+
69
+ const result = await dbModel.findOneAndUpdate(mockFilter, mockAction, options);
70
+ expect(result).toEqual(updatedDoc);
71
+ expect(mockSchema.findOneAndUpdate).toHaveBeenCalledWith(mockFilter, mockAction, options);
72
+ });
73
+
74
+ it('should remove a document by id', async () => {
75
+ const mockId = '1';
76
+ const removeResult = { deletedCount: 1 };
77
+ mockSchema.deleteOne.mockResolvedValue(removeResult);
78
+
79
+ const result = await dbModel.remove(mockId);
80
+ expect(result).toEqual(removeResult);
81
+ expect(mockSchema.deleteOne).toHaveBeenCalledWith({ id: mockId });
82
+ });
83
+
84
+ it('should count documents', async () => {
85
+ const mockFilter = { name: 'Test' };
86
+ const countResult = 2;
87
+ mockSchema.countDocuments.mockReturnValue({
88
+ lean: jest.fn().mockReturnValue({
89
+ exec: jest.fn().mockResolvedValue(countResult),
90
+ }),
91
+ });
92
+
93
+ const result = await dbModel.count(mockFilter);
94
+ expect(result).toEqual(countResult);
95
+ expect(mockSchema.countDocuments).toHaveBeenCalledWith(mockFilter);
96
+ });
97
+
98
+ it('should list documents with pagination and sorting', async () => {
99
+ const mockOptions = {
100
+ filter: { name: 'Test' },
101
+ pagination: { page: 1, pageSize: 2 },
102
+ sortBy: { field: 'name', direction: 'asc' },
103
+ };
104
+ const foundDocs = [
105
+ { _id: '1', name: 'Test' },
106
+ { _id: '2', name: 'Test2' },
107
+ ];
108
+ const totalCount = 2;
109
+
110
+ mockSchema.find.mockReturnValue({
111
+ skip: jest.fn().mockReturnThis(),
112
+ limit: jest.fn().mockReturnThis(),
113
+ sort: jest.fn().mockReturnThis(),
114
+ lean: jest.fn().mockReturnThis(),
115
+ exec: jest.fn().mockResolvedValue(foundDocs),
116
+ });
117
+
118
+ mockSchema.countDocuments.mockReturnValue({
119
+ lean: jest.fn().mockReturnValue({
120
+ exec: jest.fn().mockResolvedValue(totalCount),
121
+ }),
122
+ });
123
+
124
+ const result = await dbModel.list(mockOptions);
125
+ expect(result).toEqual([foundDocs, totalCount]);
126
+ expect(mockSchema.find).toHaveBeenCalledWith(mockOptions.filter);
127
+ expect(mockSchema.countDocuments).toHaveBeenCalledWith(mockOptions.filter);
128
+ });
129
+ });
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Creates basic CRUD methods for a Mongoose schema.
3
+ * @param {mongoose.Schema} schema - The Mongoose schema to build the model methods for.
4
+ * @returns {Object} - An object containing CRUD methods for the schema.
5
+ */
6
+ const buildDBModel = schema => {
7
+ /**
8
+ * Finds one document and updates it.
9
+ * @param {Object} filter - The filter to find the document.
10
+ * @param {Object} action - The update action to perform.
11
+ * @param {Object} options - Options for the update operation.
12
+ * @returns {Promise<Object>} - The updated document.
13
+ */
14
+ const findOneAndUpdate = (filter, action, options) => schema.findOneAndUpdate(filter, action, options).lean();
15
+
16
+ /**
17
+ * Reads a single document.
18
+ * @param {Object} input - The filter to find the document.
19
+ * @returns {Promise<Object>} - The found document.
20
+ */
21
+ const read = input => schema.findOne(input).lean();
22
+
23
+ /**
24
+ * Reads multiple documents.
25
+ * @param {Object} filter - The filter to find the documents.
26
+ * @returns {Promise<Array>} - An array of found documents.
27
+ */
28
+ const readAll = filter => schema.find(filter).lean().exec();
29
+
30
+ /**
31
+ * Creates a new document.
32
+ * @param {Object} data - The data for the new document.
33
+ * @returns {Promise<Object>} - The created document.
34
+ */
35
+ const create = data => schema.create(data);
36
+
37
+ /**
38
+ * Removes a document by id.
39
+ * @param {String} id - The id of the document to remove.
40
+ * @returns {Promise<Object>} - The result of the remove operation.
41
+ */
42
+ const remove = id => schema.deleteOne({ id });
43
+
44
+ /**
45
+ * Counts the number of documents matching a filter.
46
+ * @param {Object} filter - The filter to count the documents.
47
+ * @returns {Promise<Number>} - The count of documents.
48
+ */
49
+ const count = filter => schema.countDocuments(filter).lean().exec();
50
+
51
+ /**
52
+ * Lists documents with optional pagination and sorting.
53
+ * @param {Object} options - The options for listing documents.
54
+ * @param {Object} options.filter - The filter to find the documents.
55
+ * @param {Object} [options.pagination] - The pagination options.
56
+ * @param {Number} [options.pagination.page] - The page number.
57
+ * @param {Number} [options.pagination.pageSize] - The number of documents per page.
58
+ * @param {Object} [options.sortBy] - The sorting options.
59
+ * @param {String} [options.sortBy.field] - The field to sort by.
60
+ * @param {String} [options.sortBy.direction] - The direction to sort ('asc' or 'desc').
61
+ * @returns {Promise<Array>} - An array containing the found documents and the total count.
62
+ */
63
+ const list = async ({ filter = {}, pagination, sortBy }) => {
64
+ let query = schema.find(filter);
65
+ const countQuery = schema.countDocuments(filter);
66
+ if (pagination) {
67
+ query = query.skip((pagination.page - 1) * pagination.pageSize).limit(pagination.pageSize);
68
+ }
69
+ if (sortBy && sortBy.field) {
70
+ query = query.sort([[sortBy.field, sortBy.direction || 'asc']]);
71
+ }
72
+ const [totalCount, results] = await Promise.all([countQuery.lean().exec(), query.lean().exec()]);
73
+ return [results, totalCount];
74
+ };
75
+ return {
76
+ create,
77
+ read,
78
+ readAll,
79
+ list,
80
+ findOneAndUpdate,
81
+ remove,
82
+ count,
83
+ };
84
+ };
85
+
86
+ module.exports = {
87
+ buildDBModel,
88
+ };
@@ -6,6 +6,7 @@ const common = require('./common');
6
6
  const permission = require('./permission');
7
7
  const config = require('./config');
8
8
  const healthCheck = require('./healthCheck');
9
+ const db = require('./buildDBModel');
9
10
 
10
11
  module.exports = {
11
12
  context,
@@ -15,5 +16,6 @@ module.exports = {
15
16
  permission,
16
17
  config,
17
18
  common,
18
- healthCheck
19
+ healthCheck,
20
+ db,
19
21
  };