@venizia/ignis-docs 0.2.1-0 → 0.2.1-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 (145) hide show
  1. package/content/best-practices/architectural-patterns.md +3 -3
  2. package/content/best-practices/code-style-standards/naming-conventions.md +1 -1
  3. package/content/best-practices/contribution-workflow.md +2 -2
  4. package/content/best-practices/error-handling.md +94 -89
  5. package/content/best-practices/security-guidelines.md +5 -5
  6. package/content/extensions/components/api-reference.md +22 -21
  7. package/content/extensions/components/authentication/api.md +64 -28
  8. package/content/extensions/components/authentication/errors.md +19 -5
  9. package/content/extensions/components/authentication/index.md +19 -18
  10. package/content/extensions/components/authentication/usage.md +55 -30
  11. package/content/extensions/components/authorization/api.md +351 -84
  12. package/content/extensions/components/authorization/errors.md +51 -17
  13. package/content/extensions/components/authorization/getting-started.md +227 -0
  14. package/content/extensions/components/authorization/index.md +24 -16
  15. package/content/extensions/components/authorization/usage.md +45 -21
  16. package/content/extensions/components/health-check.md +15 -9
  17. package/content/extensions/components/index.md +24 -90
  18. package/content/extensions/components/mail/api.md +105 -54
  19. package/content/extensions/components/mail/errors.md +12 -10
  20. package/content/extensions/components/mail/index.md +32 -13
  21. package/content/extensions/components/mail/usage.md +26 -18
  22. package/content/extensions/components/request-tracker.md +18 -14
  23. package/content/extensions/components/socket-io/api.md +377 -882
  24. package/content/extensions/components/socket-io/errors.md +49 -51
  25. package/content/extensions/components/socket-io/index.md +72 -88
  26. package/content/extensions/components/socket-io/usage.md +107 -117
  27. package/content/extensions/components/static-asset/api.md +83 -31
  28. package/content/extensions/components/static-asset/errors.md +18 -7
  29. package/content/extensions/components/static-asset/index.md +18 -11
  30. package/content/extensions/components/static-asset/usage.md +11 -6
  31. package/content/extensions/components/template/index.md +3 -3
  32. package/content/extensions/components/websocket/api.md +58 -27
  33. package/content/extensions/components/websocket/errors.md +3 -3
  34. package/content/extensions/components/websocket/index.md +8 -7
  35. package/content/extensions/components/websocket/usage.md +21 -8
  36. package/content/extensions/helpers/cron/index.md +8 -7
  37. package/content/extensions/helpers/crypto/index.md +16 -8
  38. package/content/extensions/helpers/crypto/reference.md +96 -24
  39. package/content/extensions/helpers/env/index.md +14 -10
  40. package/content/extensions/helpers/error/index.md +99 -23
  41. package/content/extensions/helpers/index.md +61 -47
  42. package/content/extensions/helpers/inversion/index.md +23 -6
  43. package/content/extensions/helpers/inversion/reference.md +30 -22
  44. package/content/extensions/helpers/kafka/admin.md +3 -2
  45. package/content/extensions/helpers/kafka/compile-binary.md +69 -44
  46. package/content/extensions/helpers/kafka/consumer.md +24 -21
  47. package/content/extensions/helpers/kafka/examples.md +22 -234
  48. package/content/extensions/helpers/kafka/index.md +30 -62
  49. package/content/extensions/helpers/kafka/producer.md +31 -26
  50. package/content/extensions/helpers/kafka/schema-registry.md +19 -14
  51. package/content/extensions/helpers/logger/hf-logger.md +49 -22
  52. package/content/extensions/helpers/logger/index.md +37 -12
  53. package/content/extensions/helpers/logger/pino.md +31 -11
  54. package/content/extensions/helpers/logger/reference.md +243 -52
  55. package/content/extensions/helpers/network/api.md +65 -30
  56. package/content/extensions/helpers/network/index.md +32 -11
  57. package/content/extensions/helpers/queue/index.md +17 -6
  58. package/content/extensions/helpers/queue/reference.md +52 -25
  59. package/content/extensions/helpers/redis/index.md +29 -11
  60. package/content/extensions/helpers/redis/reference.md +85 -28
  61. package/content/extensions/helpers/secrets/index.md +82 -12
  62. package/content/extensions/helpers/socket-io/api.md +40 -21
  63. package/content/extensions/helpers/socket-io/index.md +26 -10
  64. package/content/extensions/helpers/storage/api.md +42 -24
  65. package/content/extensions/helpers/storage/index.md +10 -7
  66. package/content/extensions/helpers/types/index.md +20 -7
  67. package/content/extensions/helpers/types/reference.md +53 -14
  68. package/content/extensions/helpers/uid/index.md +166 -10
  69. package/content/extensions/helpers/websocket/api.md +52 -13
  70. package/content/extensions/helpers/websocket/index.md +7 -4
  71. package/content/extensions/helpers/worker-thread/index.md +9 -5
  72. package/content/extensions/helpers/worker-thread/reference.md +20 -20
  73. package/content/extensions/index.md +38 -39
  74. package/content/extensions/src-details/mcp-server.md +96 -548
  75. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  76. package/content/guides/core-concepts/persistent/index.md +5 -1
  77. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  78. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  79. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  80. package/content/guides/core-concepts/persistent/search-typesense.md +26 -14
  81. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  82. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  83. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  84. package/content/guides/get-started/philosophy.md +135 -670
  85. package/content/guides/get-started/setup.md +53 -74
  86. package/content/guides/migrations/redis-helpers-migration.md +4 -3
  87. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  88. package/content/guides/migrations/unified-connectors-migration.md +7 -6
  89. package/content/guides/tutorials/realtime-chat.md +1 -1
  90. package/content/references/base/application.md +63 -21
  91. package/content/references/base/components.md +3 -3
  92. package/content/references/base/connectors.md +14 -14
  93. package/content/references/base/controllers.md +12 -12
  94. package/content/references/base/datasources-reference.md +32 -31
  95. package/content/references/base/datasources.md +6 -6
  96. package/content/references/base/dependency-injection.md +12 -11
  97. package/content/references/base/filter-system/application-usage.md +54 -30
  98. package/content/references/base/filter-system/array-operators.md +24 -46
  99. package/content/references/base/filter-system/comparison-operators.md +47 -67
  100. package/content/references/base/filter-system/default-filter.md +59 -53
  101. package/content/references/base/filter-system/fields-order-pagination.md +92 -146
  102. package/content/references/base/filter-system/index.md +25 -13
  103. package/content/references/base/filter-system/json-filtering.md +45 -184
  104. package/content/references/base/filter-system/list-operators.md +23 -53
  105. package/content/references/base/filter-system/logical-operators.md +63 -121
  106. package/content/references/base/filter-system/null-operators.md +34 -104
  107. package/content/references/base/filter-system/pattern-matching.md +40 -55
  108. package/content/references/base/filter-system/quick-reference.md +86 -198
  109. package/content/references/base/filter-system/range-operators.md +18 -46
  110. package/content/references/base/filter-system/tips.md +6 -6
  111. package/content/references/base/filter-system/use-cases.md +33 -15
  112. package/content/references/base/grpc-controllers.md +53 -17
  113. package/content/references/base/index.md +5 -3
  114. package/content/references/base/middlewares.md +11 -10
  115. package/content/references/base/models-reference.md +17 -17
  116. package/content/references/base/models.md +4 -3
  117. package/content/references/base/providers.md +8 -8
  118. package/content/references/base/repositories/advanced.md +224 -326
  119. package/content/references/base/repositories/index.md +19 -6
  120. package/content/references/base/repositories/mixins.md +5 -5
  121. package/content/references/base/repositories/relations.md +160 -293
  122. package/content/references/base/repositories/soft-deletable.md +16 -6
  123. package/content/references/base/secrets.md +17 -13
  124. package/content/references/base/services.md +6 -4
  125. package/content/references/configuration/environment-variables.md +31 -23
  126. package/content/references/configuration/index.md +6 -4
  127. package/content/references/index.md +1 -1
  128. package/content/references/utilities/duration.md +85 -0
  129. package/content/references/utilities/index.md +5 -1
  130. package/content/references/utilities/jsx-reference.md +11 -11
  131. package/content/references/utilities/jsx.md +2 -2
  132. package/content/references/utilities/module.md +78 -25
  133. package/content/references/utilities/request.md +2 -1
  134. package/content/references/utilities/retry.md +139 -0
  135. package/content/references/utilities/schema.md +2 -2
  136. package/content/references/utilities/statuses-reference.md +4 -4
  137. package/content/references/utilities/statuses.md +5 -5
  138. package/dist/mcp-server/index.js +0 -0
  139. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  140. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  141. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  142. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  143. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  144. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  145. package/package.json +17 -16
