@venizia/ignis-docs 0.0.2 → 0.0.4-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) 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 +647 -182
  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 +86 -0
  21. package/wiki/changelogs/2025-12-26-transaction-support.md +57 -0
  22. package/wiki/changelogs/2025-12-29-dynamic-binding-registration.md +104 -0
  23. package/wiki/changelogs/2025-12-29-snowflake-uid-helper.md +100 -0
  24. package/wiki/changelogs/2025-12-30-repository-enhancements.md +214 -0
  25. package/wiki/changelogs/2025-12-31-json-path-filtering-array-operators.md +214 -0
  26. package/wiki/changelogs/2025-12-31-string-id-custom-generator.md +137 -0
  27. package/wiki/changelogs/2026-01-02-default-filter-and-repository-mixins.md +418 -0
  28. package/wiki/changelogs/index.md +8 -1
  29. package/wiki/changelogs/planned-schema-migrator.md +2 -10
  30. package/wiki/{get-started/core-concepts → guides/core-concepts/application}/bootstrapping.md +18 -5
  31. package/wiki/{get-started/core-concepts/application.md → guides/core-concepts/application/index.md} +47 -104
  32. package/wiki/guides/core-concepts/components-guide.md +509 -0
  33. package/wiki/guides/core-concepts/components.md +122 -0
  34. package/wiki/{get-started → guides}/core-concepts/controllers.md +30 -13
  35. package/wiki/{get-started → guides}/core-concepts/dependency-injection.md +97 -0
  36. package/wiki/guides/core-concepts/persistent/datasources.md +179 -0
  37. package/wiki/guides/core-concepts/persistent/index.md +119 -0
  38. package/wiki/guides/core-concepts/persistent/models.md +241 -0
  39. package/wiki/guides/core-concepts/persistent/repositories.md +219 -0
  40. package/wiki/guides/core-concepts/persistent/transactions.md +170 -0
  41. package/wiki/{get-started → guides}/core-concepts/services.md +26 -3
  42. package/wiki/{get-started → guides/get-started}/5-minute-quickstart.md +59 -14
  43. package/wiki/guides/get-started/philosophy.md +682 -0
  44. package/wiki/guides/get-started/setup.md +157 -0
  45. package/wiki/guides/index.md +89 -0
  46. package/wiki/guides/reference/glossary.md +243 -0
  47. package/wiki/{get-started → guides/reference}/mcp-docs-server.md +0 -10
  48. package/wiki/{get-started → guides/tutorials}/building-a-crud-api.md +134 -132
  49. package/wiki/{get-started/quickstart.md → guides/tutorials/complete-installation.md} +107 -71
  50. package/wiki/guides/tutorials/ecommerce-api.md +1399 -0
  51. package/wiki/guides/tutorials/realtime-chat.md +1261 -0
  52. package/wiki/guides/tutorials/testing.md +723 -0
  53. package/wiki/index.md +176 -37
  54. package/wiki/references/base/application.md +27 -0
  55. package/wiki/references/base/bootstrapping.md +30 -26
  56. package/wiki/references/base/components.md +532 -31
  57. package/wiki/references/base/controllers.md +136 -38
  58. package/wiki/references/base/datasources.md +108 -5
  59. package/wiki/references/base/dependency-injection.md +39 -3
  60. package/wiki/references/base/filter-system/application-usage.md +224 -0
  61. package/wiki/references/base/filter-system/array-operators.md +132 -0
  62. package/wiki/references/base/filter-system/comparison-operators.md +109 -0
  63. package/wiki/references/base/filter-system/default-filter.md +428 -0
  64. package/wiki/references/base/filter-system/fields-order-pagination.md +155 -0
  65. package/wiki/references/base/filter-system/index.md +127 -0
  66. package/wiki/references/base/filter-system/json-filtering.md +197 -0
  67. package/wiki/references/base/filter-system/list-operators.md +71 -0
  68. package/wiki/references/base/filter-system/logical-operators.md +156 -0
  69. package/wiki/references/base/filter-system/null-operators.md +58 -0
  70. package/wiki/references/base/filter-system/pattern-matching.md +108 -0
  71. package/wiki/references/base/filter-system/quick-reference.md +431 -0
  72. package/wiki/references/base/filter-system/range-operators.md +63 -0
  73. package/wiki/references/base/filter-system/tips.md +190 -0
  74. package/wiki/references/base/filter-system/use-cases.md +452 -0
  75. package/wiki/references/base/index.md +90 -0
  76. package/wiki/references/base/middlewares.md +602 -0
  77. package/wiki/references/base/models.md +215 -23
  78. package/wiki/references/base/providers.md +732 -0
  79. package/wiki/references/base/repositories/advanced.md +555 -0
  80. package/wiki/references/base/repositories/index.md +228 -0
  81. package/wiki/references/base/repositories/mixins.md +331 -0
  82. package/wiki/references/base/repositories/relations.md +486 -0
  83. package/wiki/references/base/repositories.md +40 -549
  84. package/wiki/references/base/services.md +28 -4
  85. package/wiki/references/components/authentication.md +22 -2
  86. package/wiki/references/components/health-check.md +12 -0
  87. package/wiki/references/components/index.md +23 -0
  88. package/wiki/references/components/mail.md +687 -0
  89. package/wiki/references/components/request-tracker.md +16 -0
  90. package/wiki/references/components/socket-io.md +18 -0
  91. package/wiki/references/components/static-asset.md +14 -26
  92. package/wiki/references/components/swagger.md +17 -0
  93. package/wiki/references/configuration/environment-variables.md +427 -0
  94. package/wiki/references/configuration/index.md +73 -0
  95. package/wiki/references/helpers/cron.md +14 -0
  96. package/wiki/references/helpers/crypto.md +15 -0
  97. package/wiki/references/helpers/env.md +16 -0
  98. package/wiki/references/helpers/error.md +17 -0
  99. package/wiki/references/helpers/index.md +15 -0
  100. package/wiki/references/helpers/inversion.md +24 -4
  101. package/wiki/references/helpers/logger.md +19 -0
  102. package/wiki/references/helpers/network.md +11 -0
  103. package/wiki/references/helpers/queue.md +19 -0
  104. package/wiki/references/helpers/redis.md +21 -0
  105. package/wiki/references/helpers/socket-io.md +24 -5
  106. package/wiki/references/helpers/storage.md +18 -10
  107. package/wiki/references/helpers/testing.md +18 -0
  108. package/wiki/references/helpers/types.md +167 -0
  109. package/wiki/references/helpers/uid.md +167 -0
  110. package/wiki/references/helpers/worker-thread.md +16 -0
  111. package/wiki/references/index.md +177 -0
  112. package/wiki/references/quick-reference.md +634 -0
  113. package/wiki/references/src-details/boot.md +3 -3
  114. package/wiki/references/src-details/dev-configs.md +0 -4
  115. package/wiki/references/src-details/docs.md +2 -2
  116. package/wiki/references/src-details/index.md +86 -0
  117. package/wiki/references/src-details/inversion.md +1 -6
  118. package/wiki/references/src-details/mcp-server.md +3 -15
  119. package/wiki/references/utilities/index.md +86 -10
  120. package/wiki/references/utilities/jsx.md +577 -0
  121. package/wiki/references/utilities/request.md +0 -2
  122. package/wiki/references/utilities/statuses.md +740 -0
  123. package/wiki/changelogs/planned-transaction-support.md +0 -216
  124. package/wiki/get-started/best-practices/api-usage-examples.md +0 -266
  125. package/wiki/get-started/best-practices/architectural-patterns.md +0 -170
  126. package/wiki/get-started/best-practices/data-modeling.md +0 -177
  127. package/wiki/get-started/best-practices/deployment-strategies.md +0 -121
  128. package/wiki/get-started/best-practices/performance-optimization.md +0 -88
  129. package/wiki/get-started/best-practices/security-guidelines.md +0 -99
  130. package/wiki/get-started/core-concepts/components.md +0 -98
  131. package/wiki/get-started/core-concepts/persistent.md +0 -543
  132. package/wiki/get-started/index.md +0 -65
  133. package/wiki/get-started/philosophy.md +0 -296
  134. package/wiki/get-started/prerequisites.md +0 -113
