@dudousxd/nestjs-filter 1.0.1

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 (116) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +108 -0
  4. package/dist/adapter/adapter.d.ts +158 -0
  5. package/dist/adapter/adapter.d.ts.map +1 -0
  6. package/dist/adapter/adapter.js +2 -0
  7. package/dist/adapter/adapter.js.map +1 -0
  8. package/dist/als-store.d.ts +15 -0
  9. package/dist/als-store.d.ts.map +1 -0
  10. package/dist/als-store.js +6 -0
  11. package/dist/als-store.js.map +1 -0
  12. package/dist/base-filter.d.ts +46 -0
  13. package/dist/base-filter.d.ts.map +1 -0
  14. package/dist/base-filter.js +95 -0
  15. package/dist/base-filter.js.map +1 -0
  16. package/dist/cli/generate.d.ts +3 -0
  17. package/dist/cli/generate.d.ts.map +1 -0
  18. package/dist/cli/generate.js +43 -0
  19. package/dist/cli/generate.js.map +1 -0
  20. package/dist/decorator/apply-filter.decorator.d.ts +11 -0
  21. package/dist/decorator/apply-filter.decorator.d.ts.map +1 -0
  22. package/dist/decorator/apply-filter.decorator.js +22 -0
  23. package/dist/decorator/apply-filter.decorator.js.map +1 -0
  24. package/dist/decorator/filter-for.decorator.d.ts +4 -0
  25. package/dist/decorator/filter-for.decorator.d.ts.map +1 -0
  26. package/dist/decorator/filter-for.decorator.js +29 -0
  27. package/dist/decorator/filter-for.decorator.js.map +1 -0
  28. package/dist/decorator/filterable.decorator.d.ts +5 -0
  29. package/dist/decorator/filterable.decorator.d.ts.map +1 -0
  30. package/dist/decorator/filterable.decorator.js +24 -0
  31. package/dist/decorator/filterable.decorator.js.map +1 -0
  32. package/dist/decorator/relations.decorator.d.ts +29 -0
  33. package/dist/decorator/relations.decorator.d.ts.map +1 -0
  34. package/dist/decorator/relations.decorator.js +40 -0
  35. package/dist/decorator/relations.decorator.js.map +1 -0
  36. package/dist/errors/exceptions.d.ts +32 -0
  37. package/dist/errors/exceptions.d.ts.map +1 -0
  38. package/dist/errors/exceptions.js +56 -0
  39. package/dist/errors/exceptions.js.map +1 -0
  40. package/dist/filter/filter-exception.filter.d.ts +6 -0
  41. package/dist/filter/filter-exception.filter.d.ts.map +1 -0
  42. package/dist/filter/filter-exception.filter.js +32 -0
  43. package/dist/filter/filter-exception.filter.js.map +1 -0
  44. package/dist/index.d.ts +23 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +19 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/input/dispatcher.d.ts +2 -0
  49. package/dist/input/dispatcher.d.ts.map +1 -0
  50. package/dist/input/dispatcher.js +25 -0
  51. package/dist/input/dispatcher.js.map +1 -0
  52. package/dist/input/normalizer.d.ts +9 -0
  53. package/dist/input/normalizer.d.ts.map +1 -0
  54. package/dist/input/normalizer.js +51 -0
  55. package/dist/input/normalizer.js.map +1 -0
  56. package/dist/input/source-resolver.d.ts +3 -0
  57. package/dist/input/source-resolver.d.ts.map +1 -0
  58. package/dist/input/source-resolver.js +49 -0
  59. package/dist/input/source-resolver.js.map +1 -0
  60. package/dist/input/validator.d.ts +3 -0
  61. package/dist/input/validator.d.ts.map +1 -0
  62. package/dist/input/validator.js +33 -0
  63. package/dist/input/validator.js.map +1 -0
  64. package/dist/interceptor/apply-filter.interceptor.d.ts +10 -0
  65. package/dist/interceptor/apply-filter.interceptor.d.ts.map +1 -0
  66. package/dist/interceptor/apply-filter.interceptor.js +81 -0
  67. package/dist/interceptor/apply-filter.interceptor.js.map +1 -0
  68. package/dist/module.d.ts +15 -0
  69. package/dist/module.d.ts.map +1 -0
  70. package/dist/module.js +111 -0
  71. package/dist/module.js.map +1 -0
  72. package/dist/operators/column-filter.dto.d.ts +22 -0
  73. package/dist/operators/column-filter.dto.d.ts.map +1 -0
  74. package/dist/operators/column-filter.dto.js +61 -0
  75. package/dist/operators/column-filter.dto.js.map +1 -0
  76. package/dist/operators/index.d.ts +5 -0
  77. package/dist/operators/index.d.ts.map +1 -0
  78. package/dist/operators/index.js +4 -0
  79. package/dist/operators/index.js.map +1 -0
  80. package/dist/operators/types.d.ts +21 -0
  81. package/dist/operators/types.d.ts.map +1 -0
  82. package/dist/operators/types.js +28 -0
  83. package/dist/operators/types.js.map +1 -0
  84. package/dist/operators/validate-column-filter.d.ts +24 -0
  85. package/dist/operators/validate-column-filter.d.ts.map +1 -0
  86. package/dist/operators/validate-column-filter.js +118 -0
  87. package/dist/operators/validate-column-filter.js.map +1 -0
  88. package/dist/runner.d.ts +105 -0
  89. package/dist/runner.d.ts.map +1 -0
  90. package/dist/runner.js +554 -0
  91. package/dist/runner.js.map +1 -0
  92. package/dist/testing/filter-testing.module.d.ts +7 -0
  93. package/dist/testing/filter-testing.module.d.ts.map +1 -0
  94. package/dist/testing/filter-testing.module.js +41 -0
  95. package/dist/testing/filter-testing.module.js.map +1 -0
  96. package/dist/testing/index.d.ts +3 -0
  97. package/dist/testing/index.d.ts.map +1 -0
  98. package/dist/testing/index.js +3 -0
  99. package/dist/testing/index.js.map +1 -0
  100. package/dist/testing/mock-query-builder.d.ts +6 -0
  101. package/dist/testing/mock-query-builder.d.ts.map +1 -0
  102. package/dist/testing/mock-query-builder.js +22 -0
  103. package/dist/testing/mock-query-builder.js.map +1 -0
  104. package/dist/tokens.d.ts +8 -0
  105. package/dist/tokens.d.ts.map +1 -0
  106. package/dist/tokens.js +8 -0
  107. package/dist/tokens.js.map +1 -0
  108. package/dist/types.d.ts +110 -0
  109. package/dist/types.d.ts.map +1 -0
  110. package/dist/types.js +2 -0
  111. package/dist/types.js.map +1 -0
  112. package/dist/utils/escape-like.d.ts +10 -0
  113. package/dist/utils/escape-like.d.ts.map +1 -0
  114. package/dist/utils/escape-like.js +15 -0
  115. package/dist/utils/escape-like.js.map +1 -0
  116. package/package.json +82 -0