@@ -2,274 +2,161 @@
2
2
  title: Filter Operators Quick Reference
3
3
  description: Single-page cheat sheet of all filter operators
4
4
  difficulty: intermediate
5
- lastUpdated: 2026-03-15
5
+ lastUpdated: 2026-07-23
6
6
  ---
7
7
 
8
8
  # Filter Operators Quick Reference
9
9
 
10
- Complete single-page reference for all IGNIS filter operators. For detailed explanations and examples, see the individual operator guides linked below, or start at the [Filter System Overview](./) for the full `filter` shape.
10
+ Every `where` operator, one line each. For the `filter` shape and the mental model, start at the [Filter System Overview](./). For explanations and worked examples, follow the **See** link under each table.
11
11
 
12
12
  ## Comparison Operators
13
13
 
14
- | Operator | SQL | TypeScript Example | Description |
15
- |----------|-----|-------------------|-------------|
14
+ | Operator | SQL | Example | Description |
15
+ |---|---|---|---|
16
16
  | `eq` | `=` | `{ status: { eq: 'active' } }` | Equal to |
17
17
  | `ne` | `!=` | `{ status: { ne: 'deleted' } }` | Not equal to |
18
- | `neq` | `!=` | `{ status: { neq: 'deleted' } }` | Not equal to (alias for `ne`) |
18
+ | `neq` | `!=` | `{ status: { neq: 'deleted' } }` | Alias for `ne` |
19
19
  | `gt` | `>` | `{ age: { gt: 18 } }` | Greater than |
