querier-ts 0.0.0 → 1.0.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 (88) hide show
  1. package/lib/__tests__/query.spec.d.ts +1 -0
  2. package/lib/__tests__/query.spec.js +149 -0
  3. package/lib/core/errors/__tests__/invalid-argument-error.spec.d.ts +1 -0
  4. package/lib/core/errors/__tests__/invalid-argument-error.spec.js +54 -0
  5. package/lib/core/errors/index.d.ts +1 -0
  6. package/lib/core/errors/index.js +17 -0
  7. package/lib/core/errors/invalid-argument-error.d.ts +14 -0
  8. package/lib/core/errors/invalid-argument-error.js +16 -0
  9. package/lib/core/types/attribute-validation-function.d.ts +1 -0
  10. package/lib/core/types/attribute-validation-function.js +2 -0
  11. package/lib/core/types/column-condition.d.ts +6 -0
  12. package/lib/core/types/column-condition.js +2 -0
  13. package/lib/core/types/index.d.ts +4 -0
  14. package/lib/core/types/index.js +20 -0
  15. package/lib/core/types/query-conditions-group-nullable.d.ts +4 -0
  16. package/lib/core/types/query-conditions-group-nullable.js +2 -0
  17. package/lib/core/types/query-conditions-group.d.ts +4 -0
  18. package/lib/core/types/query-conditions-group.js +2 -0
  19. package/lib/core/types/query-row-validator-initializer.d.ts +8 -0
  20. package/lib/core/types/query-row-validator-initializer.js +2 -0
  21. package/lib/core/validation/__tests__/query-row-validator.spec.d.ts +1 -0
  22. package/lib/core/validation/__tests__/query-row-validator.spec.js +195 -0
  23. package/lib/core/validation/decorators/__tests__/number-validation.spec.d.ts +1 -0
  24. package/lib/core/validation/decorators/__tests__/number-validation.spec.js +114 -0
  25. package/lib/core/validation/decorators/index.d.ts +1 -0
  26. package/lib/core/validation/decorators/index.js +17 -0
  27. package/lib/core/validation/decorators/number-validaton.d.ts +36 -0
  28. package/lib/core/validation/decorators/number-validaton.js +123 -0
  29. package/lib/core/validation/index.d.ts +1 -0
  30. package/lib/core/validation/index.js +17 -0
  31. package/lib/core/validation/query-row-validator.d.ts +57 -0
  32. package/lib/core/validation/query-row-validator.js +84 -0
  33. package/lib/index.d.ts +1 -2
  34. package/lib/index.js +15 -3
  35. package/lib/query.d.ts +33 -38
  36. package/lib/query.js +51 -50
  37. package/lib/utils/functions/generic/__tests__/compare-arrays.spec.d.ts +1 -0
  38. package/lib/utils/functions/generic/__tests__/compare-arrays.spec.js +21 -0
  39. package/lib/utils/functions/generic/__tests__/deep-equal.spec.d.ts +1 -0
  40. package/lib/utils/functions/generic/__tests__/deep-equal.spec.js +82 -0
  41. package/lib/utils/functions/generic/__tests__/get-entries.spec.d.ts +1 -0
  42. package/lib/utils/functions/generic/__tests__/get-entries.spec.js +55 -0
  43. package/lib/utils/functions/generic/compare-arrays.d.ts +1 -9
  44. package/lib/utils/functions/generic/compare-arrays.js +2 -9
  45. package/lib/utils/functions/generic/deep-equal.d.ts +1 -0
  46. package/lib/utils/functions/generic/deep-equal.js +23 -0
  47. package/lib/utils/functions/generic/get-entries.d.ts +5 -8
  48. package/lib/utils/functions/generic/get-entries.js +7 -9
  49. package/lib/utils/functions/generic/index.d.ts +3 -3
  50. package/lib/utils/functions/generic/index.js +17 -5
  51. package/lib/utils/functions/sort/__tests__/sort-by-properties.spec.d.ts +1 -0
  52. package/lib/utils/functions/sort/__tests__/sort-by-properties.spec.js +69 -0
  53. package/lib/utils/functions/sort/__tests__/sort-by-property.spec.d.ts +1 -0
  54. package/lib/utils/functions/sort/__tests__/sort-by-property.spec.js +63 -0
  55. package/lib/utils/functions/sort/index.d.ts +2 -3
  56. package/lib/utils/functions/sort/index.js +16 -5
  57. package/lib/utils/functions/sort/sort-by-properties.d.ts +2 -2
  58. package/lib/utils/functions/sort/sort-by-properties.js +11 -9
  59. package/lib/utils/functions/sort/sort-by-property.d.ts +2 -2
  60. package/lib/utils/functions/sort/sort-by-property.js +18 -6
  61. package/lib/utils/functions/type-guards/__tests__/is-function.spec.d.ts +1 -0
  62. package/lib/utils/functions/type-guards/__tests__/is-function.spec.js +38 -0
  63. package/lib/utils/functions/type-guards/__tests__/is-number.spec.d.ts +1 -0
  64. package/lib/utils/functions/type-guards/__tests__/is-number.spec.js +35 -0
  65. package/lib/utils/functions/type-guards/__tests__/is-object.spec.d.ts +1 -0
  66. package/lib/utils/functions/type-guards/__tests__/is-object.spec.js +38 -0
  67. package/lib/utils/functions/type-guards/index.d.ts +3 -4
  68. package/lib/utils/functions/type-guards/index.js +17 -7
  69. package/lib/utils/functions/type-guards/is-function.d.ts +3 -3
  70. package/lib/utils/functions/type-guards/is-function.js +2 -2
  71. package/lib/utils/functions/type-guards/is-number.d.ts +3 -3
  72. package/lib/utils/functions/type-guards/is-number.js +2 -2
  73. package/lib/utils/functions/type-guards/is-object.d.ts +3 -3
  74. package/lib/utils/functions/type-guards/is-object.js +2 -2
  75. package/lib/utils/types/add-prefix-to-object.d.ts +1 -1
  76. package/lib/utils/types/allowed-names.d.ts +1 -1
  77. package/lib/utils/types/flag-excluded-type.d.ts +1 -1
  78. package/lib/utils/types/generic-object.d.ts +1 -1
  79. package/lib/utils/types/generic-object.js +0 -1
  80. package/lib/utils/types/index.d.ts +9 -10
  81. package/lib/utils/types/index.js +23 -0
  82. package/lib/utils/types/omit-type.d.ts +1 -1
  83. package/lib/utils/types/partial-of-properties.d.ts +1 -1
  84. package/lib/utils/types/prop-of.d.ts +1 -1
  85. package/lib/utils/types/property-only.d.ts +1 -1
  86. package/lib/utils/types/recursive-partial.d.ts +1 -1
  87. package/lib/utils/types/type.d.ts +1 -1
  88. package/package.json +23 -24
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const errors_1 = require("../core/errors");
4
+ const query_1 = require("../query");
5
+ class User {
6
+ constructor(id, name, permissions, isActive, createdAt, updatedAt) {
7
+ this.id = id;
8
+ this.name = name;
9
+ this.permissions = permissions;
10
+ this.isActive = isActive;
11
+ this.createdAt = createdAt;
12
+ this.updatedAt = updatedAt;
13
+ }
14
+ isAdmin() {
15
+ return this.id === 1;
16
+ }
17
+ }
18
+ const users = [
19
+ new User(1, 'John', { useCookies: true, sendNotifications: true }, true, new Date('2023-01-01'), new Date('2023-01-10')),
20
+ new User(2, 'Mary', { useCookies: false, sendNotifications: true }, false, new Date('2023-02-01'), new Date('2023-02-10')),
21
+ new User(3, 'Bob', { useCookies: true, sendNotifications: false }, true, new Date('2023-03-01'), new Date('2023-03-10')),
22
+ ];
23
+ describe('Query', () => {
24
+ describe('creation', () => {
25
+ it('should create a query from array', () => {
26
+ const query = query_1.Query.from(users);
27
+ expect(query.all().length).toBe(3);
28
+ });
29
+ });
30
+ describe('where()', () => {
31
+ it('should filter using object conditions', () => {
32
+ const result = query_1.Query.from(users).where({ isActive: true }).all();
33
+ expect(result).toHaveLength(2);
34
+ expect(result.every((u) => u.isActive)).toBe(true);
35
+ });
36
+ it('should filter using function condition', () => {
37
+ const result = query_1.Query.from(users)
38
+ .where((user) => user.isAdmin())
39
+ .all();
40
+ expect(result).toHaveLength(1);
41
+ expect(result[0].id).toBe(1);
42
+ });
43
+ it('should combine multiple where calls', () => {
44
+ const result = query_1.Query.from(users)
45
+ .where({ isActive: true })
46
+ .where((user) => user.permissions.useCookies)
47
+ .all();
48
+ expect(result).toHaveLength(2);
49
+ });
50
+ });
51
+ describe('nested where()', () => {
52
+ it('should filter using inner object conditions', () => {
53
+ const result = query_1.Query.from(users)
54
+ .where({
55
+ permissions: {
56
+ sendNotifications: true,
57
+ },
58
+ })
59
+ .all();
60
+ expect(result).toHaveLength(2);
61
+ });
62
+ });
63
+ describe('filterWhere()', () => {
64
+ it('should ignore null and undefined conditions', () => {
65
+ const isActive = undefined;
66
+ const result = query_1.Query.from(users)
67
+ .filterWhere({
68
+ isActive,
69
+ id: 1,
70
+ })
71
+ .all();
72
+ expect(result).toHaveLength(1);
73
+ expect(result[0].id).toBe(1);
74
+ });
75
+ });
76
+ describe('select()', () => {
77
+ it('should select a single column', () => {
78
+ const result = query_1.Query.from(users).select('name').column();
79
+ expect(result).toEqual(['John', 'Mary', 'Bob']);
80
+ });
81
+ it('should select multiple columns', () => {
82
+ const result = query_1.Query.from(users).select(['id', 'name']).values();
83
+ expect(result).toEqual([
84
+ [1, 'John'],
85
+ [2, 'Mary'],
86
+ [3, 'Bob'],
87
+ ]);
88
+ });
89
+ });
90
+ describe('ordering', () => {
91
+ it('should order by ascending property', () => {
92
+ const result = query_1.Query.from(users).select('name').orderBy('name').column();
93
+ expect(result).toEqual(['Bob', 'John', 'Mary']);
94
+ });
95
+ it('should order by descending property', () => {
96
+ const result = query_1.Query.from(users).select('id').orderBy('-id').column();
97
+ expect(result).toEqual([3, 2, 1]);
98
+ });
99
+ it('should order by multiple properties', () => {
100
+ const result = query_1.Query.from(users)
101
+ .orderBy('isActive', '-id')
102
+ .select('id')
103
+ .column();
104
+ expect(result).toEqual([2, 3, 1]);
105
+ });
106
+ });
107
+ describe('pagination', () => {
108
+ it('should skip rows', () => {
109
+ const result = query_1.Query.from(users).select('id').skip(1).column();
110
+ expect(result).toEqual([2, 3]);
111
+ });
112
+ it('should limit rows', () => {
113
+ const result = query_1.Query.from(users).select('id').limit(2).column();
114
+ expect(result).toEqual([1, 2]);
115
+ });
116
+ it('should combine skip and limit', () => {
117
+ const result = query_1.Query.from(users).select('id').skip(1).limit(1).column();
118
+ expect(result).toEqual([2]);
119
+ });
120
+ it('should throw if skip is negative', () => {
121
+ expect(() => query_1.Query.from(users).skip(-1)).toThrow(errors_1.InvalidArgumentError);
122
+ });
123
+ it('should throw if limit is not an integer', () => {
124
+ expect(() => query_1.Query.from(users).limit(1.5)).toThrow(errors_1.InvalidArgumentError);
125
+ });
126
+ });
127
+ describe('result helpers', () => {
128
+ it('count()', () => {
129
+ expect(query_1.Query.from(users).count()).toBe(3);
130
+ });
131
+ it('exists()', () => {
132
+ expect(query_1.Query.from(users).where({ id: 99 }).exists()).toBe(false);
133
+ });
134
+ it('first()', () => {
135
+ expect(query_1.Query.from(users).first()?.id).toBe(1);
136
+ });
137
+ it('last()', () => {
138
+ expect(query_1.Query.from(users).last()?.id).toBe(3);
139
+ });
140
+ it('scalar()', () => {
141
+ const id = query_1.Query.from(users).select('id').scalar();
142
+ expect(id).toBe(1);
143
+ });
144
+ it('scalar() should return false if no results', () => {
145
+ const result = query_1.Query.from(users).where({ id: 99 }).scalar();
146
+ expect(result).toBe(false);
147
+ });
148
+ });
149
+ });
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const invalid_argument_error_1 = require("../invalid-argument-error");
4
+ describe('InvalidArgumentError', () => {
5
+ it('should be an instance of Error', () => {
6
+ const error = new invalid_argument_error_1.InvalidArgumentError({
7
+ method: 'testMethod',
8
+ param: 'value',
9
+ argument: 123,
10
+ expected: 'a string',
11
+ });
12
+ expect(error).toBeInstanceOf(Error);
13
+ });
14
+ it('should have the correct name', () => {
15
+ const error = new invalid_argument_error_1.InvalidArgumentError({
16
+ method: 'testMethod',
17
+ param: 'value',
18
+ argument: 123,
19
+ expected: 'a string',
20
+ });
21
+ expect(error.name).toBe('InvalidArgumentError');
22
+ });
23
+ it('should generate the correct error message', () => {
24
+ const error = new invalid_argument_error_1.InvalidArgumentError({
25
+ method: 'doSomething',
26
+ param: 0,
27
+ argument: false,
28
+ expected: 'a boolean',
29
+ });
30
+ expect(error.message).toBe('false is not a valid argument to param 0 on doSomething(). It should be a boolean.');
31
+ });
32
+ it('should expose configuration properties', () => {
33
+ const config = {
34
+ method: 'save',
35
+ param: 'id',
36
+ argument: null,
37
+ expected: 'a non-null value',
38
+ };
39
+ const error = new invalid_argument_error_1.InvalidArgumentError(config);
40
+ expect(error.method).toBe(config.method);
41
+ expect(error.param).toBe(config.param);
42
+ expect(error.argument).toBe(config.argument);
43
+ expect(error.expected).toBe(config.expected);
44
+ });
45
+ it('should preserve prototype chain', () => {
46
+ const error = new invalid_argument_error_1.InvalidArgumentError({
47
+ method: 'run',
48
+ param: 'options',
49
+ argument: {},
50
+ expected: 'a valid options object',
51
+ });
52
+ expect(error instanceof invalid_argument_error_1.InvalidArgumentError).toBe(true);
53
+ });
54
+ });
@@ -0,0 +1 @@
1
+ export * from './invalid-argument-error';
@@ -0,0 +1,17 @@
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
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./invalid-argument-error"), exports);
@@ -0,0 +1,14 @@
1
+ interface InvalidArgumentErrorConfig {
2
+ method: string;
3
+ param: string | number;
4
+ argument: unknown;
5
+ expected: string;
6
+ }
7
+ export declare class InvalidArgumentError extends Error {
8
+ readonly method: string;
9
+ readonly param: string | number;
10
+ readonly argument: unknown;
11
+ readonly expected: string;
12
+ constructor({ method, param, argument, expected, }: InvalidArgumentErrorConfig);
13
+ }
14
+ export {};
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidArgumentError = void 0;
4
+ class InvalidArgumentError extends Error {
5
+ constructor({ method, param, argument, expected, }) {
6
+ super(`${String(argument)} is not a valid argument to param ${param} on ${method}(). ` +
7
+ `It should be ${expected}.`);
8
+ this.name = 'InvalidArgumentError';
9
+ this.method = method;
10
+ this.param = param;
11
+ this.argument = argument;
12
+ this.expected = expected;
13
+ Object.setPrototypeOf(this, new.target.prototype);
14
+ }
15
+ }
16
+ exports.InvalidArgumentError = InvalidArgumentError;
@@ -0,0 +1 @@
1
+ export type AttributeValidationFunction<T extends object, P extends keyof T = keyof T> = (value: T[P]) => boolean;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import { AttributeValidationFunction } from './attribute-validation-function';
2
+ import { QueryConditionsGroupNullable } from './query-conditions-group-nullable';
3
+ /**
4
+ * Condition to apply to a row column.
5
+ */
6
+ export type ColumnCondition<T extends object, P extends keyof T> = T[P] extends object ? QueryConditionsGroupNullable<T[P]> | undefined : T[P] | AttributeValidationFunction<T, P> | null | undefined;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export * from './attribute-validation-function';
2
+ export * from './query-conditions-group';
3
+ export * from './query-conditions-group-nullable';
4
+ export * from './query-row-validator-initializer';
@@ -0,0 +1,20 @@
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
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./attribute-validation-function"), exports);
18
+ __exportStar(require("./query-conditions-group"), exports);
19
+ __exportStar(require("./query-conditions-group-nullable"), exports);
20
+ __exportStar(require("./query-row-validator-initializer"), exports);
@@ -0,0 +1,4 @@
1
+ import { PropertyOnly } from '../../utils/types';
2
+ export type QueryConditionsGroupNullable<T extends object> = {
3
+ [P in keyof PropertyOnly<T>]?: T[P] extends object ? QueryConditionsGroupNullable<T[P]> : T[P] | ((value: T[P]) => boolean) | null;
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { PropertyOnly } from '../../utils/types';
2
+ export type QueryConditionsGroup<T extends object> = {
3
+ [P in keyof PropertyOnly<T>]?: T[P] extends object ? QueryConditionsGroup<T[P]> : T[P] | ((value: T[P]) => boolean);
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import { QueryConditionsGroupNullable } from './query-conditions-group-nullable';
2
+ /**
3
+ * Validator configuration.
4
+ */
5
+ export interface QueryRowValidatorInitializer<T extends object> {
6
+ conditionsObject: QueryConditionsGroupNullable<T>;
7
+ ignoreNullValues: boolean;
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const query_row_validator_1 = require("../query-row-validator");
4
+ describe('QueryRowValidator', () => {
5
+ describe('primitive comparisons', () => {
6
+ it('should validate equality for primitive values', () => {
7
+ const row = { id: 1, name: 'Alice' };
8
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
9
+ conditionsObject: {
10
+ id: 1,
11
+ name: 'Alice',
12
+ },
13
+ ignoreNullValues: false,
14
+ });
15
+ expect(result).toBe(true);
16
+ });
17
+ it('should return false when primitive values differ', () => {
18
+ const row = { id: 1 };
19
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
20
+ conditionsObject: {
21
+ id: 2,
22
+ },
23
+ ignoreNullValues: false,
24
+ });
25
+ expect(result).toBe(false);
26
+ });
27
+ });
28
+ describe('function conditions', () => {
29
+ it('should validate using a function condition', () => {
30
+ const row = { age: 30 };
31
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
32
+ conditionsObject: {
33
+ age: (value) => value > 18,
34
+ },
35
+ ignoreNullValues: false,
36
+ });
37
+ expect(result).toBe(true);
38
+ });
39
+ it('should return false when function condition fails', () => {
40
+ const row = { age: 15 };
41
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
42
+ conditionsObject: {
43
+ age: (value) => value > 18,
44
+ },
45
+ ignoreNullValues: false,
46
+ });
47
+ expect(result).toBe(false);
48
+ });
49
+ });
50
+ describe('array conditions', () => {
51
+ it('should validate arrays using strict comparison', () => {
52
+ const row = { tags: ['a', 'b'] };
53
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
54
+ conditionsObject: {
55
+ tags: ['a', 'b'],
56
+ },
57
+ ignoreNullValues: false,
58
+ });
59
+ expect(result).toBe(true);
60
+ });
61
+ it('should return false for arrays with different values', () => {
62
+ const row = { tags: ['a', 'b'] };
63
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
64
+ conditionsObject: {
65
+ tags: ['a', 'c'],
66
+ },
67
+ ignoreNullValues: false,
68
+ });
69
+ expect(result).toBe(false);
70
+ });
71
+ it('should return false if condition is array but value is not', () => {
72
+ const row = { tags: 'a,b' };
73
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
74
+ conditionsObject: {
75
+ tags: ['a', 'b'],
76
+ },
77
+ ignoreNullValues: false,
78
+ });
79
+ expect(result).toBe(false);
80
+ });
81
+ });
82
+ describe('object conditions (nested validation)', () => {
83
+ it('should validate nested objects recursively', () => {
84
+ const row = {
85
+ user: {
86
+ name: 'John',
87
+ age: 25,
88
+ },
89
+ };
90
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
91
+ conditionsObject: {
92
+ user: {
93
+ name: 'John',
94
+ age: (value) => value >= 18,
95
+ },
96
+ },
97
+ ignoreNullValues: false,
98
+ });
99
+ expect(result).toBe(true);
100
+ });
101
+ it('should return false when nested validation fails', () => {
102
+ const row = {
103
+ user: {
104
+ name: 'John',
105
+ age: 15,
106
+ },
107
+ };
108
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
109
+ conditionsObject: {
110
+ user: {
111
+ age: (value) => value >= 18,
112
+ },
113
+ },
114
+ ignoreNullValues: false,
115
+ });
116
+ expect(result).toBe(false);
117
+ });
118
+ it('should return false if condition is object but value is not', () => {
119
+ const row = {
120
+ user: 'John',
121
+ };
122
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
123
+ conditionsObject: {
124
+ user: { name: 'John' },
125
+ },
126
+ ignoreNullValues: false,
127
+ });
128
+ expect(result).toBe(false);
129
+ });
130
+ });
131
+ describe('ignoreNullValues behavior', () => {
132
+ it('should ignore null conditions when ignoreNullValues is true', () => {
133
+ const row = { name: 'Alice' };
134
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
135
+ conditionsObject: {
136
+ name: null,
137
+ },
138
+ ignoreNullValues: true,
139
+ });
140
+ expect(result).toBe(true);
141
+ });
142
+ it('should ignore undefined conditions when ignoreNullValues is true', () => {
143
+ const row = { name: 'Alice' };
144
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
145
+ conditionsObject: {
146
+ name: undefined,
147
+ },
148
+ ignoreNullValues: true,
149
+ });
150
+ expect(result).toBe(true);
151
+ });
152
+ it('should NOT ignore null when ignoreNullValues is false', () => {
153
+ const row = { name: 'Alice' };
154
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
155
+ conditionsObject: {
156
+ name: null,
157
+ },
158
+ ignoreNullValues: false,
159
+ });
160
+ expect(result).toBe(false);
161
+ });
162
+ });
163
+ describe('multiple conditions', () => {
164
+ it('should return true only if all conditions pass', () => {
165
+ const row = {
166
+ id: 1,
167
+ active: true,
168
+ roles: ['admin'],
169
+ };
170
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
171
+ conditionsObject: {
172
+ id: 1,
173
+ active: true,
174
+ roles: ['admin'],
175
+ },
176
+ ignoreNullValues: false,
177
+ });
178
+ expect(result).toBe(true);
179
+ });
180
+ it('should return false if at least one condition fails', () => {
181
+ const row = {
182
+ id: 1,
183
+ active: false,
184
+ };
185
+ const result = query_row_validator_1.QueryRowValidator.validate(row, {
186
+ conditionsObject: {
187
+ id: 1,
188
+ active: true,
189
+ },
190
+ ignoreNullValues: false,
191
+ });
192
+ expect(result).toBe(false);
193
+ });
194
+ });
195
+ });
@@ -0,0 +1 @@
1
+ import 'reflect-metadata';
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
9
+ return function (target, key) { decorator(target, key, paramIndex); }
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ require("reflect-metadata");
13
+ const errors_1 = require("../../../errors");
14
+ const number_validaton_1 = require("../number-validaton");
15
+ class TestService {
16
+ sum(a, b, c) {
17
+ return a + b + c;
18
+ }
19
+ onlyInteger(value) {
20
+ return value;
21
+ }
22
+ ranged(value) {
23
+ return value;
24
+ }
25
+ }
26
+ __decorate([
27
+ number_validaton_1.validateNumbers,
28
+ __param(0, (0, number_validaton_1.min)(0)),
29
+ __param(1, (0, number_validaton_1.max)(10)),
30
+ __param(2, number_validaton_1.integer)
31
+ ], TestService.prototype, "sum", null);
32
+ __decorate([
33
+ number_validaton_1.validateNumbers,
34
+ __param(0, number_validaton_1.integer)
35
+ ], TestService.prototype, "onlyInteger", null);
36
+ __decorate([
37
+ number_validaton_1.validateNumbers,
38
+ __param(0, (0, number_validaton_1.min)(5)),
39
+ __param(0, (0, number_validaton_1.max)(10))
40
+ ], TestService.prototype, "ranged", null);
41
+ describe('number decorators', () => {
42
+ let service;
43
+ beforeEach(() => {
44
+ service = new TestService();
45
+ });
46
+ describe('valid scenarios', () => {
47
+ it('should allow valid arguments', () => {
48
+ expect(service.sum(1, 5, 3)).toBe(9);
49
+ });
50
+ it('should allow integer values', () => {
51
+ expect(service.onlyInteger(10)).toBe(10);
52
+ });
53
+ it('should allow values within min/max range', () => {
54
+ expect(service.ranged(5)).toBe(5);
55
+ expect(service.ranged(10)).toBe(10);
56
+ });
57
+ });
58
+ describe('min decorator', () => {
59
+ it('should throw if value is less than min', () => {
60
+ expect(() => service.sum(-1, 5, 3)).toThrow(errors_1.InvalidArgumentError);
61
+ });
62
+ it('should throw with correct error message', () => {
63
+ try {
64
+ service.sum(-1, 5, 3);
65
+ }
66
+ catch (e) {
67
+ expect(e).toBeInstanceOf(errors_1.InvalidArgumentError);
68
+ expect(e.message).toContain('equal or greater than 0');
69
+ }
70
+ });
71
+ });
72
+ describe('max decorator', () => {
73
+ it('should throw if value is greater than max', () => {
74
+ expect(() => service.sum(1, 20, 3)).toThrow(errors_1.InvalidArgumentError);
75
+ });
76
+ it('should throw with correct error message', () => {
77
+ try {
78
+ service.sum(1, 20, 3);
79
+ }
80
+ catch (e) {
81
+ expect(e).toBeInstanceOf(errors_1.InvalidArgumentError);
82
+ expect(e.message).toContain('equal or less than 10');
83
+ }
84
+ });
85
+ });
86
+ describe('integer decorator', () => {
87
+ it('should throw if value is not an integer', () => {
88
+ expect(() => service.onlyInteger(1.5)).toThrow(errors_1.InvalidArgumentError);
89
+ });
90
+ it('should accept safe integers', () => {
91
+ expect(service.onlyInteger(Number.MAX_SAFE_INTEGER)).toBe(Number.MAX_SAFE_INTEGER);
92
+ });
93
+ it('should throw if value is NaN', () => {
94
+ expect(() => service.onlyInteger(NaN)).toThrow(errors_1.InvalidArgumentError);
95
+ });
96
+ });
97
+ describe('combined decorators', () => {
98
+ it('should validate min and max together', () => {
99
+ expect(() => service.ranged(4)).toThrow(errors_1.InvalidArgumentError);
100
+ expect(() => service.ranged(11)).toThrow(errors_1.InvalidArgumentError);
101
+ });
102
+ it('should pass when all constraints are satisfied', () => {
103
+ expect(service.ranged(7)).toBe(7);
104
+ });
105
+ });
106
+ describe('type validation', () => {
107
+ it('should throw if value is not a number for min', () => {
108
+ expect(() => service.sum('1', 5, 3)).toThrow(errors_1.InvalidArgumentError);
109
+ });
110
+ it('should throw if value is not a number for max', () => {
111
+ expect(() => service.sum(1, '5', 3)).toThrow(errors_1.InvalidArgumentError);
112
+ });
113
+ });
114
+ });
@@ -0,0 +1 @@
1
+ export * from './number-validaton';