@ackplus/nest-crud-request 0.1.50 → 1.1.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.
Files changed (41) hide show
  1. package/README.md +6 -130
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/{src → dist}/lib/query-builder.d.ts +1 -0
  5. package/dist/lib/query-builder.d.ts.map +1 -0
  6. package/{src → dist}/lib/query-builder.js +23 -16
  7. package/{src → dist}/lib/relation-builder.d.ts +1 -0
  8. package/dist/lib/relation-builder.d.ts.map +1 -0
  9. package/{src → dist}/lib/relation-builder.js +2 -6
  10. package/dist/lib/types.d.ts +53 -0
  11. package/dist/lib/types.d.ts.map +1 -0
  12. package/dist/lib/types.js +31 -0
  13. package/{src → dist}/lib/utils.d.ts +1 -0
  14. package/dist/lib/utils.d.ts.map +1 -0
  15. package/dist/lib/utils.js +11 -0
  16. package/{src → dist}/lib/where-builder.d.ts +4 -0
  17. package/dist/lib/where-builder.d.ts.map +1 -0
  18. package/{src → dist}/lib/where-builder.js +30 -13
  19. package/eslint.config.mjs +22 -0
  20. package/jest.config.ts +10 -0
  21. package/package.json +2 -20
  22. package/project.json +46 -0
  23. package/src/index.ts +3 -0
  24. package/src/lib/query-builder.ts +189 -0
  25. package/src/lib/relation-builder.ts +68 -0
  26. package/src/lib/types.js +1 -0
  27. package/src/lib/types.js.map +1 -0
  28. package/src/lib/types.ts +61 -0
  29. package/src/lib/utils.ts +11 -0
  30. package/src/lib/where-builder.ts +159 -0
  31. package/src/test/query-builder-where.spec.ts +173 -0
  32. package/src/test/query-builder.spec.ts +140 -0
  33. package/src/test/relation-builder.spec.ts +32 -0
  34. package/src/test/where-builder-complex.spec.ts +173 -0
  35. package/tsconfig.json +17 -0
  36. package/tsconfig.lib.json +10 -0
  37. package/tsconfig.spec.json +15 -0
  38. package/src/index.js +0 -6
  39. package/src/lib/utils.js +0 -11
  40. package/tsconfig.tsbuildinfo +0 -1
  41. /package/{src/index.d.ts → dist/index.js} +0 -0