20
20
  | `gte` | `>=` | `{ age: { gte: 18 } }` | Greater than or equal |
21
21
  | `lt` | `<` | `{ price: { lt: 100 } }` | Less than |
22
22
  | `lte` | `<=` | `{ price: { lte: 100 } }` | Less than or equal |
23
23
 
24
24
  > [!NOTE]
25
- > `ne`/`neq` follow SQL three-valued logic: a row whose field is `NULL` **never** matches `{ field: { neq: value } }` (`NULL <> value` evaluates to UNKNOWN, not TRUE). To include NULL rows, add `{ or: [{ field: { neq: value } }, { field: null }] }`.
25
+ > `ne`/`neq` follow SQL three-valued logic. A row whose field is `NULL` never matches `{ field: { neq: value } }`, because `NULL <> value` is UNKNOWN, not TRUE. To include NULL rows too, use `{ or: [{ field: { neq: value } }, { field: null }] }`.
26
26
 
27
27
  **See:** [Comparison Operators Guide](./comparison-operators.md)
28
28
 
29
+ ## Null / Presence Operators
29
30
 
30
- ## Range Operators
31
-
32
- | Operator | SQL | TypeScript Example | Description |
33
- |----------|-----|-------------------|-------------|
34
- | `between` | `BETWEEN` | `{ age: { between: [18, 65] } }` | Value is within range (inclusive) |
35
- | `notBetween` | `NOT BETWEEN` | `{ age: { notBetween: [0, 18] } }` | Value is outside range |
31
+ | Operator | SQL | Example | Description |
32
+ |---|---|---|---|
33
+ | `is` | `IS NULL` / `=` | `{ deletedAt: { is: null } }` | `IS NULL` when the value is `null`, equality otherwise |
34
+ | `isn` | `IS NOT NULL` / `!=` | `{ email: { isn: null } }` | `IS NOT NULL` when the value is `null`, not-equal otherwise |
35
+ | `exists` | `IS NOT NULL` / `IS NULL` | `{ deletedAt: { exists: false } }` | `exists: true` -> `IS NOT NULL`, `exists: false` -> `IS NULL` |
36
+ | `notExists` | `IS NULL` / `IS NOT NULL` | `{ verifiedAt: { notExists: true } }` | Inverse of `exists` |
36
37
 
37
- **See:** [Range Operators Guide](./range-operators.md)
38
+ **Shorthand:** a bare `null` is implicit `IS NULL`. `{ deletedAt: null }` is identical to `{ deletedAt: { eq: null } }` or `{ deletedAt: { is: null } }`.
38
39
 
40
+ **See:** [Null Operators Guide](./null-operators.md)
39
41
 
40
42
  ## List Operators
41
43
 
42
- | Operator | SQL | TypeScript Example | Description |
43
- |----------|-----|-------------------|-------------|
44
- | `in` | `IN` | `{ status: { in: ['active', 'pending'] } }` | Value matches any in array |
44
+ | Operator | SQL | Example | Description |
45
+ |---|---|---|---|
46
+ | `in` | `IN` | `{ status: { in: ['active', 'pending'] } }` | Value matches any in the array |
45
47
  | `inq` | `IN` | `{ status: { inq: ['active', 'pending'] } }` | Alias for `in` |
46
- | `nin` | `NOT IN` | `{ status: { nin: ['deleted', 'banned'] } }` | Value doesn't match any in array |
48
+ | `nin` | `NOT IN` | `{ status: { nin: ['deleted', 'banned'] } }` | Value matches none in the array |
49
+
50
+ > [!NOTE]
51
+ > An empty array is a hard edge. `{ in: [] }` / `{ inq: [] }` match no rows; `{ nin: [] }` matches every row, because an empty exclusion list excludes nothing.
47
52
 
48
53
  **See:** [List Operators Guide](./list-operators.md)
49
54
 
55
+ ## Range Operators
56
+
57
+ | Operator | SQL | Example | Description |
58
+ |---|---|---|---|
59
+ | `between` | `BETWEEN` | `{ age: { between: [18, 65] } }` | Value is within range, inclusive |
60
+ | `notBetween` | `NOT BETWEEN` | `{ age: { notBetween: [0, 18] } }` | Value is outside range |
61
+
62
+ Both require a 2-element array `[min, max]` - anything else throws.
63
+
64
+ **See:** [Range Operators Guide](./range-operators.md)
50
65
 