@@ -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
+ ```
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: Pattern Matching Operators
3
+ description: Operators for string pattern matching and regular expressions
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Pattern Matching Operators
8
+
9
+ Operators for string pattern matching and regular expressions.
10
+
11
+
12
+ ## like - Pattern Matching (Case-Sensitive)
13
+
14
+ Matches strings using SQL LIKE patterns.
15
+
16
+ ```typescript
17
+ // Starts with
18
+ { where: { email: { like: '%@gmail.com' } } }
19
+ // SQL: WHERE "email" LIKE '%@gmail.com'
20
+
21
+ // Contains
22
+ { where: { name: { like: '%john%' } } }
23
+ // SQL: WHERE "name" LIKE '%john%'
24
+
25
+ // Ends with
26
+ { where: { filename: { like: '%.pdf' } } }
27
+ // SQL: WHERE "filename" LIKE '%.pdf'
28
+
29
+ // Single character wildcard
30
+ { where: { code: { like: 'A_B' } } } // Matches 'A1B', 'AXB', etc.
31
+ // SQL: WHERE "code" LIKE 'A_B'
32
+ ```
33
+
34
+ **Pattern Characters:**
35
+ - `%` - Matches any sequence of characters (including empty)
36
+ - `_` - Matches exactly one character
37
+
38
+
39
+ ## nlike - Not Like
40
+
41
+ ```typescript
42
+ { where: { email: { nlike: '%@test.com' } } }
43
+ // SQL: WHERE "email" NOT LIKE '%@test.com'
44
+ ```
45
+
46
+
47
+ ## ilike - Case-Insensitive Pattern Matching
48
+
49
+ PostgreSQL-specific case-insensitive LIKE.
50
+
51
+ ```typescript
52
+ { where: { name: { ilike: '%john%' } } }
53
+ // SQL: WHERE "name" ILIKE '%john%'
54
+ // Matches: 'John', 'JOHN', 'john', 'JoHn'
55
+
56
+ { where: { email: { ilike: '%@GMAIL.COM' } } }
57
+ // Matches: 'user@gmail.com', 'USER@Gmail.Com'
58
+ ```
59
+
60
+
61
+ ## nilike - Not ILike
62
+
63
+ ```typescript
64
+ { where: { email: { nilike: '%@example%' } } }
65
+ // SQL: WHERE NOT ("email" ILIKE '%@example%')
66
+ ```
67
+
68
+
69
+ ## regexp - Regular Expression (Case-Sensitive)
70
+
71
+ PostgreSQL POSIX regex matching.
72
+
73
+ ```typescript
74
+ // Starts with letter
75
+ { where: { code: { regexp: '^[A-Z]' } } }
76
+ // SQL: WHERE "code" ~ '^[A-Z]'
77
+
78
+ // Email pattern
79
+ { where: { email: { regexp: '^[a-z]+@[a-z]+\\.[a-z]+$' } } }
80
+ // SQL: WHERE "email" ~ '^[a-z]+@[a-z]+\.[a-z]+$'
81
+
82
+ // Phone number pattern
83
+ { where: { phone: { regexp: '^\\+?[0-9]{10,15}$' } } }
84
+ ```
85
+
86
+ > [!NOTE]
87
+ > Escape backslashes in TypeScript strings: `\\d` for regex `\d`.
88
+
89
+
90
+ ## iregexp - Case-Insensitive Regular Expression
91
+
92
+ ```typescript
93
+ { where: { name: { iregexp: '^john' } } }
94
+ // SQL: WHERE "name" ~* '^john'
95
+ // Matches: 'John Doe', 'JOHN SMITH', 'john'
96
+ ```
97
+
98
+
99
+ ## Summary
100
+
101
+ | Operator | SQL | Case | Description |
102
+ |----------|-----|------|-------------|
103
+ | `like` | `LIKE` | Sensitive | Pattern with wildcards |
104
+ | `nlike` | `NOT LIKE` | Sensitive | Negative pattern |
105
+ | `ilike` | `ILIKE` | Insensitive | PostgreSQL only |
106
+ | `nilike` | `NOT ILIKE` | Insensitive | PostgreSQL only |
107
+ | `regexp` | `~` | Sensitive | POSIX regex match |
108
+ | `iregexp` | `~*` | Insensitive | POSIX regex match |