@@ -0,0 +1,140 @@
1
+ import { QueryBuilder } from '../lib/query-builder';
2
+ import { OrderDirectionEnum } from '../lib/types';
3
+
4
+
5
+ describe('QueryBuilder', () => {
6
+ let queryBuilder: QueryBuilder;
7
+
8
+ beforeEach(() => {
9
+ queryBuilder = new QueryBuilder({});
10
+ });
11
+
12
+ it('should set options', () => {
13
+ const options = { select: ['name', 'age'] };
14
+ queryBuilder.setOptions(options);
15
+ expect(queryBuilder.toObject(true).select).toEqual(options.select);
16
+ });
17
+
18
+ it('should merge options shallowly', () => {
19
+ queryBuilder.setOptions({ select: ['name'] });
20
+ queryBuilder.mergeOptions({ select: ['age'] });
21
+ expect(queryBuilder.toObject(true).select).toEqual(['age']);
22
+ });
23
+
24
+ it('should merge options deeply', () => {
25
+ queryBuilder.setOptions({ where: { age: { $gt: 18 } } });
26
+ queryBuilder.mergeOptions({ where: { name: { $eq: 'John' } } }, true);
27
+ expect(queryBuilder.toObject(true).where).toEqual({
28
+ age: { $gt: 18 },
29
+ name: { $eq: 'John' },
30
+ });
31
+ });
32
+
33
+ it('should add select fields', () => {
34
+ queryBuilder.addSelect('name');
35
+ queryBuilder.addSelect(['age', 'email']);
36
+ expect(queryBuilder.toObject(true).select).toEqual([
37
+ 'name',
38
+ 'age',
39
+ 'email',
40
+ ]);
41
+ });
42
+
43
+ it('should remove select fields', () => {
44
+ queryBuilder.addSelect([
45
+ 'name',
46
+ 'age',
47
+ 'email',
48
+ ]);
49
+ queryBuilder.removeSelect('age');
50
+ expect(queryBuilder.toObject(true).select).toEqual(['name', 'email']);
51
+ });
52
+
53
+ it('should add and remove relations as array of objects', () => {
54
+ queryBuilder.addRelation('profile', ['id', 'bio']);
55
+ queryBuilder.addRelation('posts', ['title', 'content']);
56
+
57
+ const relations = queryBuilder.toObject(true).relations;
58
+ expect(relations).toEqual(
59
+ expect.objectContaining({
60
+ profile: { select: ['id', 'bio'] },
61
+ posts: { select: ['title', 'content'] },
62
+ }),
63
+ );
64
+
65
+ queryBuilder.removeRelation('profile');
66
+ const updatedRelations = queryBuilder.toObject(true).relations;
67
+ expect(updatedRelations).toEqual(
68
+ expect.objectContaining({
69
+ posts: { select: ['title', 'content'] },
70
+ }),
71
+ );
72
+ expect(updatedRelations).not.toEqual(
73
+ expect.objectContaining({ profile: true }),
74
+ );
75
+ });
76
+
77
+ it('should handle null or empty relations', () => {
78
+ queryBuilder.addRelation('profile');
79
+ expect(queryBuilder.toObject(true).relations).not.toEqual(undefined);
80
+
81
+ queryBuilder.addRelation('profile');
82
+ queryBuilder.removeRelation('profile');
83
+ expect(queryBuilder.toObject(true).relations).toEqual(undefined);
84
+ });
85
+
86
+ it('should add and remove relations as array of strings', () => {
87
+ queryBuilder.addRelation('profile');
88
+ queryBuilder.addRelation('posts');
89
+
90
+ const relations = queryBuilder.toObject(true).relations;
91
+ expect(relations).toEqual(
92
+ expect.objectContaining({ profile: true, posts: true }),
93
+ );
94
+
95
+ queryBuilder.removeRelation('profile');
96
+ const updatedRelations = queryBuilder.toObject(true).relations;
97
+ expect(updatedRelations).toEqual(
98
+ expect.objectContaining({ posts: true }),
99
+ );
100
+ expect(updatedRelations).not.toEqual(
101
+ expect.objectContaining({ profile: true }),
102
+ );
103
+ });
104
+
105
+ it('should add where conditions', () => {
106
+ queryBuilder.where('age', 25);
107
+ expect(queryBuilder.toObject(true).where).toEqual({ age: { $eq: 25 } });
108
+ });
109
+
110
+ it('should handle empty where conditions', () => {
111
+ queryBuilder.where(() => {
112
+ // Do nothing
113
+ });
114
+ expect(queryBuilder.toObject(true).where).toEqual(undefined);
115
+ });
116
+
117
+ it('should add order', () => {
118
+ queryBuilder.addOrder('name', OrderDirectionEnum.ASC);
119
+ expect(queryBuilder.toObject(true).order).toEqual({ name: OrderDirectionEnum.ASC });
120
+ });
121
+
122
+ it('should remove order', () => {
123
+ queryBuilder.addOrder('name', OrderDirectionEnum.ASC);
124
+ queryBuilder.removeOrder('name');
125
+ expect(queryBuilder.toObject(true).order).toEqual(undefined);
126
+ });
127
+
128
+ it('should set skip and take', () => {
129
+ queryBuilder.setSkip(10);
130
+ queryBuilder.setTake(5);
131
+ expect(queryBuilder.toObject(true).skip).toBe(10);
132
+ expect(queryBuilder.toObject(true).take).toBe(5);
133
+ });
134
+
135
+ it('should convert to JSON', () => {
136
+ queryBuilder.setOptions({ select: ['name'] });
137
+ const json = queryBuilder.toJson();
138
+ expect(json).toBe(JSON.stringify(queryBuilder.toObject(true)));
139
+ });
140
+ });
@@ -0,0 +1,32 @@
1
+ import { RelationBuilder } from '../lib/relation-builder';
2
+
3
+
4
+ describe('RelationBuilder', () => {
5
+ let relationBuilder: RelationBuilder;
6
+
7
+ beforeEach(() => {
8
+ relationBuilder = new RelationBuilder();
9
+ });
10
+
11
+ it('should handle empty relations', () => {
12
+ // Initially, the relations should be empty
13
+ expect(relationBuilder.toObject()).toEqual({});
14
+
15
+ // Clear any relations if set
16
+ relationBuilder.clear();
17
+ expect(relationBuilder.toObject()).toEqual({});
18
+ });
19
+
20
+ it('should handle setting empty relations', () => {
21
+ // Set empty relations
22
+ relationBuilder.setRelations([]);
23
+ expect(relationBuilder.toObject()).toEqual({});
24
+ });
25
+
26
+ it('should handle clearing relations', () => {
27
+ // Add some relations and then clear them
28
+ relationBuilder.setRelations(['relation1', 'relation2']);
29
+ relationBuilder.clear();
30
+ expect(relationBuilder.toObject()).toEqual({});
31
+ });
32
+ });
@@ -0,0 +1,173 @@
1
+ import { WhereBuilder } from '../lib/where-builder';
2
+ import { WhereOperatorEnum } from '../lib/types';
3
+
4
+ describe('WhereBuilder - Complex Nested Structures', () => {
5
+ let whereBuilder: WhereBuilder;
6
+
7
+ beforeEach(() => {
8
+ whereBuilder = new WhereBuilder();
9
+ });
10
+
11
+ it('should create complex nested where structure with mixed conditions', () => {
12
+ // Target structure:
13
+ // {
14
+ // customerId: { $in: ['cust_123', 'cust_456'] },
15
+ // $or: [
16
+ // { status: { $eq: 'pending' } },
17
+ // { status: { $eq: 'processing' } },
18
+ // {
19
+ // $and: [
20
+ // { total: { $gt: 1000 } },
21
+ // { tax: { $lte: 200 } },
22
+ // ],
23
+ // },
24
+ // ],
25
+ // }
26
+
27
+ whereBuilder
28
+ .where('customerId', WhereOperatorEnum.IN, ['cust_123', 'cust_456'])
29
+ .orWhere('status', WhereOperatorEnum.EQ, 'pending')
30
+ .orWhere('status', WhereOperatorEnum.EQ, 'processing')
31
+ .orWhere((builder) => {
32
+ builder.where('total', WhereOperatorEnum.GT, 1000)
33
+ .where('tax', WhereOperatorEnum.LT_OR_EQ, 200);
34
+ });
35
+
36
+ const result = whereBuilder.toObject();
37
+
38
+ expect(result).toEqual({
39
+ customerId: { $in: ['cust_123', 'cust_456'] },
40
+ $or: [
41
+ { status: { $eq: 'pending' } },
42
+ { status: { $eq: 'processing' } },
43
+ {
44
+ total: { $gt: 1000 },
45
+ tax: { $lte: 200 },
46
+ },
47
+ ],
48
+ });
49
+ });
50
+
51
+ it('should handle multiple field conditions with same logical operator', () => {
52
+ whereBuilder
53
+ .where('name', 'John')
54
+ .orWhere('age', WhereOperatorEnum.GT, 18)
55
+ .orWhere('status', 'active')
56
+ .where('country', 'USA');
57
+
58
+ const result = whereBuilder.toObject();
59
+
60
+ expect(result).toEqual({
61
+ name: { $eq: 'John' },
62
+ country: { $eq: 'USA' },
63
+ $or: [
64
+ { age: { $gt: 18 } },
65
+ { status: { $eq: 'active' } },
66
+ ],
67
+ });
68
+ });
69
+
70
+ it('should handle nested $and and $or conditions', () => {
71
+ whereBuilder
72
+ .where('userId', '123')
73
+ .orWhere((builder) => {
74
+ builder.where('role', 'admin')
75
+ .where('department', 'IT');
76
+ })
77
+ .orWhere((builder) => {
78
+ builder.where('role', 'manager')
79
+ .where('level', WhereOperatorEnum.GT, 5);
80
+ });
81
+
82
+ const result = whereBuilder.toObject();
83
+
84
+ expect(result).toEqual({
85
+ userId: { $eq: '123' },
86
+ $or: [
87
+ {
88
+ role: { $eq: 'admin' },
89
+ department: { $eq: 'IT' },
90
+ },
91
+ {
92
+ role: { $eq: 'manager' },
93
+ level: { $gt: 5 },
94
+ },
95
+ ],
96
+ });
97
+ });
98
+
99
+ it('should handle direct object conditions', () => {
100
+ whereBuilder
101
+ .where({
102
+ name: { $eq: 'John' },
103
+ age: { $gt: 18 },
104
+ })
105
+ .orWhere({
106
+ status: { $eq: 'active' },
107
+ verified: { $eq: true },
108
+ });
109
+
110
+ const result = whereBuilder.toObject();
111
+
112
+ expect(result).toEqual({
113
+ name: { $eq: 'John' },
114
+ age: { $gt: 18 },
115
+ $or: [
116
+ {
117
+ status: { $eq: 'active' },
118
+ verified: { $eq: true },
119
+ },
120
+ ],
121
+ });
122
+ });
123
+
124
+ it('should merge multiple $or conditions correctly', () => {
125
+ whereBuilder
126
+ .orWhere('category', 'tech')
127
+ .orWhere('category', 'design')
128
+ .where('published', true)
129
+ .orWhere('priority', WhereOperatorEnum.GT, 5);
130
+
131
+ const result = whereBuilder.toObject();
132
+
133
+ expect(result).toEqual({
134
+ published: { $eq: true },
135
+ $or: [
136
+ { category: { $eq: 'tech' } },
137
+ { category: { $eq: 'design' } },
138
+ { priority: { $gt: 5 } },
139
+ ],
140
+ });
141
+ });
142
+
143
+ it('should handle complex nested logical operations', () => {
144
+ whereBuilder
145
+ .where('companyId', '456')
146
+ .orWhere((builder) => {
147
+ builder.where('department', 'Sales')
148
+ .orWhere((innerBuilder) => {
149
+ innerBuilder.where('region', 'North')
150
+ .where('quota', WhereOperatorEnum.GT, 100000);
151
+ });
152
+ })
153
+ .where('active', true);
154
+
155
+ const result = whereBuilder.toObject();
156
+
157
+ expect(result).toEqual({
158
+ companyId: { $eq: '456' },
159
+ active: { $eq: true },
160
+ $or: [
161
+ {
162
+ department: { $eq: 'Sales' },
163
+ $or: [
164
+ {
165
+ region: { $eq: 'North' },
166
+ quota: { $gt: 100000 },
167
+ },
168
+ ],
169
+ },
170
+ ],
171
+ });
172
+ });
173
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "commonjs",
5
+ "forceConsistentCasingInFileNames": true
6
+ },
7
+ "files": [],
8
+ "include": [],
9
+ "references": [
10
+ {
11
+ "path": "./tsconfig.lib.json"
12
+ },
13
+ {
14
+ "path": "./tsconfig.spec.json"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "declaration": true,
6
+ "types": ["node"]
7
+ },
8
+ "include": ["src/**/*.ts"],
9
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "moduleResolution": "node10",
7
+ "types": ["jest", "node"]
8
+ },
9
+ "include": [
10
+ "jest.config.ts",
11
+ "src/**/*.test.ts",
12
+ "src/**/*.spec.ts",
13
+ "src/**/*.d.ts"
14
+ ]
15
+ }
package/src/index.js DELETED
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./lib/query-builder"), exports);
5
- tslib_1.__exportStar(require("./lib/where-builder"), exports);
6
- tslib_1.__exportStar(require("./lib/types"), exports);
package/src/lib/utils.js DELETED
@@ -1,11 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deepMerge = deepMerge;
4
- function deepMerge(target, source) {
5
- for (const key in source) {
6
- if (source[key] instanceof Object && key in target) {
7
- Object.assign(source[key], deepMerge(target[key], source[key]));
8
- }
9
- }
10
- return Object.assign(Object.assign({}, target), source);
11
- }
@@ -1 +0,0 @@
1
- {"version":"5.8.3"}
File without changes