51
66
  ## Pattern Matching Operators
52
67
 
53
- | Operator | SQL | TypeScript Example | Description |
54
- |----------|-----|-------------------|-------------|
55
- | `like` | `LIKE` | `{ name: { like: '%john%' } }` | Pattern match (case-sensitive) |
56
- | `nlike` | `NOT LIKE` | `{ name: { nlike: '%test%' } }` | Inverse pattern match (case-sensitive) |
57
- | `ilike` | `ILIKE` | `{ email: { ilike: '%@gmail.com' } }` | Pattern match (case-insensitive) |
58
- | `nilike` | `NOT ILIKE` | `{ email: { nilike: '%spam%' } }` | Inverse pattern match (case-insensitive) |
68
+ | Operator | SQL | Example | Description |
69
+ |---|---|---|---|
70
+ | `like` | `LIKE` | `{ name: { like: '%john%' } }` | Pattern match, case-sensitive |
71
+ | `nlike` | `NOT LIKE` | `{ name: { nlike: '%test%' } }` | Inverse, case-sensitive |
72
+ | `ilike` | `ILIKE` | `{ email: { ilike: '%@gmail.com' } }` | Pattern match, case-insensitive |
73
+ | `nilike` | `NOT ILIKE` | `{ email: { nilike: '%spam%' } }` | Inverse, case-insensitive |
59
74
  | `regexp` | `~` | `{ code: { regexp: '^[A-Z]{3}$' } }` | Regular expression (PostgreSQL) |
60
75
  | `iregexp` | `~*` | `{ code: { iregexp: '^[a-z]{3}$' } }` | Case-insensitive regex (PostgreSQL) |
61
76
 
62
- **Wildcard Patterns:**
63
- - `%` - Matches any sequence of characters
64
- - `_` - Matches any single character
77
+ **Wildcards:** `%` matches any sequence of characters, `_` matches any single character.
65
78
 
66
79
  **See:** [Pattern Matching Guide](./pattern-matching.md)
67
80
 
68
-
69
- ## Null Check Operators
70
-
71
- | Operator | SQL | TypeScript Example | Description |
72
- |----------|-----|-------------------|-------------|
73
- | `is` | `IS NULL` / `=` | `{ deletedAt: { is: null } }` | IS NULL when value is `null`, equality otherwise |
74
- | `isn` | `IS NOT NULL` / `!=` | `{ email: { isn: null } }` | IS NOT NULL when value is `null`, not-equal otherwise |
75
-
76
- **Shorthand Syntax:**
77
- ```typescript
78
- // Direct null assignment (implicit IS NULL)
79
- { deletedAt: null }
80
- // SQL: WHERE "deleted_at" IS NULL
81
-
82
- // Using eq with null
83
- { deletedAt: { eq: null } }
84
- // SQL: WHERE "deleted_at" IS NULL
85
-
86
- // Using ne with null
87
- { deletedAt: { ne: null } }
88
- // SQL: WHERE "deleted_at" IS NOT NULL
89
- ```
90
-
91
- **See:** [Null Operators Guide](./null-operators.md)
92
-
93
-
94
- ## Presence & Negation Operators
95
-
96
- | Operator | SQL | TypeScript Example | Description |
97
- |----------|-----|-------------------|-------------|
98
- | `exists` | `IS NOT NULL` / `IS NULL` | `{ deletedAt: { exists: false } }` | `exists: true` -> IS NOT NULL, `exists: false` -> IS NULL |
99
- | `notExists` | `IS NULL` / `IS NOT NULL` | `{ verifiedAt: { notExists: true } }` | Inverse of `exists` (`notExists: true` -> IS NULL) |
100
- | `not` | `NOT (...)` | `{ status: { not: 'archived' } }` / `{ views: { not: { gt: 100 } } }` | Negates the nested condition; a bare value negates `eq` |
101
-
102
- `exists`/`notExists`/`not` are supported on the PostgreSQL connector. `not` recurses: `{ not: { gt: 100 } }` becomes `NOT (col > 100)`, and `{ not: 5 }` becomes `NOT (col = 5)`. `exists` also works over JSON paths on PostgreSQL (`{ 'metadata.score': { exists: true } }`).
103
-
104
- **See:** [Null Operators Guide](./null-operators.md) (`exists`/`notExists`), [Logical Operators Guide](./logical-operators.md) (`not`)
105
-
106
-
107
81
  ## Logical Operators
108
82
 