@@ -0,0 +1,81 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable, } from '@nestjs/common';
11
+ import { ModuleRef } from '@nestjs/core';
12
+ import { from } from 'rxjs';
13
+ import { switchMap } from 'rxjs/operators';
14
+ import { getApplyFilterMetadata, } from '../decorator/apply-filter.decorator.js';
15
+ import { getFilterableMetadata } from '../decorator/filterable.decorator.js';
16
+ import { FilterMissingAdapterException, FilterMissingEntityException, } from '../errors/exceptions.js';
17
+ import { resolveInputFromRequest } from '../input/source-resolver.js';
18
+ import { FilterRunner } from '../runner.js';
19
+ import { APPLY_FILTER_REQ_KEY, FILTER_ADAPTER } from '../tokens.js';
20
+ let ApplyFilterInterceptor = class ApplyFilterInterceptor {
21
+ moduleRef;
22
+ constructor(moduleRef) {
23
+ this.moduleRef = moduleRef;
24
+ }
25
+ intercept(ctx, next) {
26
+ const handler = ctx.getHandler();
27
+ const controller = ctx.getClass();
28
+ const entries = getApplyFilterMetadata(controller, handler.name);
29
+ if (entries.length === 0)
30
+ return next.handle();
31
+ const req = ctx
32
+ .switchToHttp()
33
+ .getRequest();
34
+ if (!req[APPLY_FILTER_REQ_KEY]) {
35
+ req[APPLY_FILTER_REQ_KEY] = [];
36
+ }
37
+ const slot = req[APPLY_FILTER_REQ_KEY];
38
+ const runner = this.moduleRef.get(FilterRunner, { strict: false });
39
+ // Resolve adapter: try each:true to find all providers, pick the non-null one
40
+ let adapter = null;
41
+ try {
42
+ const adapters = this.moduleRef.get(FILTER_ADAPTER, {
43
+ strict: false,
44
+ each: true,
45
+ });
46
+ if (Array.isArray(adapters)) {
47
+ adapter = adapters.find((a) => a !== null) ?? null;
48
+ }
49
+ else {
50
+ adapter = adapters;
51
+ }
52
+ }
53
+ catch {
54
+ adapter = null;
55
+ }
56
+ return from(this.runAll(entries, slot, req, runner, adapter)).pipe(switchMap(() => next.handle()));
57
+ }
58
+ async runAll(entries, slot, req, runner, adapter) {
59
+ if (!adapter) {
60
+ throw new FilterMissingAdapterException();
61
+ }
62
+ for (const entry of entries) {
63
+ const FilterClass = entry.options.resolve ? entry.options.resolve(req) : entry.filterClass;
64
+ const filterableMeta = getFilterableMetadata(FilterClass);
65
+ if (!filterableMeta) {
66
+ throw new FilterMissingEntityException(FilterClass.name);
67
+ }
68
+ const qb = adapter.createQueryBuilder(filterableMeta.entity);
69
+ const source = entry.options.source ?? 'auto';
70
+ const rawInput = resolveInputFromRequest(req, source);
71
+ await runner.apply(FilterClass, rawInput, qb, { req });
72
+ slot[entry.paramIndex] = qb;
73
+ }
74
+ }
75
+ };
76
+ ApplyFilterInterceptor = __decorate([
77
+ Injectable(),
78
+ __metadata("design:paramtypes", [ModuleRef])
79
+ ], ApplyFilterInterceptor);
80
+ export { ApplyFilterInterceptor };
81
+ //# sourceMappingURL=apply-filter.interceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-filter.interceptor.js","sourceRoot":"","sources":["../../src/interceptor/apply-filter.interceptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type DynamicModule, type Type } from '@nestjs/common';
2
+ import type { FilterModuleAsyncOptions, FilterModuleOptions } from './types.js';
3
+ export declare class FilterModule {
4
+ static forRoot(options?: FilterModuleOptions): DynamicModule;
5
+ static forRootAsync(options: FilterModuleAsyncOptions): DynamicModule;
6
+ static forFeature(filters: Array<Type<unknown>>): DynamicModule;
7
+ static forFeatureAsync(options: {
8
+ imports?: DynamicModule[];
9
+ filters?: Array<Type<unknown>>;
10
+ useFactory: (...args: unknown[]) => Promise<Array<Type<unknown>>> | Array<Type<unknown>>;
11
+ inject?: unknown[];
12
+ }): DynamicModule;
13
+ private static buildAsyncOptionsProvider;
14
+ }
15
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAyB,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAKtF,OAAO,KAAK,EACV,wBAAwB,EACxB,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AAQpB,qBACa,YAAY;IACvB,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa;IAgBhE,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,wBAAwB,GAAG,aAAa;IAmBrE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,aAAa;IAQ/D,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE;QAC9B,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;QAC1B,OAAO,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/B,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACzF,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;KACpB,GAAG,aAAa;IAoBjB,OAAO,CAAC,MAAM,CAAC,yBAAyB;CA2BzC"}
package/dist/module.js ADDED
@@ -0,0 +1,111 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var FilterModule_1;
8
+ import { Module } from '@nestjs/common';
9
+ import { APP_INTERCEPTOR } from '@nestjs/core';
10
+ import { ApplyFilterInterceptor } from './interceptor/apply-filter.interceptor.js';
11
+ import { FilterRunner } from './runner.js';
12
+ import { FILTER_ADAPTER, FILTER_MODULE_OPTIONS } from './tokens.js';
13
+ let FilterCoreModule = class FilterCoreModule {
14
+ };
15
+ FilterCoreModule = __decorate([
16
+ Module({})
17
+ ], FilterCoreModule);
18
+ let FilterFeatureModule = class FilterFeatureModule {
19
+ };
20
+ FilterFeatureModule = __decorate([
21
+ Module({})
22
+ ], FilterFeatureModule);
23
+ let FilterModule = FilterModule_1 = class FilterModule {
24
+ static forRoot(options = {}) {
25
+ const providers = [
26
+ { provide: FILTER_MODULE_OPTIONS, useValue: options },
27
+ { provide: FILTER_ADAPTER, useValue: null },
28
+ FilterRunner,
29
+ ApplyFilterInterceptor,
30
+ { provide: APP_INTERCEPTOR, useExisting: ApplyFilterInterceptor },
31
+ ];
32
+ return {
33
+ module: FilterCoreModule,
34
+ global: true,
35
+ providers,
36
+ exports: [FilterRunner, FILTER_MODULE_OPTIONS, FILTER_ADAPTER],
37
+ };
38
+ }
39
+ static forRootAsync(options) {
40
+ const asyncProvider = FilterModule_1.buildAsyncOptionsProvider(options);
41
+ const asyncProviders = Array.isArray(asyncProvider) ? asyncProvider : [asyncProvider];
42
+ const providers = [
43
+ ...asyncProviders,
44
+ { provide: FILTER_ADAPTER, useValue: null },
45
+ FilterRunner,
46
+ ApplyFilterInterceptor,
47
+ { provide: APP_INTERCEPTOR, useExisting: ApplyFilterInterceptor },
48
+ ];
49
+ return {
50
+ module: FilterCoreModule,
51
+ global: true,
52
+ imports: (options.imports ?? []),
53
+ providers,
54
+ exports: [FilterRunner, FILTER_MODULE_OPTIONS, FILTER_ADAPTER],
55
+ };
56
+ }
57
+ static forFeature(filters) {
58
+ return {
59
+ module: FilterFeatureModule,
60
+ providers: [...filters.map((F) => F)],
61
+ exports: filters,
62
+ };
63
+ }
64
+ static forFeatureAsync(options) {
65
+ const FILTER_FEATURE_CLASSES = 'FILTER_FEATURE_CLASSES';
66
+ const filtersProvider = {
67
+ provide: FILTER_FEATURE_CLASSES,
68
+ useFactory: options.useFactory,
69
+ inject: (options.inject ?? []),
70
+ };
71
+ // If filter classes are known up front, register them directly as providers
72
+ // so they can be resolved by moduleRef.resolve(FilterClass).
73
+ const filterProviders = (options.filters ?? []).map((F) => F);
74
+ return {
75
+ module: FilterFeatureModule,
76
+ imports: options.imports ?? [],
77
+ providers: [filtersProvider, ...filterProviders],
78
+ exports: [FILTER_FEATURE_CLASSES, ...(options.filters ?? [])],
79
+ };
80
+ }
81
+ static buildAsyncOptionsProvider(options) {
82
+ if (options.useFactory) {
83
+ return {
84
+ provide: FILTER_MODULE_OPTIONS,
85
+ useFactory: options.useFactory,
86
+ inject: (options.inject ?? []),
87
+ };
88
+ }
89
+ if (options.useClass) {
90
+ return [
91
+ { provide: options.useClass, useClass: options.useClass },
92
+ {
93
+ provide: FILTER_MODULE_OPTIONS,
94
+ useFactory: async (factory) => factory.createFilterOptions(),
95
+ inject: [options.useClass],
96
+ },
97
+ ];
98
+ }
99
+ const factoryClass = options.useExisting;
100
+ return {
101
+ provide: FILTER_MODULE_OPTIONS,
102
+ useFactory: async (factory) => factory.createFilterOptions(),
103
+ inject: [factoryClass],
104
+ };
105
+ }
106
+ };
107
+ FilterModule = FilterModule_1 = __decorate([
108
+ Module({})
109
+ ], FilterModule);
110
+ export { FilterModule };
111
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Reusable DTO for ColumnFilter with class-validator decorators.
3
+ *
4
+ * Usage in a NestJS controller body DTO:
5
+ * ```ts
6
+ * class SearchDto {
7
+ * @IsOptional()
8
+ * @IsArray()
9
+ * @ValidateNested({ each: true })
10
+ * @Type(() => ColumnFilterDto)
11
+ * where?: ColumnFilterDto[];
12
+ * }
13
+ * ```
14
+ */
15
+ export declare class ColumnFilterDto {
16
+ field: string;
17
+ operator: string;
18
+ value?: unknown;
19
+ AND?: ColumnFilterDto[];
20
+ OR?: ColumnFilterDto[];
21
+ }
22
+ //# sourceMappingURL=column-filter.dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-filter.dto.d.ts","sourceRoot":"","sources":["../../src/operators/column-filter.dto.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;IAE1B,KAAK,EAAG,MAAM,CAAC;IAIf,QAAQ,EAAG,MAAM,CAAC;IAGlB,KAAK,CAAC,EAAE,OAAO,CAAC;IAMhB,GAAG,CAAC,EAAE,eAAe,EAAE,CAAC;IAMxB,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC;CACxB"}
@@ -0,0 +1,61 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Type } from 'class-transformer';
11
+ import { IsArray, IsIn, IsOptional, IsString, ValidateNested } from 'class-validator';
12
+ import { FILTER_OPERATORS } from './types.js';
13
+ /**
14
+ * Reusable DTO for ColumnFilter with class-validator decorators.
15
+ *
16
+ * Usage in a NestJS controller body DTO:
17
+ * ```ts
18
+ * class SearchDto {
19
+ * @IsOptional()
20
+ * @IsArray()
21
+ * @ValidateNested({ each: true })
22
+ * @Type(() => ColumnFilterDto)
23
+ * where?: ColumnFilterDto[];
24
+ * }
25
+ * ```
26
+ */
27
+ export class ColumnFilterDto {
28
+ field;
29
+ operator;
30
+ value;
31
+ AND;
32
+ OR;
33
+ }
34
+ __decorate([
35
+ IsString(),
36
+ __metadata("design:type", String)
37
+ ], ColumnFilterDto.prototype, "field", void 0);
38
+ __decorate([
39
+ IsString(),
40
+ IsIn(FILTER_OPERATORS),
41
+ __metadata("design:type", String)
42
+ ], ColumnFilterDto.prototype, "operator", void 0);
43
+ __decorate([
44
+ IsOptional(),
45
+ __metadata("design:type", Object)
46
+ ], ColumnFilterDto.prototype, "value", void 0);
47
+ __decorate([
48
+ IsOptional(),
49
+ IsArray(),
50
+ ValidateNested({ each: true }),
51
+ Type(() => ColumnFilterDto),
52
+ __metadata("design:type", Array)
53
+ ], ColumnFilterDto.prototype, "AND", void 0);
54
+ __decorate([
55
+ IsOptional(),
56
+ IsArray(),
57
+ ValidateNested({ each: true }),
58
+ Type(() => ColumnFilterDto),
59
+ __metadata("design:type", Array)
60
+ ], ColumnFilterDto.prototype, "OR", void 0);
61
+ //# sourceMappingURL=column-filter.dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-filter.dto.js","sourceRoot":"","sources":["../../src/operators/column-filter.dto.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,eAAe;IAE1B,KAAK,CAAU;IAIf,QAAQ,CAAU;IAGlB,KAAK,CAAW;IAMhB,GAAG,CAAqB;IAMxB,EAAE,CAAqB;CACxB;AApBC;IADC,QAAQ,EAAE;;8CACI;AAIf;IAFC,QAAQ,EAAE;IACV,IAAI,CAAC,gBAAuC,CAAC;;iDAC5B;AAGlB;IADC,UAAU,EAAE;;8CACG;AAMhB;IAJC,UAAU,EAAE;IACZ,OAAO,EAAE;IACT,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC;;4CACJ;AAMxB;IAJC,UAAU,EAAE;IACZ,OAAO,EAAE;IACT,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC;;2CACL"}
@@ -0,0 +1,5 @@
1
+ export type { ColumnFilter, FilterOperator } from './types.js';
2
+ export { FILTER_OPERATORS } from './types.js';
3
+ export { ColumnFilterDto } from './column-filter.dto.js';
4
+ export { validateColumnFilter, validateColumnFilters, InvalidColumnFilterError, } from './validate-column-filter.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/operators/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { FILTER_OPERATORS } from './types.js';
2
+ export { ColumnFilterDto } from './column-filter.dto.js';
3
+ export { validateColumnFilter, validateColumnFilters, InvalidColumnFilterError, } from './validate-column-filter.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/operators/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Supported filter operators for generic column-based filtering.
3
+ *
4
+ * Compatible with flip-nestjs SqlQueryBuilderService ColumnFilter[].
5
+ */
6
+ export type FilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'iContains' | 'startsWith' | 'endsWith' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'notBetween' | 'in' | 'notIn' | 'isAnyOf' | 'isEmpty' | 'isNotEmpty' | 'isNull' | 'isNotNull' | 'exists' | 'notExists';
7
+ /**
8
+ * All valid operator strings, used for runtime validation.
9
+ */
10
+ export declare const FILTER_OPERATORS: readonly FilterOperator[];
11
+ /**
12
+ * A single column filter condition with optional AND/OR composition.
13
+ */
14
+ export interface ColumnFilter {
15
+ field: string;
16
+ operator: FilterOperator;
17
+ value?: unknown;
18
+ AND?: ColumnFilter[];
19
+ OR?: ColumnFilter[];
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/operators/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,WAAW,GACX,UAAU,GACV,aAAa,GACb,WAAW,GACX,YAAY,GACZ,UAAU,GACV,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GACL,SAAS,GACT,YAAY,GACZ,IAAI,GACJ,OAAO,GACP,SAAS,GACT,SAAS,GACT,YAAY,GACZ,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,WAAW,CAAC;AAEhB;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,cAAc,EAuB5C,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC;IACrB,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC;CACrB"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * All valid operator strings, used for runtime validation.
3
+ */
4
+ export const FILTER_OPERATORS = [
5
+ 'equals',
6
+ 'notEquals',
7
+ 'contains',
8
+ 'notContains',
9
+ 'iContains',
10
+ 'startsWith',
11
+ 'endsWith',
12
+ 'gt',
13
+ 'gte',
14
+ 'lt',
15
+ 'lte',
16
+ 'between',
17
+ 'notBetween',
18
+ 'in',
19
+ 'notIn',
20
+ 'isAnyOf',
21
+ 'isEmpty',
22
+ 'isNotEmpty',
23
+ 'isNull',
24
+ 'isNotNull',
25
+ 'exists',
26
+ 'notExists',
27
+ ];
28
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/operators/types.ts"],"names":[],"mappings":"AA6BA;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA8B;IACzD,QAAQ;IACR,WAAW;IACX,UAAU;IACV,aAAa;IACb,WAAW;IACX,YAAY;IACZ,UAAU;IACV,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,SAAS;IACT,YAAY;IACZ,IAAI;IACJ,OAAO;IACP,SAAS;IACT,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,WAAW;CACH,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { type ColumnFilter } from './types.js';
2
+ /**
3
+ * Maximum allowed nesting depth for AND/OR filter composition.
4
+ * Prevents stack overflow from maliciously deep payloads (DoS).
5
+ */
6
+ export declare const MAX_FILTER_DEPTH = 10;
7
+ export declare class InvalidColumnFilterError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ /**
11
+ * Validates a ColumnFilter at runtime:
12
+ * - field must be a non-empty string with no SQL-unsafe characters
13
+ * - operator must be a known FilterOperator
14
+ * - value is required for non-unary operators
15
+ * - 'between' requires a 2-element array
16
+ * - 'in'/'isAnyOf' require arrays
17
+ * - AND/OR arrays are validated recursively
18
+ */
19
+ export declare function validateColumnFilter(filter: ColumnFilter, depth?: number): void;
20
+ /**
21
+ * Validates an array of ColumnFilter objects.
22
+ */
23
+ export declare function validateColumnFilters(filters: ColumnFilter[]): void;
24
+ //# sourceMappingURL=validate-column-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-column-filter.d.ts","sourceRoot":"","sources":["../../src/operators/validate-column-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAyC,MAAM,YAAY,CAAC;AA2BtF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,SAAI,GAAG,IAAI,CA+E1E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAOnE"}
@@ -0,0 +1,118 @@
1
+ import { FILTER_OPERATORS } from './types.js';
2
+ const operatorSet = new Set(FILTER_OPERATORS);
3
+ /**
4
+ * Operators that require no value (unary operators).
5
+ */
6
+ const UNARY_OPERATORS = new Set([
7
+ 'isEmpty',
8
+ 'isNotEmpty',
9
+ 'isNull',
10
+ 'isNotNull',
11
+ 'exists',
12
+ 'notExists',
13
+ ]);
14
+ /**
15
+ * Operators that require an array value.
16
+ */
17
+ const ARRAY_OPERATORS = new Set([
18
+ 'in',
19
+ 'notIn',
20
+ 'isAnyOf',
21
+ 'between',
22
+ 'notBetween',
23
+ ]);
24
+ /**
25
+ * Maximum allowed nesting depth for AND/OR filter composition.
26
+ * Prevents stack overflow from maliciously deep payloads (DoS).
27
+ */
28
+ export const MAX_FILTER_DEPTH = 10;
29
+ export class InvalidColumnFilterError extends Error {
30
+ constructor(message) {
31
+ super(message);
32
+ this.name = 'InvalidColumnFilterError';
33
+ }
34
+ }
35
+ /**
36
+ * Validates a ColumnFilter at runtime:
37
+ * - field must be a non-empty string with no SQL-unsafe characters
38
+ * - operator must be a known FilterOperator
39
+ * - value is required for non-unary operators
40
+ * - 'between' requires a 2-element array
41
+ * - 'in'/'isAnyOf' require arrays
42
+ * - AND/OR arrays are validated recursively
43
+ */
44
+ export function validateColumnFilter(filter, depth = 0) {
45
+ if (depth > MAX_FILTER_DEPTH) {
46
+ throw new InvalidColumnFilterError(`Filter nesting exceeds maximum depth (${MAX_FILTER_DEPTH}).`);
47
+ }
48
+ if (!filter || typeof filter !== 'object') {
49
+ throw new InvalidColumnFilterError('Column filter must be a non-null object.');
50
+ }
51
+ // Validate field
52
+ if (typeof filter.field !== 'string' || filter.field.length === 0) {
53
+ throw new InvalidColumnFilterError('Column filter "field" must be a non-empty string.');
54
+ }
55
+ // Reject field names that contain SQL-unsafe characters
56
+ if (!/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(filter.field)) {
57
+ throw new InvalidColumnFilterError(`Column filter field "${filter.field}" contains invalid characters. Only letters, digits, underscores, and dots are allowed.`);
58
+ }
59
+ // Validate operator
60
+ if (!operatorSet.has(filter.operator)) {
61
+ throw new InvalidColumnFilterError(`Unknown filter operator "${filter.operator}". ` +
62
+ `Valid operators: ${FILTER_OPERATORS.join(', ')}.`);
63
+ }
64
+ const op = filter.operator;
65
+ // Reject null for non-unary operators (point to isNull instead)
66
+ if (!UNARY_OPERATORS.has(op) && filter.value === null) {
67
+ throw new InvalidColumnFilterError(`Operator "${op}" received null. Use "isNull" for NULL checks.`);
68
+ }
69
+ // Validate value
70
+ if (UNARY_OPERATORS.has(op)) {
71
+ // Unary operators don't need a value — ignore any provided value
72
+ }
73
+ else if (op === 'between' || op === 'notBetween') {
74
+ if (!Array.isArray(filter.value) || filter.value.length !== 2) {
75
+ throw new InvalidColumnFilterError(`Operator "${op}" requires a value that is a 2-element array, got: ${JSON.stringify(filter.value)}.`);
76
+ }
77
+ }
78
+ else if (ARRAY_OPERATORS.has(op)) {
79
+ if (!Array.isArray(filter.value)) {
80
+ throw new InvalidColumnFilterError(`Operator "${op}" requires an array value, got: ${typeof filter.value}.`);
81
+ }
82
+ }
83
+ else {
84
+ if (filter.value === undefined) {
85
+ throw new InvalidColumnFilterError(`Operator "${op}" requires a value.`);
86
+ }
87
+ }
88
+ // Validate nested AND
89
+ if (filter.AND !== undefined) {
90
+ if (!Array.isArray(filter.AND)) {
91
+ throw new InvalidColumnFilterError('"AND" must be an array of ColumnFilter.');
92
+ }
93
+ for (const sub of filter.AND) {
94
+ validateColumnFilter(sub, depth + 1);
95
+ }
96
+ }
97
+ // Validate nested OR
98
+ if (filter.OR !== undefined) {
99
+ if (!Array.isArray(filter.OR)) {
100
+ throw new InvalidColumnFilterError('"OR" must be an array of ColumnFilter.');
101
+ }
102
+ for (const sub of filter.OR) {
103
+ validateColumnFilter(sub, depth + 1);
104
+ }
105
+ }
106
+ }
107
+ /**
108
+ * Validates an array of ColumnFilter objects.
109
+ */
110
+ export function validateColumnFilters(filters) {
111
+ if (!Array.isArray(filters)) {
112
+ throw new InvalidColumnFilterError('Column filters must be an array.');
113
+ }
114
+ for (const filter of filters) {
115
+ validateColumnFilter(filter);
116
+ }
117
+ }
118
+ //# sourceMappingURL=validate-column-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-column-filter.js","sourceRoot":"","sources":["../../src/operators/validate-column-filter.ts"],"names":[],"mappings":"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"}