@venizia/ignis-docs 0.0.3 → 0.0.4-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 (131) hide show
  1. package/README.md +1 -1
  2. package/package.json +4 -2
  3. package/wiki/best-practices/api-usage-examples.md +591 -0
  4. package/wiki/best-practices/architectural-patterns.md +415 -0
  5. package/wiki/best-practices/architecture-decisions.md +488 -0
  6. package/wiki/{get-started/best-practices → best-practices}/code-style-standards.md +406 -17
  7. package/wiki/{get-started/best-practices → best-practices}/common-pitfalls.md +109 -4
  8. package/wiki/{get-started/best-practices → best-practices}/contribution-workflow.md +34 -7
  9. package/wiki/best-practices/data-modeling.md +376 -0
  10. package/wiki/best-practices/deployment-strategies.md +698 -0
  11. package/wiki/best-practices/index.md +27 -0
  12. package/wiki/best-practices/performance-optimization.md +196 -0
  13. package/wiki/best-practices/security-guidelines.md +218 -0
  14. package/wiki/{get-started/best-practices → best-practices}/troubleshooting-tips.md +97 -1
  15. package/wiki/changelogs/2025-12-16-initial-architecture.md +1 -1
  16. package/wiki/changelogs/2025-12-16-model-repo-datasource-refactor.md +1 -1
  17. package/wiki/changelogs/2025-12-17-refactor.md +1 -1
  18. package/wiki/changelogs/2025-12-18-performance-optimizations.md +5 -5
  19. package/wiki/changelogs/2025-12-18-repository-validation-security.md +13 -7
  20. package/wiki/changelogs/2025-12-26-nested-relations-and-generics.md +2 -2
  21. package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
  22. package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
  23. package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
  24. package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
  25. package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
  26. package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
  27. package/wiki/changelogs/index.md +6 -0
  28. package/wiki/changelogs/planned-schema-migrator.md +0 -8
  29. package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
  30. package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
  31. package/wiki/guides/core-concepts/components-guide.md +509 -0
  32. package/wiki/{get-started → guides}/core-concepts/components.md +24 -17
  33. package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
  34. package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
  35. package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
  36. package/wiki/guides/core-concepts/persistent/index.md +119 -0
  37. package/wiki/guides/core-concepts/persistent/models.md +241 -0
  38. package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
  39. package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
  40. package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
  41. package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
  42. package/wiki/guides/get-started/philosophy.md +682 -0
  43. package/wiki/guides/get-started/setup.md +157 -0
  44. package/wiki/guides/index.md +89 -0
  45. package/wiki/guides/reference/glossary.md +243 -0
  46. package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
  47. package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
  48. package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
  49. package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
  50. package/wiki/guides/tutorials/realtime-chat.md +1261 -0
  51. package/wiki/guides/tutorials/testing.md +723 -0
  52. package/wiki/index.md +176 -37
  53. package/wiki/references/base/application.md +27 -0
  54. package/wiki/references/base/bootstrapping.md +31 -26
  55. package/wiki/references/base/components.md +24 -7
  56. package/wiki/references/base/controllers.md +50 -20
  57. package/wiki/references/base/datasources.md +30 -0
  58. package/wiki/references/base/dependency-injection.md +39 -3
  59. package/wiki/references/base/filter-system/application-usage.md +224 -0
  60. package/wiki/references/base/filter-system/array-operators.md +132 -0
  61. package/wiki/references/base/filter-system/comparison-operators.md +109 -0
  62. package/wiki/references/base/filter-system/default-filter.md +428 -0
  63. package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
  64. package/wiki/references/base/filter-system/index.md +127 -0
  65. package/wiki/references/base/filter-system/json-filtering.md +197 -0
  66. package/wiki/references/base/filter-system/list-operators.md +71 -0
  67. package/wiki/references/base/filter-system/logical-operators.md +156 -0
  68. package/wiki/references/base/filter-system/null-operators.md +58 -0
  69. package/wiki/references/base/filter-system/pattern-matching.md +108 -0
  70. package/wiki/references/base/filter-system/quick-reference.md +431 -0
  71. package/wiki/references/base/filter-system/range-operators.md +63 -0
  72. package/wiki/references/base/filter-system/tips.md +190 -0
  73. package/wiki/references/base/filter-system/use-cases.md +452 -0
  74. package/wiki/references/base/index.md +90 -0
  75. package/wiki/references/base/middlewares.md +604 -0
  76. package/wiki/references/base/models.md +215 -23
  77. package/wiki/references/base/providers.md +731 -0
  78. package/wiki/references/base/repositories/advanced.md +555 -0
  79. package/wiki/references/base/repositories/index.md +228 -0
  80. package/wiki/references/base/repositories/mixins.md +331 -0
  81. package/wiki/references/base/repositories/relations.md +486 -0
  82. package/wiki/references/base/repositories.md +40 -635
  83. package/wiki/references/base/services.md +28 -4
  84. package/wiki/references/components/authentication.md +22 -2
  85. package/wiki/references/components/health-check.md +12 -0
  86. package/wiki/references/components/index.md +23 -0
  87. package/wiki/references/components/mail.md +687 -0
  88. package/wiki/references/components/request-tracker.md +16 -0
  89. package/wiki/references/components/socket-io.md +18 -0
  90. package/wiki/references/components/static-asset.md +14 -26
  91. package/wiki/references/components/swagger.md +17 -0
  92. package/wiki/references/configuration/environment-variables.md +427 -0
  93. package/wiki/references/configuration/index.md +73 -0
  94. package/wiki/references/helpers/cron.md +14 -0
  95. package/wiki/references/helpers/crypto.md +15 -0
  96. package/wiki/references/helpers/env.md +16 -0
  97. package/wiki/references/helpers/error.md +17 -0
  98. package/wiki/references/helpers/index.md +14 -0
  99. package/wiki/references/helpers/inversion.md +24 -4
  100. package/wiki/references/helpers/logger.md +19 -0
  101. package/wiki/references/helpers/network.md +11 -0
  102. package/wiki/references/helpers/queue.md +19 -0
  103. package/wiki/references/helpers/redis.md +21 -0
  104. package/wiki/references/helpers/socket-io.md +24 -5
  105. package/wiki/references/helpers/storage.md +18 -10
  106. package/wiki/references/helpers/testing.md +18 -0
  107. package/wiki/references/helpers/types.md +16 -0
  108. package/wiki/references/helpers/uid.md +167 -0
  109. package/wiki/references/helpers/worker-thread.md +16 -0
  110. package/wiki/references/index.md +177 -0
  111. package/wiki/references/quick-reference.md +634 -0
  112. package/wiki/references/src-details/boot.md +3 -3
  113. package/wiki/references/src-details/dev-configs.md +0 -4
  114. package/wiki/references/src-details/docs.md +2 -2
  115. package/wiki/references/src-details/index.md +86 -0
  116. package/wiki/references/src-details/inversion.md +1 -6
  117. package/wiki/references/src-details/mcp-server.md +3 -15
  118. package/wiki/references/utilities/index.md +86 -10
  119. package/wiki/references/utilities/jsx.md +577 -0
  120. package/wiki/references/utilities/request.md +0 -2
  121. package/wiki/references/utilities/statuses.md +740 -0
  122. package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
  123. package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
  124. package/wiki/get-started/best-practices/data-modeling.md +0 -177
  125. package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
  126. package/wiki/get-started/best-practices/performance-optimization.md +0 -97
  127. package/wiki/get-started/best-practices/security-guidelines.md +0 -99
  128. package/wiki/get-started/core-concepts/persistent.md +0 -539
  129. package/wiki/get-started/index.md +0 -65
  130. package/wiki/get-started/philosophy.md +0 -296
  131. package/wiki/get-started/prerequisites.md +0 -113