109
- | Operator | SQL | TypeScript Example | Description |
110
- |----------|-----|-------------------|-------------|
111
- | `and` | `AND` | `{ and: [{ age: { gt: 18 } }, { status: 'active' }] }` | All conditions must be true |
83
+ | Operator | SQL | Example | Description |
84
+ |---|---|---|---|
85
+ | `and` | `AND` | `{ and: [{ age: { gt: 18 } }, { status: 'active' }] }` | Every condition must be true |
112
86
  | `or` | `OR` | `{ or: [{ role: 'admin' }, { role: 'moderator' }] }` | At least one condition must be true |
113
- | `and: []` | (dropped) | `{ and: [] }` | Vacuously true - no condition added to the query |
87
+ | `not` | `NOT (...)` | `{ status: { not: 'archived' } }` / `{ views: { not: { gt: 100 } } }` | Negates the nested condition; a bare value negates `eq` |
88
+ | (implicit) | `AND` | `{ status: 'active', age: { gte: 18 } }` | Multiple top-level `where` keys are ANDed together |
89
+ | `and: []` | (dropped) | `{ and: [] }` | Vacuously true - no condition added |
114
90
  | `or: []` | `false` | `{ or: [] }` | Vacuously false - matches no rows |
115
91
 
116
- **Implicit AND:**
117
- ```typescript
118
- // Multiple fields = implicit AND
119
- {
120
- status: 'active',
121
- age: { gte: 18 },
122
- role: 'user'
123
- }
124
- // WHERE status = 'active' AND age >= 18 AND role = 'user'
125
- ```
92
+ `not` recurses: `{ not: { gt: 100 } }` becomes `NOT (col > 100)`; `{ not: 5 }` becomes `NOT (col = 5)`; `{ not: null }` becomes `IS NOT NULL`.
126
93
 
127
- **NOT logic** is expressed via the general-purpose `not` operator (`{ field: { not: <value | operatorObject> } }`) or the dedicated negation operators (`ne`, `neq`, `nin`, `nlike`, `nilike`, `notBetween`, `isn`).
94
+ `exists`/`notExists` also work over JSON paths (`{ 'metadata.score': { exists: true } }`).
128
95
 
129
96
  **See:** [Logical Operators Guide](./logical-operators.md)
130
97
 
98
+ ## Array Operators (PostgreSQL)
131
99
 
132
- ## PostgreSQL Array Operators
100
+ For array columns (`varchar[]`, `text[]`, `integer[]`, and so on) - not to be confused with `in`/`nin`, which match a scalar against a list.
133
101
 
134
- These operators work with PostgreSQL array columns (`varchar[]`, `text[]`, `integer[]`, etc.).
102
+ | Operator | SQL | Example | Description |
103
+ |---|---|---|---|
104
+ | `contains` | `@>` | `{ tags: { contains: ['typescript', 'nodejs'] } }` | Column array contains ALL given elements |
105
+ | `containedBy` | `<@` | `{ tags: { containedBy: ['ts', 'js', 'go', 'rust'] } }` | Column array is a subset of the given array |
106
+ | `overlaps` | `&&` | `{ tags: { overlaps: ['react', 'vue', 'angular'] } }` | Arrays share at least one element |
135
107
 
136
- | Operator | PostgreSQL | TypeScript Example | Description |
137
- |----------|------------|-------------------|-------------|
138
- | `contains` | `@>` | `{ tags: { contains: ['typescript', 'nodejs'] } }` | Array contains **ALL** specified elements |
139
- | `containedBy` | `<@` | `{ tags: { containedBy: ['ts', 'js', 'go', 'rust'] } }` | Array is subset of specified array |
140
- | `overlaps` | `&&` | `{ tags: { overlaps: ['react', 'vue', 'angular'] } }` | Arrays have at least one common element |
141
-
142
- **Important:** These are array-specific operators, not to be confused with `in`/`nin` which match scalar values against an array.
108
+ A scalar operand is wrapped into a single-element array automatically.
143
109
 
144
110
  **See:** [Array Operators Guide](./array-operators.md)
145
111
 
112
+ ## JSON Path Operators (PostgreSQL)
146
113
 
147
- ## JSON/JSONB Operators (PostgreSQL)
148
-
149
- Query nested fields within JSON/JSONB columns using dot notation as the key.
150
-
151
- ### JSON Path Syntax
114
+ A dot-notation key targets a JSON/JSONB column instead of a top-level one.
152
115
 
153
116
  | Syntax | Example | Description |
154
- |--------|---------|-------------|
155
- | Dot notation | `{ 'metadata.user.name': 'John' }` | Access nested properties |
156
- | Array index | `{ 'metadata.tags[0]': 'urgent' }` | Access array elements |
117
+ |---|---|---|
118
+ | Dot notation | `{ 'metadata.user.name': 'John' }` | Access a nested property |
119
+ | Array index | `{ 'metadata.tags[0]': 'urgent' }` | Access an array element |
157
120
  | Combined | `{ 'metadata.users[0].email': value }` | Nested arrays and objects |
158
121
 
159
- ### JSON Path with Operators
122
+ **Supported operators:** `eq`, `ne`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `inq`, `nin`, `like`, `nlike`, `ilike`, `nilike`, `between`, `notBetween`, `regexp`, `iregexp`, `is`, `isn`, `exists`, `notExists`, `not`. That's the same set as top-level columns, minus the array operators (`contains`/`containedBy`/`overlaps`), which need a real array column.
160
123
 
161
- ```typescript
162
- // Equality (string comparison via #>>)
163
- { 'metadata.user.role': 'admin' }
164
- // SQL: "metadata" #>> '{user,role}' = 'admin'
165
-
166
- // Numeric comparison (safe casting via CASE/numeric)
167
- { 'metadata.score': { gt: 80 } }
168
-
169
- // Pattern matching
170
- { 'metadata.level': { ilike: '%high%' } }
171
- // SQL: "metadata" #>> '{level}' ILIKE '%high%'
172
-
173
- // Multiple JSON conditions
174
- {
175
- and: [
176
- { 'metadata.user.age': { gt: 18 } },
177
- { 'metadata.user.country': 'US' }
178
- ]
179
- }
180
- ```
181
-
182
- ### Supported Operators with JSON Paths
183
-
184
- All comparison operators work with JSON path queries:
185
- - `eq`, `ne`, `neq`, `gt`, `gte`, `lt`, `lte`
186
- - `in`, `inq`, `nin`
187
- - `like`, `nlike`, `ilike`, `nilike`
188
- - `between`, `notBetween`
189
- - `regexp`, `iregexp`
190
- - `is`, `isn`
191
- - `exists`, `notExists`, `not`
192
-
193
- Numeric operators (`gt`, `gte`, `lt`, `lte`, `between`, `notBetween`) use safe numeric casting to handle mixed JSON value types.
124
+ Numeric operators cast the extracted text to `numeric` automatically: `gt`, `gte`, `lt`, `lte`, `between`, `notBetween`, and `eq`/`ne`/`neq`/`in`/`inq`/`nin` when the operand is a number. So `{ 'metadata.score': { gt: 80 } }` compares as a number, not a string.
194
125
 
195
126
  **See:** [JSON Filtering Guide](./json-filtering.md)
196
127
 
128
+ ## Fields, Order & Pagination
197
129
 
198
- ## Fields, Ordering & Pagination
199
-
200
- ### Select Specific Fields
201
-
202
- ```typescript
203
- const users = await userRepository.find({
204
- filter: {
205
- where: { isActive: true },
206
- fields: ['id', 'name', 'email'], // Only return these fields
207
- }
208
- });
209
- ```
210
-
211
- ### Ordering
212
-
213
- ```typescript
214
- // Single field
215
- { order: ['createdAt DESC'] }
216
-
217
- // Multiple fields
218
- { order: ['status ASC', 'createdAt DESC'] }
219
-
220
- // Default direction is ASC
221
- { order: ['name'] } // Same as 'name ASC'
222
-
223
- // JSON path ordering
224
- { order: ['metadata.priority DESC'] }
225
- ```
226
-
227
- ### Pagination
228
-
229
- ```typescript
230
- {
231
- limit: 10, // Max records to return (default: 10)
232
- skip: 20, // Skip first 20 records (alias: offset)
233
- }
234
-
235
- // Page 3 with 10 items per page
236
- {
237
- limit: 10,
238
- skip: 20, // (page - 1) * limit = (3 - 1) * 10
239
- }
240
- ```
130
+ | Property | Syntax | Example | Result |
131
+ |---|---|---|---|
132
+ | `fields` (array) | `string[]` | `fields: ['id', 'name', 'email']` | `SELECT` only those columns |
133
+ | `fields` (object) | `{ field: true }` | `fields: { id: true, name: true }` | Same - inclusion-only, `false` is ignored |
134
+ | `order` | `'field ASC'` / `'field DESC'` | `order: ['createdAt DESC']` | `ORDER BY`; default direction is `ASC` (`order: ['name']` = `'name ASC'`) |
135
+ | `order` (JSON path) | `'a.b DESC'` | `order: ['metadata.priority DESC']` | `ORDER BY` on a JSON path |
136
+ | `limit` | number | `limit: 10` | `LIMIT`; omitted -> `query.limit ?? settings.defaultLimit ?? 10` |
137
+ | `skip` | number | `skip: 20` | `OFFSET`; alias of `offset` - `skip` wins if both are given |
138
+ | `offset` | number | `offset: 20` | `OFFSET`; alias of `skip` |
241
139
 
242
140
  **See:** [Fields, Ordering & Pagination Guide](./fields-order-pagination.md)
243
141
 
142
+ ## Default Filter
244
143
 
245
- ## Default Filters
144
+ A model's `settings.defaultFilter` merges into every read, update, and delete for that model.
246
145
 