@@ -0,0 +1,127 @@
1
+ ---
2
+ title: Filter System Overview
3
+ description: Complete reference for the IGNIS filter system
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Filter System
8
+
9
+ Complete reference for the Ignis filter system - operators, JSON filtering, array operators, default filters, and query patterns.
10
+
11
+ > [!NOTE]
12
+ > If you're new to Ignis, start with:
13
+ > - [5-Minute Quickstart](/guides/get-started/5-minute-quickstart) - Get up and running
14
+ > - [Building a CRUD API](/guides/tutorials/building-a-crud-api) - Learn the basics
15
+ > - [Repositories](/references/base/repositories) - Repository overview
16
+
17
+ ## Prerequisites
18
+
19
+ Before reading this document, you should understand:
20
+
21
+ - [Repositories](../repositories/) - Basic repository operations (find, create, update, delete)
22
+ - [Models](../models.md) - Entity definitions and schemas
23
+ - SQL basics - Understanding of WHERE clauses and operators
24
+ - TypeScript type system - Type safety and inference
25
+
26
+ ## Documentation
27
+
28
+ | Guide | Description |
29
+ |-------|-------------|
30
+ | [**⚡ Quick Reference**](./quick-reference.md) | **Single-page cheat sheet of all operators** |
31
+ | [Comparison Operators](./comparison-operators.md) | Equality, range, null checks |
32
+ | [Pattern Matching](./pattern-matching.md) | LIKE, ILIKE, regex |
33
+ | [Logical Operators](./logical-operators.md) | AND, OR combinations |
34
+ | [List Operators](./list-operators.md) | IN, NOT IN |
35
+ | [Range Operators](./range-operators.md) | BETWEEN, NOT BETWEEN |
36
+ | [Null Operators](./null-operators.md) | IS NULL, IS NOT NULL |
37
+ | [Array Operators](./array-operators.md) | PostgreSQL array operations |
38
+ | [JSON Filtering](./json-filtering.md) | JSON/JSONB path queries |
39
+ | [Fields, Order, Pagination](./fields-order-pagination.md) | SELECT, ORDER BY, LIMIT |
40
+ | [**Default Filter**](./default-filter.md) | Automatic filter application |
41
+ | [Application Usage](./application-usage.md) | Filter flow in applications |
42
+ | [Tips & Best Practices](./tips.md) | Performance and patterns |
43
+ | [Use Cases](./use-cases.md) | Real-world examples |
44
+
45
+
46
+ ## Filter Structure
47
+
48
+ The `Filter<T>` object is the core mechanism for querying data in Ignis. It provides a structured, type-safe way to express complex queries without writing raw SQL.
49
+
50
+ ```typescript
51
+ type TFilter<T> = {
52
+ where?: TWhere<T>; // Query conditions (SQL WHERE)
53
+ fields?: TFields<T>; // Column selection (SQL SELECT)
54
+ order?: string[]; // Sorting (SQL ORDER BY)
55
+ limit?: number; // Max results (SQL LIMIT)
56
+ skip?: number; // Pagination offset (SQL OFFSET)
57
+ offset?: number; // Alias for skip
58
+ include?: TInclusion[]; // Related data (SQL JOIN / subqueries)
59
+ };
60
+ ```
61
+
62
+
63
+ ## SQL Mapping Overview
64
+
65
+ | Filter Property | SQL Equivalent | Purpose |
66
+ |-----------------|----------------|---------|
67
+ | `where` | `WHERE` | Filter rows by conditions |
68
+ | `fields` | `SELECT col1, col2` | Select specific columns |
69
+ | `order` | `ORDER BY` | Sort results |
70
+ | `limit` | `LIMIT` | Restrict number of results |
71
+ | `skip` / `offset` | `OFFSET` | Skip rows for pagination |
72
+ | `include` | `JOIN` / subquery | Include related data |
73
+
74
+
75
+ ## Basic Example
76
+
77
+ ```typescript
78
+ // Filter object
79
+ const filter = {
80
+ where: { status: 'active', role: 'admin' },
81
+ fields: ['id', 'name', 'email'],
82
+ order: ['createdAt DESC'],
83
+ limit: 10,
84
+ skip: 0
85
+ };
86
+
87
+ // Equivalent SQL
88
+ // SELECT "id", "name", "email"
89
+ // FROM "User"
90
+ // WHERE "status" = 'active' AND "role" = 'admin'
91
+ // ORDER BY "created_at" DESC
92
+ // LIMIT 10 OFFSET 0
93
+ ```
94
+
95
+
96
+ ## Quick Reference
97
+
98
+ | Want to... | Filter Syntax |
99
+ |------------|---------------|
100
+ | Equals | `{ field: value }` or `{ field: { eq: value } }` |
101
+ | Not equals | `{ field: { ne: value } }` |
102
+ | Greater than | `{ field: { gt: value } }` |
103
+ | Greater or equal | `{ field: { gte: value } }` |
104
+ | Less than | `{ field: { lt: value } }` |
105
+ | Less or equal | `{ field: { lte: value } }` |
106
+ | Is null | `{ field: null }` or `{ field: { is: null } }` |
107
+ | Is not null | `{ field: { isn: null } }` |
108
+ | In list | `{ field: { in: [a, b, c] } }` |
109
+ | Not in list | `{ field: { nin: [a, b, c] } }` |
110
+ | Range | `{ field: { between: [min, max] } }` |
111
+ | Outside range | `{ field: { notBetween: [min, max] } }` |
112
+ | Contains pattern | `{ field: { like: '%pattern%' } }` |
113
+ | Case-insensitive | `{ field: { ilike: '%pattern%' } }` |
114
+ | Regex match | `{ field: { regexp: '^pattern$' } }` |
115
+ | Array contains all | `{ arrayField: { contains: [a, b] } }` |
116
+ | Array is subset | `{ arrayField: { containedBy: [a, b, c] } }` |
117
+ | Array overlaps | `{ arrayField: { overlaps: [a, b] } }` |
118
+ | JSON nested | `{ 'jsonField.nested.path': value }` |
119
+ | JSON with operator | `{ 'jsonField.path': { gt: 10 } }` |
120
+ | AND conditions | `{ a: 1, b: 2 }` or `{ and: [{a: 1}, {b: 2}] }` |
121
+ | OR conditions | `{ or: [{ a: 1 }, { b: 2 }] }` |
122
+ | Include relation | `{ include: [{ relation: 'name' }] }` |
123
+ | Nested include | `{ include: [{ relation: 'a', scope: { include: [{ relation: 'b' }] } }] }` |
124
+ | Select fields | `{ fields: ['id', 'name'] }` |
125
+ | Order by | `{ order: ['field DESC'] }` |
126
+ | Order by JSON | `{ order: ['jsonField.path DESC'] }` |
127
+ | Paginate | `{ limit: 10, skip: 20 }` |
@@ -0,0 +1,197 @@
1
+ ---
2
+ title: JSON/JSONB Filtering
3
+ description: Query nested fields within JSON/JSONB columns using dot notation
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # JSON/JSONB Filtering
8
+
9
+ Query nested fields within JSON/JSONB columns using dot notation. This is a PostgreSQL-specific feature.
10
+
11
+
12
+ ## Basic JSON Path Syntax
13
+
14
+ ```typescript
15
+ // Column: metadata jsonb
16
+ // Data: { "user": { "id": 123, "role": "admin" }, "tags": ["urgent"] }
17
+
18
+ // Simple nested field
19
+ { where: { 'metadata.user.id': 123 } }
20
+ // SQL: "metadata" #>> '{user,id}' = '123'
21
+
22
+ // Deep nesting
23
+ { where: { 'metadata.user.role': 'admin' } }
24
+ // SQL: "metadata" #>> '{user,role}' = 'admin'
25
+
26
+ // Array index access
27
+ { where: { 'metadata.tags[0]': 'urgent' } }
28
+ // SQL: "metadata" #>> '{tags,0}' = 'urgent'
29
+
30
+ // Kebab-case keys
31
+ { where: { 'metadata.user-id': 'abc123' } }
32
+ // SQL: "metadata" #>> '{user-id}' = 'abc123'
33
+ ```
34
+
35
+
36
+ ## Supported Path Formats
37
+
38
+ | Format | Example | SQL Path |
39
+ |--------|---------|----------|
40
+ | Simple field | `metadata.name` | `{name}` |
41
+ | Nested field | `metadata.user.email` | `{user,email}` |
42
+ | Array index | `metadata.tags[0]` | `{tags,0}` |
43
+ | Nested with array | `metadata.items[2].name` | `{items,2,name}` |
44
+ | Kebab-case | `metadata.user-id` | `{user-id}` |
45
+
46
+
47
+ ## JSON with Operators
48
+
49
+ All standard operators work with JSON paths:
50
+
51
+ ```typescript
52
+ // Numeric comparison (automatic safe casting)
53
+ { where: { 'metadata.score': { gt: 80 } } }
54
+ // SQL: CASE WHEN ("metadata" #>> '{score}') ~ '^-?[0-9]+(\.[0-9]+)?$'
55
+ // THEN ("metadata" #>> '{score}')::numeric ELSE NULL END > 80
56
+
57
+ // Range comparison
58
+ { where: { 'metadata.priority': { gte: 1, lte: 5 } } }
59
+
60
+ // Between
61
+ { where: { 'metadata.score': { between: [70, 90] } } }
62
+
63
+ // Pattern matching
64
+ { where: { 'metadata.level': { ilike: '%high%' } } }
65
+ // SQL: "metadata" #>> '{level}' ILIKE '%high%'
66
+
67
+ // IN operator
68
+ { where: { 'metadata.status': { in: ['pending', 'review'] } } }
69
+ ```
70
+
71
+
72
+ ## Safe Numeric Casting
73
+
74
+ JSON fields may contain mixed types. Ignis uses safe casting to prevent database errors:
75
+
76
+ ```typescript
77
+ // Data in database:
78
+ // Row 1: { "score": 85 } <- number
79
+ // Row 2: { "score": "high" } <- string
80
+ // Row 3: { "score": null } <- null
81
+
82
+ // Query with numeric operator
83
+ { where: { 'metadata.score': { gt: 50 } } }
84
+
85
+ // Result:
86
+ // Row 1: 85 > 50 -> matched
87
+ // Row 2: "high" -> NULL -> not matched
88
+ // Row 3: null -> NULL -> not matched
89
+ ```
90
+
91
+ | JSON Value | Numeric Operation Result |
92
+ |------------|-------------------------|
93
+ | `{ "score": 85 }` | Compares as `85` |
94
+ | `{ "score": "high" }` | Treated as `NULL` (no match) |
95
+ | `{ "score": null }` | Treated as `NULL` (no match) |
96
+
97
+
98
+ ## Boolean Values
99
+
100
+ Booleans are compared as TEXT strings:
101
+
102
+ ```typescript
103
+ // JSON data: { "enabled": true }
104
+
105
+ { where: { 'metadata.enabled': true } }
106
+ // SQL: "metadata" #>> '{enabled}' = 'true'
107
+ ```
108
+
109
+
110
+ ## JSON Path Ordering
111
+
112
+ Order results by JSON fields:
113
+
114
+ ```typescript
115
+ { filter: { order: ['metadata.priority DESC'] } }
116
+ // SQL: ORDER BY "metadata" #> '{priority}' DESC
117
+
118
+ // Multiple JSON fields
119
+ { filter: { order: ['metadata.priority DESC', 'metadata.score ASC'] } }
120
+ ```
121
+
122
+ **Sort Order for JSONB Types:**
123
+
124
+ | JSONB Type | Sort Order |
125
+ |------------|------------|
126
+ | `null` | First (lowest) |
127
+ | `boolean` | `false` < `true` |
128
+ | `number` | Numeric order |
129
+ | `string` | Lexicographic |
130
+ | `array` | Element-wise |
131
+ | `object` | Key-value |
132
+
133
+
134
+ ## Path Validation & Security
135
+
136
+ Path components are validated to prevent SQL injection:
137
+
138
+ ```typescript
139
+ // Valid paths
140
+ 'metadata.fieldName'
141
+ 'metadata.nested.deep.value'
142
+ 'data.items[0]'
143
+ 'config.user_id'
144
+ 'data.meta-data' // kebab-case allowed
145
+
146
+ // Invalid (throws error)
147
+ 'metadata.field;DROP TABLE'
148
+ 'data.123invalid'
149
+ 'config.(SELECT * FROM users)'
150
+ ```
151
+
152
+ **Error Messages:**
153
+ ```
154
+ // Non-JSON column
155
+ Error: Column 'name' is not JSON/JSONB type | dataType: 'text'
156
+
157
+ // Invalid path
158
+ Error: Invalid JSON path component: 'field;DROP'
159
+ ```
160
+
161
+
162
+ ## Performance Tips
163
+
164
+ 1. **Index Your JSON Paths:**
165
+ ```sql
166
+ CREATE INDEX idx_metadata_priority ON "Product" (("metadata" ->> 'priority'));
167
+ CREATE INDEX idx_metadata_gin ON "Product" USING GIN ("metadata");
168
+ ```
169
+
170
+ 2. **Use Appropriate Types in JSON:**
171
+ ```json
172
+ // Good
173
+ { "priority": 3, "enabled": true }
174
+
175
+ // Bad
176
+ { "priority": "3", "enabled": "true" }
177
+ ```
178
+
179
+ 3. **Keep Paths Shallow:**
180
+ ```typescript
181
+ // Easier to work with
182
+ 'metadata.priority'
183
+
184
+ // Harder to optimize
185
+ 'data.level1.level2.level3.level4.value'
186
+ ```
187
+
188
+
189
+ ## Null-Safe JSON Paths
190
+
191
+ ```typescript
192
+ // If JSON field doesn't exist, #>> returns NULL
193
+ // This is safe - no errors, just no matches
194
+ { where: { 'metadata.nonexistent.field': 'value' } }
195
+ // SQL: "metadata" #>> '{nonexistent,field}' = 'value'
196
+ // Result: No rows (NULL != 'value')
197
+ ```
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: List Operators
3
+ description: Operators for matching values against arrays
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # List Operators
8
+
9
+ Operators for matching values against arrays.
10
+
11
+
12
+ ## in / inq - In Array
13
+
14
+ Matches records where field value is in the provided array.
15
+
16
+ ```typescript
17
+ { where: { status: { in: ['active', 'pending', 'review'] } } }
18
+ { where: { status: { inq: ['active', 'pending', 'review'] } } } // Alias
19
+
20
+ // SQL: WHERE "status" IN ('active', 'pending', 'review')
21
+
22
+ // Numeric IDs
23
+ { where: { categoryId: { in: [1, 2, 3, 4, 5] } } }
24
+ // SQL: WHERE "category_id" IN (1, 2, 3, 4, 5)
25
+ ```
26
+
27
+
28
+ ## nin - Not In Array
29
+
30
+ ```typescript
31
+ { where: { status: { nin: ['deleted', 'archived', 'banned'] } } }
32
+ // SQL: WHERE "status" NOT IN ('deleted', 'archived', 'banned')
33
+ ```
34
+
35
+
36
+ ## Edge Cases
37
+
38
+ | Scenario | Behavior |
39
+ |----------|----------|
40
+ | `{ in: [] }` (empty array) | Returns no rows (`false`) |
41
+ | `{ nin: [] }` (empty array) | Returns all rows (`true`) |
42
+ | `{ in: 'value' }` (non-array) | Treated as `{ eq: 'value' }` |
43
+
44
+ > [!WARNING]
45
+ > `NOT IN` excludes rows where the column is `NULL`. If your column can be `NULL`, use `OR` to include them:
46
+ > ```typescript
47
+ > where: {
48
+ > or: [
49
+ > { status: { nin: ['deleted'] } },
50
+ > { status: { is: null } }
51
+ > ]
52
+ > }
53
+ > ```
54
+
55
+
56
+ ## Performance Tip
57
+
58
+ ```typescript
59
+ // For very large arrays (1000+ items), consider chunking
60
+ const allIds = getLargeIdList(); // 5000 IDs
61
+
62
+ const chunkSize = 500;
63
+ const results = [];
64
+ for (let i = 0; i < allIds.length; i += chunkSize) {
65
+ const chunk = allIds.slice(i, i + chunkSize);
66
+ const chunkResults = await repo.find({
67
+ filter: { where: { id: { in: chunk } } }
68
+ });
69
+ results.push(...chunkResults);
70
+ }
71
+ ```
@@ -0,0 +1,156 @@
1
+ ---
2
+ title: Logical Operators
3
+ description: Combine multiple conditions with AND and OR logic
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Logical Operators
8
+
9
+ Combine multiple conditions with AND and OR logic.
10
+
11
+
12
+ ## Implicit AND
13
+
14
+ Multiple conditions in the same object are combined with AND:
15
+
16
+ ```typescript
17
+ {
18
+ where: {
19
+ status: 'active',
20
+ role: 'admin',
21
+ verified: true,
22
+ }
23
+ }
24
+ // SQL: WHERE "status" = 'active' AND "role" = 'admin' AND "verified" = true
25
+ ```
26
+
27
+
28
+ ## Explicit AND
29
+
30
+ Use `and` array for explicit AND conditions:
31
+
32
+ ```typescript
33
+ {
34
+ where: {
35
+ and: [
36
+ { status: 'active' },
37
+ { role: { in: ['admin', 'moderator'] } },
38
+ { createdAt: { gte: new Date('2024-01-01') } },
39
+ ]
40
+ }
41
+ }
42
+ // SQL: WHERE ("status" = 'active')
43
+ // AND ("role" IN ('admin', 'moderator'))
44
+ // AND ("created_at" >= '2024-01-01')
45
+ ```
46
+
47
+
48
+ ## OR Operator
49
+
50
+ Use `or` array for OR conditions:
51
+
52
+ ```typescript
53
+ {
54
+ where: {
55
+ or: [
56
+ { status: 'active' },
57
+ { isPublished: true },
58
+ { featured: true },
59
+ ]
60
+ }
61
+ }
62
+ // SQL: WHERE ("status" = 'active')
63
+ // OR ("is_published" = true)
64
+ // OR ("featured" = true)
65
+ ```
66
+
67
+
68
+ ## Nested AND/OR
69
+
70
+ Combine AND and OR for complex logic:
71
+
72
+ ```typescript
73
+ // (status = 'active' AND verified = true) OR (role = 'admin')
74
+ {
75
+ where: {
76
+ or: [
77
+ {
78
+ and: [
79
+ { status: 'active' },
80
+ { verified: true },
81
+ ]
82
+ },
83
+ { role: 'admin' },
84
+ ]
85
+ }
86
+ }
87
+
88
+ // status = 'active' AND (role = 'admin' OR role = 'moderator')
89
+ {
90
+ where: {
91
+ status: 'active',
92
+ or: [
93
+ { role: 'admin' },
94
+ { role: 'moderator' },
95
+ ]
96
+ }
97
+ }
98
+ // Equivalent to:
99
+ {
100
+ where: {
101
+ status: 'active',
102
+ role: { in: ['admin', 'moderator'] },
103
+ }
104
+ }
105
+ ```
106
+
107
+
108
+ ## NOT Logic
109
+
110
+ Use negation operators for NOT conditions:
111
+
112
+ ```typescript
113
+ // NOT equal
114
+ { where: { status: { ne: 'deleted' } } }
115
+
116
+ // NOT IN
117
+ { where: { status: { nin: ['deleted', 'banned'] } } }
118
+
119
+ // NOT LIKE
120
+ { where: { email: { nlike: '%@test.com' } } }
121
+
122
+ // NOT NULL
123
+ { where: { verifiedAt: { isn: null } } }
124
+
125
+ // NOT BETWEEN
126
+ { where: { score: { notBetween: [40, 60] } } }
127
+ ```
128
+
129
+
130
+ ## Complex Example
131
+
132
+ ```typescript
133
+ // Find active products that are either:
134
+ // - Featured with high rating, OR
135
+ // - On sale with good stock
136
+ {
137
+ where: {
138
+ status: 'active',
139
+ deletedAt: { is: null },
140
+ or: [
141
+ {
142
+ and: [
143
+ { featured: true },
144
+ { rating: { gte: 4.5 } }
145
+ ]
146
+ },
147
+ {
148
+ and: [
149
+ { onSale: true },
150
+ { stock: { gte: 10 } }
151
+ ]
152
+ }
153
+ ]
154
+ }
155
+ }
156
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ title: Null Check Operators
3
+ description: Operators for checking null and non-null values
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Null Check Operators
8
+
9
+ Operators for checking null and non-null values.
10
+
11
+
12
+ ## is - IS NULL / Equality
13
+
14
+ ```typescript
15
+ // NULL check
16
+ { where: { deletedAt: { is: null } } }
17
+ // SQL: WHERE "deleted_at" IS NULL
18
+
19
+ // Value check (same as eq)
20
+ { where: { status: { is: 'active' } } }
21
+ // SQL: WHERE "status" = 'active'
22
+ ```
23
+
24
+
25
+ ## isn - IS NOT NULL / Not Equality
26
+
27
+ ```typescript
28
+ // NOT NULL check
29
+ { where: { verifiedAt: { isn: null } } }
30
+ // SQL: WHERE "verified_at" IS NOT NULL
31
+
32
+ // Value check (same as ne)
33
+ { where: { status: { isn: 'deleted' } } }
34
+ // SQL: WHERE "status" != 'deleted'
35
+ ```
36
+
37
+
38
+ ## Common Patterns
39
+
40
+ ### Soft Delete Pattern
41
+
42
+ ```typescript
43
+ // Find active records (not deleted)
44
+ { where: { deletedAt: { is: null } } }
45
+
46
+ // Find deleted records only
47
+ { where: { deletedAt: { isn: null } } }
48
+ ```
49
+
50
+ ### Verified Users
51
+
52
+ ```typescript
53
+ // Find verified users
54
+ { where: { emailVerifiedAt: { isn: null } } }
55
+
56
+ // Find unverified users
57
+ { where: { emailVerifiedAt: { is: null } } }
58
+ ```