247
- Automatically apply filters to all repository queries (e.g., soft delete, multi-tenant).
146
+ | Collision shape | Result |
147
+ |---|---|
148
+ | Different keys | AND-composed - `{ isDeleted: false }` default + `{ status: 'published' }` caller filter -> `WHERE "isDeleted" = false AND "status" = 'published'` |
149
+ | Same key, scalar vs. scalar | Caller wins - the one override escape, no `shouldSkipDefaultFilter` needed |
150
+ | Same key, scalar vs. operator object (either side) | AND-composed |
151
+ | Same key, both `and` | Concatenated - both groups hold |
152
+ | Same key, both `or` | Kept as two separate conjuncts, never unioned |
248
153
 
249
154
  ```typescript
250
- @model({
251
- type: 'entity',
252
- settings: {
253
- defaultFilter: {
254
- where: { isDeleted: false },
255
- limit: 100,
256
- },
257
- },
258
- })
259
- export class User extends BaseEntity<typeof User.schema> {
260
- static override schema = userTable;
261
- }
262
-
263
- // All queries automatically include the default filter
264
- await userRepository.find({ filter: {} });
265
- // WHERE isDeleted = false LIMIT 100
266
-
267
- // Skip default filter for admin operations
155
+ // Skip the default filter entirely
268
156
  await userRepository.find({
269
- filter: {},
157
+ filter: { where: { status: 'published' } },
270
158
  options: { shouldSkipDefaultFilter: true },
271
159
  });
272
- // No automatic filter applied
273
160
  ```
274
161
 
275
162
  **See:** [Default Filter Guide](./default-filter.md)
@@ -280,5 +167,6 @@ await userRepository.find({
280
167
 
281
168
  **Files:**
282
169
 
283
- - [`packages/core/src/connectors/postgres/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/filter.ts) - `FilterBuilder`, translates `TFilter` to Drizzle/SQL
284
- - [`packages/core/src/base/repositories/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/repositories/common/operators.ts) - `QueryOperators`/`Sorts` constants
170
+ - [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, translates `TFilter` to Drizzle/SQL
171
+ - [`packages/core-server/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, one handler per operator
172
+ - [`packages/filter/src/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/filter/src/common/operators.ts) - `QueryOperators`/`Sorts` constants
@@ -6,76 +6,48 @@ difficulty: intermediate
6
6
 
7
7
  # Range Operators
8
8
 
9
- Operators for matching values within or outside a range.
9
+ Matches a field against a `[min, max]` range.
10
10
 
11
+ | Operator | SQL | Meaning |
12
+ |----------|-----|---------|
13
+ | `between` | `BETWEEN ... AND ...` | Value is within the range (inclusive) |
14
+ | `notBetween` | `NOT (... BETWEEN ... AND ...)` | Value is outside the range |
11
15
 
12
16
  ## between
13
17
 
14
- Find values within a range (inclusive):
15
-
16
18
  ```typescript
17
- // Numeric range
18
19
  { where: { price: { between: [100, 500] } } }
19
20
  // SQL: WHERE "price" BETWEEN 100 AND 500
20
-
21
- // Date range
22
- {
23
- where: {
24
- createdAt: {
25
- between: [new Date('2024-01-01'), new Date('2024-12-31')]
26
- }
27
- }
28
- }
29
- // SQL: WHERE "created_at" BETWEEN '2024-01-01' AND '2024-12-31'
30
-
31
- // String range (lexicographic)
32
- { where: { lastName: { between: ['A', 'M'] } } }
33
- // SQL: WHERE "last_name" BETWEEN 'A' AND 'M'
34
21
  ```
35
22
 
36
- > [!WARNING]
37
- > The value MUST be an array with exactly 2 elements `[min, max]`. Invalid values throw an error:
38
- > ```
39
- > Error: [BETWEEN] Invalid value: expected array of 2 elements, got ...
40
- > ```
23
+ **Notice:** both bounds are inclusive.
41
24
 
25
+ **Edge cases:**
26
+ - The value must be a 2-element array `[min, max]`; anything else throws `[PostgresQueryOperators][BETWEEN] Invalid value: expected array of 2 elements, got ...`.
27
+ - If either bound is `null`, the condition matches no rows (SQL `NULL` comparison).
28
+ - If `min > max`, the condition matches no rows.
42
29
 
43
30
  ## notBetween
44
31
 
45
- Find values outside a range:
46
-
47
32
  ```typescript
48
33
  { where: { score: { notBetween: [40, 60] } } }
49
34
  // SQL: WHERE NOT ("score" BETWEEN 40 AND 60)
50
- // Matches: scores < 40 OR scores > 60
51
35
  ```
52
36
 
53
- > [!WARNING]
54
- > Same validation as `between` -- the value MUST be an array with exactly 2 elements.
55
-
37
+ **Notice:** matches values strictly outside the range.
56
38
 
57
- ## Alternative: Using gte/lte
58
-
59
- You can also express ranges using comparison operators:
60
-
61
- ```typescript
62
- // Equivalent to between: [100, 500]
63
- { where: { price: { gte: 100, lte: 500 } } }
64
- // SQL: WHERE "price" >= 100 AND "price" <= 500
65
-
66
- // Exclusive range (not including boundaries)
67
- { where: { price: { gt: 100, lt: 500 } } }
68
- // SQL: WHERE "price" > 100 AND "price" < 500
69
- ```
39
+ **Edge cases:**
40
+ - Same 2-element array validation as `between`, throwing `[PostgresQueryOperators][NOT_BETWEEN] Invalid value: expected array of 2 elements, got ...`.
41
+ - A `NULL` column matches neither `between` nor `notBetween`.
70
42
 
71
43
  ## See also
72
44
 
73
45
  - [Filter System Overview](./) - the `filter` shape and the full `where` operator table
74
- - [Comparison Operators](./comparison-operators) - `gt`/`gte`/`lt`/`lte`, the building blocks of the `gte`/`lte` equivalent above
46
+ - [Comparison Operators](./comparison-operators) - `gt`/`gte`/`lt`/`lte`, which can express the same range as an alternative to `between`/`notBetween`
75
47
  - [Quick Reference](./quick-reference) - every operator, one line each
76
48
 
77
49
  **Files:**
78
50
 
79
- - [`packages/core/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, per-operator SQL builders
80
- - [`packages/core/src/connectors/postgres/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/filter.ts) - `FilterBuilder`, translates `TFilter` to Drizzle/SQL
81
- - [`packages/core/src/base/repositories/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/repositories/common/operators.ts) - `QueryOperators` constants
51
+ - [`packages/core-server/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, per-operator SQL builders
52
+ - [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, translates `TFilter` to Drizzle/SQL
53
+ - [`packages/filter/src/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/filter/src/common/operators.ts) - `QueryOperators` constants
@@ -6,11 +6,11 @@ difficulty: intermediate
6
6
 
7
7
  # Pro Tips & Edge Cases
8
8
 
9
- Behavior that is easy to assume incorrectly when writing a `filter` - each one verified against `FilterBuilder`/`PostgresQueryOperators`.
9
+ A filter can return the wrong rows even when every operator name looks right. Each entry below is verified against `FilterBuilder`/`PostgresQueryOperators` in `packages/core-server`.
10
10
 
11
11
  ## `NOT IN` and `!=` silently exclude `NULL`
12
12
 
13
- SQL three-valued logic, not an IGNIS quirk: a row whose column is `NULL` never matches `nin`, `ne`, or `neq`, because `NULL <> value` evaluates to UNKNOWN rather than TRUE.
13
+ This is SQL three-valued logic, not an IGNIS quirk. A row whose column is `NULL` never matches `nin`, `ne`, or `neq`, because `NULL <> value` evaluates to UNKNOWN rather than TRUE.
14
14
 
15
15
  ```typescript
16
16
  { where: { status: { nin: ['deleted'] } } }
@@ -38,7 +38,7 @@ if (ids.length === 0) {
38
38
 
39
39
  ## JSON numeric comparisons need actual JSON numbers
40
40
 
41
- A JSON path comparison casts safely with `CASE WHEN (...) ~ '^-?[0-9]+(\.[0-9]+)?$' THEN (...)::numeric ELSE NULL END` - the regex has to match or the cast yields `NULL` and the row is excluded:
41
+ A JSON path comparison casts safely with `CASE WHEN (...) ~ '^-?[0-9]+(\.[0-9]+)?$' THEN (...)::numeric ELSE NULL END`. The regex has to match, or the cast yields `NULL` and the row is excluded:
42
42
 
43
43
  ```typescript
44
44
  // { "priority": "3" } (string) - regex matches "3" -> casts to numeric 3 -> 3 > 2 matches
@@ -84,7 +84,7 @@ Store numbers as JSON numbers (`{ "priority": 3 }`), not numeric strings, to avo
84
84
  ```typescript
85
85
  { fields: { id: true, name: true, email: true } }
86
86
 
87
- // Setting a key to `false` does NOT exclude it - the key is simply ignored.
87
+ // Setting a key to `false` does NOT exclude it - the key is ignored.
88
88
  // To exclude fields, list only the ones you want, as an array:
89
89
  { fields: ['id', 'name', 'email'] }
90
90
  ```
@@ -150,5 +150,5 @@ const products = await productRepository.find({
150
150
 
151
151
  **Files:**
152
152
 
153
- - [`packages/core/src/connectors/postgres/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/filter.ts) - `FilterBuilder`, JSON path casting, `toColumns`
154
- - [`packages/core/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, empty-array and array-operator handling
153
+ - [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, JSON path casting, `toColumns`
154
+ - [`packages/core-server/src/connectors/postgres/repositories/dialect/query.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/dialect/query.ts) - `PostgresQueryOperators.FNS`, empty-array and array-operator handling