masquerade-orm 0.8.1 → 0.8.3

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.
package/docs/find.md CHANGED
@@ -1,265 +1,275 @@
1
- # Find
2
-
3
- ```js
4
- await ExampleClass.find(findObj)
5
- ```
6
-
7
- The `find` method is the most complex part of the ORM. **Fortunately, it is fully covered by IntelliSense, and you are strongly encouraged to rely on it.**
8
-
9
- It accepts a single argument, findObj, which contains three optional fields.
10
- Because all fields are optional, findObj itself may be an empty object (although this is rarely useful, as it would return all instances of ExampleClass).
11
-
12
- The three optional fields are:
13
-
14
- - relations
15
- - where
16
- - relationalWhere
17
-
18
-
19
-
20
- ## The `relations` Field:
21
-
22
- The `relations` field determines which relations are eagerly loaded from the database.
23
-
24
- A crucial detail to understand is that relations are never filtered.
25
- They are either loaded or not. The ORM never displays partial relational data.
26
-
27
- ```js
28
- // assume that relationalProp is a property of type SomeClass or SomeClass[]
29
- await ExampleClass.find(
30
- {
31
- relations: {relationalProp: true},
32
- where: {
33
- relationalProp: {
34
- id: 57
35
- }
36
- }
37
- }
38
- )
39
- ```
40
-
41
- The example above translates to:
42
- **“Fetch all instances of ExampleClass whose relationalProp contains a SomeClass instance with id = 57.”**
43
-
44
- In other words, the condition matches when either of the following is true:
45
-
46
- ```js
47
- // 1-to-1 relationship case
48
- exampleClassInstance.relationalProp === someClassId57
49
- ```
50
- or
51
- ```js
52
- // 1-to-many relationship case
53
- exampleClassInstance.relationalProp.includes(someClassId57)
54
- ```
55
-
56
- ### Lazy Loading
57
-
58
- ```js
59
- // Assume the 'Chat' class has relational properties 'users' and 'messages'.
60
- // Initially, we load only the 'messages' relation for a specific chat.
61
-
62
- const resultArray = await Chat.find({
63
- relations: { messages: true }, // eager load the 'messages' relation
64
- where: { id: 123 } // fetch the chat with ID 123
65
- })
66
-
67
- const someChat = resultArray[0]
68
-
69
- // At this point, 'someChat.users' is not loaded.
70
- // To load the 'users' relation, we need to await it.
71
- await someChat.users
72
- ```
73
-
74
-
75
- ## The `where` Field:
76
-
77
- The `where` field is for filtering the root instances, in the following case, Chat instances.
78
- ```js
79
- await Chat.find({
80
- where: {
81
- messages: {
82
- sender: {
83
- id: 12
84
- }
85
- }
86
- }
87
- })
88
- ```
89
- Translation: **“Find all chats that contain a message from a user with the id 12, without loading messages.“**
90
-
91
- - **Note:** The scope of the `where` condtions is agnostic to the scope of the `relations` (eager-loading).
92
- It is completely safe to filter based on specific relations without having said relations passed into the `relations` field.
93
-
94
- ### Introduction to the `sql`, `OR` and `AND` functions
95
-
96
- ```js
97
- import { sql, AND, OR } from "masquerade"
98
-
99
- await Angel.find({
100
- where: {
101
- // name is either "Micheal" OR "Gabriel"
102
- name: OR('Micheal', 'Gabriel'),
103
-
104
- // demonsSentToAbyss is greater than 12,000 AND less than 57,000
105
- demonsSentToAbyss: AND(sql`> 12000`, sql`< 57000`)
106
- }
107
- })
108
- ```
109
-
110
- ### Using the `sql` function with explicit column identifiers
111
- In the previous example, the `sql` function implicitly inserted a column identifier (`#`) on the left side of the SQL statement.
112
- ```js
113
- // these two statements are equivalent
114
- sql`> 12000`
115
- sql`# > 12000`
116
- ```
117
-
118
- In next example, `#` identifiers must be written explicitly because the SQL string uses `AND` conditional operators directly, rather than using the `AND()` helper function.
119
-
120
- ```js
121
- import { sql } from "masquerade"
122
-
123
- const twoYearsAgo = new Date().setFullYear(new Date().getFullYear() - 2)
124
- const oneYearAgo = new Date().setFullYear(new Date().getFullYear() - 1)
125
-
126
- await User.find({
127
- where: {
128
- // donations between 1,200 and 5,700 cents (exclusive)
129
- donations: sql`1200 < # AND # < 5700`,
130
-
131
- // account's age is between one and two years old.
132
- createdAt: sql`${twoYearsAgo} <= # AND # <= ${oneYearAgo}`
133
- }
134
- })
135
- // The ANDs are written directly inside the 'sql' string instead of
136
- // having to rely on helper functions to achieve the same result.
137
- // The 'sql' function gives you the ability to write powerful
138
- // 'where' conditions in an easy-to-read and easy-to-write manner.
139
- ```
140
-
141
- ### Using the `sql` function to create a `LIKE` `WHERE` condition
142
- ```js
143
- import { sql } from "masquerade"
144
-
145
- await User.find({
146
- where: {
147
- // registered using a Gmail email
148
- email: sql`LIKE '%@gmail.com%'`
149
- }
150
- })
151
- ```
152
-
153
- ### Using the `sql` function to create a `WHERE` condition for matching JSON values
154
-
155
- ```ts
156
- import { Entity } from "masquerade"
157
-
158
- type OrderOverview = {
159
- status: "pending" | "completed" | "cancelled"
160
- total: number
161
- currency: string
162
- }
163
-
164
- class Order extends Entity {
165
- // other properties...
166
- metadata: UserMetadata
167
- // other properties + constructor...
168
- }
169
-
170
- const completedOrders = await Order.find({
171
- where:
172
- { overview: sql`json_extract(#, '$.status') = 'completed'` }
173
- })
174
- ```
175
-
176
- - **Note:** for SQL-client specific guide for writing `WHERE` conditions involving JSON and array data, go to the bottom of this page or click **[here](https://github.com/MasqueradeORM/MasqueradeORM/blob/master/docs/find.md#array-and-json-where-conditions-guide)**.
177
-
178
-
179
- ## The `relationalWhere` Field:
180
-
181
- ```js
182
- import { sql } from "masquerade"
183
-
184
- // Finds users that have at least one chat that contains at least one message whose sender's username is 'Glory2Christ'.
185
- await User.find({
186
- relationalWhere: (user) => sql`${user.chats.messages.sender.username} = 'Glory2Christ'`
187
- })
188
- ```
189
-
190
- ```js
191
- import { sql } from "masquerade"
192
-
193
- // Identical to the previous example, but here the relational where is called from a different scope.
194
- // note: the field has an underscore, to prevent any (rather impossible) name collisions.
195
-
196
- await User.find({
197
- where: {
198
- chats: {
199
- relationalWhere_: (chat) => sql`${chat.messages.sender.username} = 'Glory2Christ'`,
200
- // can be combined with regular 'where' conditions - below is valid code
201
- // chatName: 'The History of Orthodoxy'
202
- }
203
- }
204
- })
205
- ```
206
-
207
- ### Array and JSON `WHERE` Conditions Guide
208
-
209
- The model we will use for the examples:
210
-
211
- ```ts
212
- import { Entity } from "masquerade"
213
-
214
- type UserMetadata = {
215
- roles: string[] // e.g., ["admin", "moderator"]
216
- lastLogin?: string // optional, ISO date string
217
- preferences?: {
218
- theme?: "light" | "dark"
219
- notifications?: boolean
220
- }
221
- }
222
-
223
- class User extends Entity {
224
- // other properties...
225
- metadata: UserMetadata
226
- sessions: string[]
227
- // other properties + constructor...
228
- }
229
- ```
230
-
231
- Assuming we are writing the condition for the property `metadata` or `sessions` like so:
232
- ```ts
233
- import { sql } from "masquerade"
234
- // 'metadata' find
235
- const users = await User.find({where: {metadata: sql`_OPERATION_STRING_`}})
236
-
237
- // 'sessions' find
238
- const users2 = await User.find({where: {sessions: sql`_OPERATION_STRING_`}})
239
-
240
- // **if not specified, the default is the 'metadata' find
241
-
242
- // replace _OPERATION_STRING_ with the appropriate
243
- // operation string from the table below
244
- ```
245
-
246
- <strong>**Operation String Table**
247
-
248
- | Operation | SQLite | PostgreSQL |
249
- |-------------|---------------|------------|
250
- Array length <br>(example uses len = 2) | **'metadata' find** <br> `json_array_length(json_extract(#, '$.roles')) > 2` <br> **'sessions' find** <br> `json_array_length(json_extract(#)) > 2` | **'metadata' find** <br> `jsonb_array_length(#->'roles') > 2` <br> **'sessions' find** <br> `jsonb_array_length(#) > 2`|
251
- | Access index `i` of array | **'metadata' find** <br>`json_extract(#, '$.roles[i]') = 'admin'`<br> **'sessions' find** <br>`json_extract(#, '$[i]') = 'SOME_SESSION_ID'` | **'metadata' find** <br>`#->'roles'->>i = 'admin''`<br> **'sessions' find** <br>`#->>i = 'admin'` |
252
- | Check if array contains a value | `json_extract(#, '$.roles') LIKE '%"admin"%'` | `#->'roles' @> '["admin"]'::jsonb` |
253
- Check nested field | `json_extract(#, '$.preferences.theme') = 'dark'` | `#->'preferences'->>'theme' = 'dark'` |
254
- </strong>
255
-
256
-
257
- <br>
258
- <div align="center">
259
- <strong>
260
- © 2026
261
- <a href="https://github.com/MasqueradeORM">MasqueradeORM </a>
262
- -
263
- Released under the MIT License
264
- </strong>
1
+ # Find
2
+
3
+ ```js
4
+ await ExampleClass.find(findObj)
5
+ ```
6
+
7
+ The `find` method is the most complex part of the ORM. **Fortunately, it is fully covered by IntelliSense, and you are strongly encouraged to rely on it.**
8
+
9
+ It accepts a single argument, findObj, which contains three optional fields.
10
+ Because all fields are optional, findObj itself may be an empty object (although this is rarely useful, as it would return all instances of ExampleClass).
11
+
12
+ The three optional fields are:
13
+
14
+ - relations
15
+ - where
16
+ - templateWhere
17
+
18
+
19
+
20
+ ## The `relations` Field:
21
+
22
+ The `relations` field determines which relations are eagerly loaded from the database.
23
+
24
+ A crucial detail to understand is that relations are never filtered.
25
+ They are either loaded or not. The ORM never displays partial relational data.
26
+
27
+ ```js
28
+ // assume that relationalProp is a property of type SomeClass or SomeClass[]
29
+ await ExampleClass.find(
30
+ {
31
+ relations: {relationalProp: true},
32
+ where: {
33
+ relationalProp: {
34
+ id: 57
35
+ }
36
+ }
37
+ }
38
+ )
39
+ ```
40
+
41
+ The example above translates to:
42
+ **“Fetch all instances of ExampleClass whose relationalProp contains a SomeClass instance with id = 57.”**
43
+
44
+ In other words, the condition matches when either of the following is true:
45
+
46
+ ```js
47
+ // 1-to-1 relationship case
48
+ exampleClassInstance.relationalProp === someClassId57
49
+ ```
50
+ or
51
+ ```js
52
+ // 1-to-many relationship case
53
+ exampleClassInstance.relationalProp.includes(someClassId57)
54
+ ```
55
+
56
+ ### Lazy Loading
57
+
58
+ ```js
59
+ // Assume the 'Chat' class has relational properties 'users' and 'messages'.
60
+ // Initially, we load only the 'messages' relation for a specific chat.
61
+
62
+ const resultArray = await Chat.find({
63
+ relations: { messages: true }, // eager load the 'messages' relation
64
+ where: { id: 123 } // fetch the chat with ID 123
65
+ })
66
+
67
+ const someChat = resultArray[0]
68
+
69
+ // At this point, 'someChat.users' is not loaded.
70
+ // To load the 'users' relation, we need to await it.
71
+ await someChat.users
72
+ ```
73
+
74
+
75
+ ## The `where` Field:
76
+
77
+ The `where` field is for filtering the root instances, in the following case, Chat instances.
78
+ ```js
79
+ await Chat.find({
80
+ where: {
81
+ messages: {
82
+ sender: {
83
+ id: 12
84
+ }
85
+ }
86
+ }
87
+ })
88
+ ```
89
+ Translation: **“Find all chats that contain a message from a user with the id 12, without loading messages.“**
90
+
91
+ - **Note:** The scope of the `where` condtions is agnostic to the scope of the `relations` (eager-loading).
92
+ It is completely safe to filter based on specific relations without having said relations passed into the `relations` field.
93
+
94
+ ### Introduction to the `sql`, `OR` and `AND` functions
95
+
96
+ ```js
97
+ import { sql, AND, OR } from "masquerade-orm"
98
+
99
+ await Angel.find({
100
+ where: {
101
+ // name is either "Micheal" OR "Gabriel"
102
+ name: OR('Micheal', 'Gabriel'),
103
+
104
+ // demonsSentToAbyss is greater than 12,000 AND less than 57,000
105
+ demonsSentToAbyss: AND(sql`> 12000`, sql`< 57000`)
106
+ }
107
+ })
108
+ ```
109
+
110
+ ### Using the `sql` function with explicit column identifiers
111
+ In the previous example, the `sql` function implicitly inserted a column identifier (`#`) on the left side of the SQL statement.
112
+ ```js
113
+ // these two statements are equivalent
114
+ sql`> 12000`
115
+ sql`# > 12000`
116
+ ```
117
+
118
+ In next example, `#` identifiers must be written explicitly because the SQL string uses `AND` conditional operators directly, rather than using the `AND()` helper function.
119
+
120
+ ```js
121
+ import { sql } from "masquerade-orm"
122
+
123
+ const twoYearsAgo = new Date().setFullYear(new Date().getFullYear() - 2)
124
+ const oneYearAgo = new Date().setFullYear(new Date().getFullYear() - 1)
125
+
126
+ await User.find({
127
+ where: {
128
+ // donations between 1,200 and 5,700 cents (exclusive)
129
+ donations: sql`1200 < # AND # < 5700`,
130
+
131
+ // account's age is between one and two years old.
132
+ createdAt: sql`${twoYearsAgo} <= # AND # <= ${oneYearAgo}`
133
+ }
134
+ })
135
+ // The ANDs are written directly inside the 'sql' string instead of
136
+ // having to rely on helper functions to achieve the same result.
137
+ // The 'sql' function gives you the ability to write powerful
138
+ // 'where' conditions in an easy-to-read and easy-to-write manner.
139
+ ```
140
+
141
+ <!-- **Equivalent Alternative Syntax:**
142
+ ```js
143
+ await User.find({
144
+ where: {
145
+ donations: (donations) => sql`1200 < ${donations} AND ${donations} < 5700`,
146
+ createdAt: (createdAt) => sql`${twoYearsAgo} <= ${createdAt} AND ${createdAt} <= ${oneYearAgo}`
147
+ }
148
+ })
149
+ ``` -->
150
+
151
+ ### Using the `sql` function to create a `LIKE` `WHERE` condition
152
+ ```js
153
+ import { sql } from "masquerade-orm"
154
+
155
+ await User.find({
156
+ where: {
157
+ // registered using a Gmail email
158
+ email: sql`LIKE '%@gmail.com%'`
159
+ }
160
+ })
161
+ ```
162
+
163
+ ### Using the `sql` function to create a `WHERE` condition for matching JSON values
164
+
165
+ ```ts
166
+ import { Entity } from "masquerade-orm"
167
+
168
+ type OrderOverview = {
169
+ status: "pending" | "completed" | "cancelled"
170
+ total: number
171
+ currency: string
172
+ }
173
+
174
+ class Order extends Entity {
175
+ // other properties...
176
+ metadata: UserMetadata
177
+ // other properties + constructor...
178
+ }
179
+
180
+ const completedOrders = await Order.find({
181
+ where:
182
+ { overview: sql`json_extract(#, '$.status') = 'completed'` }
183
+ })
184
+ ```
185
+
186
+ - **Note:** for SQL-client specific guide for writing `WHERE` conditions involving JSON and array data, go to the bottom of this page or click **[here](https://github.com/MasqueradeORM/MasqueradeORM/blob/master/docs/find.md#array-and-json-where-conditions-guide)**.
187
+
188
+
189
+ ## The `templateWhere` Field:
190
+
191
+ ```js
192
+ import { sql } from "masquerade-orm"
193
+
194
+ // Finds users that have at least one chat that contains at least one message whose sender's username is 'Glory2Christ'.
195
+ await User.find({
196
+ templateWhere: (user) => sql`${user.chats.messages.sender.username} = 'Glory2Christ'`
197
+ })
198
+ ```
199
+
200
+ ```js
201
+ import { sql } from "masquerade-orm"
202
+
203
+ // Identical to the previous example, but here the 'templateWhere' is called from a different scope.
204
+ // note: the field has an underscore, to prevent any (rather impossible) name collisions.
205
+
206
+ await User.find({
207
+ where: {
208
+ chats: {
209
+ templateWhere_: (chat) => sql`${chat.messages.sender.username} = 'Glory2Christ'`,
210
+ // can be combined with regular 'where' conditions - below is valid code
211
+ // chatName: 'The History of Orthodoxy'
212
+ }
213
+ }
214
+ })
215
+ ```
216
+
217
+ ### Array and JSON `WHERE` Conditions Guide
218
+
219
+ The model we will use for the examples:
220
+
221
+ ```ts
222
+ import { Entity } from "masquerade-orm"
223
+
224
+ type UserMetadata = {
225
+ roles: string[] // e.g., ["admin", "moderator"]
226
+ lastLogin?: string // optional, ISO date string
227
+ preferences?: {
228
+ theme?: "light" | "dark"
229
+ notifications?: boolean
230
+ }
231
+ }
232
+
233
+ class User extends Entity {
234
+ // other properties...
235
+ metadata: UserMetadata
236
+ sessions: string[]
237
+ // other properties + constructor...
238
+ }
239
+ ```
240
+
241
+ Assuming we are writing the condition for the property `metadata` or `sessions` like so:
242
+ ```ts
243
+ import { sql } from "masquerade-orm"
244
+ // 'metadata' find
245
+ const users = await User.find({where: {metadata: sql`_OPERATION_STRING_`}})
246
+
247
+ // 'sessions' find
248
+ const users2 = await User.find({where: {sessions: sql`_OPERATION_STRING_`}})
249
+
250
+ // **if not specified, the default is the 'metadata' find
251
+
252
+ // replace _OPERATION_STRING_ with the appropriate
253
+ // operation string from the table below
254
+ ```
255
+
256
+ <strong>**Operation String Table**
257
+
258
+ | Operation | SQLite | PostgreSQL |
259
+ |-------------|---------------|------------|
260
+ Array length <br>(example uses len = 2) | **'metadata' find** <br> `json_array_length(json_extract(#, '$.roles')) > 2` <br> **'sessions' find** <br> `json_array_length(json_extract(#)) > 2` | **'metadata' find** <br> `jsonb_array_length(#->'roles') > 2` <br> **'sessions' find** <br> `jsonb_array_length(#) > 2`|
261
+ | Access index `i` of array | **'metadata' find** <br>`json_extract(#, '$.roles[i]') = 'admin'`<br> **'sessions' find** <br>`json_extract(#, '$[i]') = 'SOME_SESSION_ID'` | **'metadata' find** <br>`#->'roles'->>i = 'admin''`<br> **'sessions' find** <br>`#->>i = 'admin'` |
262
+ | Check if array contains a value | `json_extract(#, '$.roles') LIKE '%"admin"%'` | `#->'roles' @> '["admin"]'::jsonb` |
263
+ Check nested field | `json_extract(#, '$.preferences.theme') = 'dark'` | `#->'preferences'->>'theme' = 'dark'` |
264
+ </strong>
265
+
266
+
267
+ <br>
268
+ <div align="center">
269
+ <strong>
270
+ © 2026
271
+ <a href="https://github.com/MasqueradeORM">MasqueradeORM </a>
272
+ -
273
+ Released under the MIT License
274
+ </strong>
265
275
  </div>
@@ -3,7 +3,7 @@
3
3
 
4
4
  ## 1) Declaring the Class:
5
5
  ```js
6
- import { Entity } from 'masquerade'
6
+ import { Entity } from 'masquerade-orm'
7
7
 
8
8
  class YourClass extends Entity {
9
9
  // class properties
@@ -18,7 +18,7 @@ The class **MUST** extend `Entity` or a descendent of `Entity`.
18
18
 
19
19
  ## 3) Making a Table Column Unique:
20
20
  ```js
21
- /**@typedef {import('masquerade').integer} integer */
21
+ /**@typedef {import('masquerade-orm').integer} integer */
22
22
  /**@type {string | Unique}*/ propertyName
23
23
  ```
24
24
 
@@ -26,7 +26,8 @@ The class **MUST** extend `Entity` or a descendent of `Entity`.
26
26
  Assuming we have the following classes extending Entity: `User`, `Chat` and `Message`.
27
27
 
28
28
  ```js
29
- import { Entity } from 'masquerade'
29
+ import { Entity } from 'masquerade-orm'
30
+ import { User, Chat, Message } from './your/entities'
30
31
 
31
32
  class Example extends Entity {
32
33
  // one-to-one relationship with a User instance
@@ -47,6 +48,8 @@ class Example extends Entity {
47
48
  Each relational property will create a junction table named `className___propName_jt`.
48
49
 
49
50
 
51
+ ** **For more in-depth documentation regarding class definitions **[click here](https://github.com/MasqueradeORM/MasqueradeORM/blob/master/docs/in-depth-class-definitions.md)**.** **
52
+
50
53
  # Booting Up the ORM
51
54
 
52
55
  ## 1) Database Connection Driver:
@@ -76,7 +79,7 @@ const yourDbConnection = new Pool({
76
79
 
77
80
  ## 2) Configuration Object:
78
81
  ```js
79
- /**@typedef {import('masquerade').OrmConfigObj} OrmConfigObj*/
82
+ /**@typedef {import('masquerade-orm').OrmConfigObj} OrmConfigObj*/
80
83
 
81
84
  /** @type {OrmConfigObj} */ const ormConfig = {
82
85
  dbConnection: yourDbConnection,
@@ -101,6 +104,12 @@ await ORM.javascriptBoot(ormConfig, classes, moreClasses, someClass)
101
104
 
102
105
  <h1 align="center">All done!</h1>
103
106
 
107
+ <div align="center">
108
+
109
+ ### **It is HIGHLY recommended to read [JSDoc – UX Tips](https://github.com/MasqueradeORM/MasqueradeORM/blob/master/docs/jsdoc-ux-tips.md)**
110
+
111
+ </div>
112
+
104
113
  <br>
105
114
  <div align="center">
106
115
  <strong>
@@ -3,7 +3,7 @@
3
3
 
4
4
  ## 1) Declaring the Class:
5
5
  ```js
6
- import { Entity } from 'masquerade'
6
+ import { Entity } from 'masquerade-orm'
7
7
 
8
8
  class YourClass extends Entity {
9
9
  // class properties
@@ -20,7 +20,7 @@ propertyName?: string
20
20
  ## 3) Making a Table Column Unique:
21
21
 
22
22
  ```ts
23
- import { Unique } from 'masquerade'
23
+ import { Unique } from 'masquerade-orm'
24
24
  propertyName: string | Unique
25
25
  ```
26
26
 
@@ -28,7 +28,8 @@ propertyName: string | Unique
28
28
  Assuming we have the following classes extending Entity: `User`, `Chat` and `Message`.
29
29
 
30
30
  ```ts
31
- import { Entity } from 'masquerade'
31
+ import { Entity } from 'masquerade-orm'
32
+ import { User, Chat, Message } from './your/entities'
32
33
 
33
34
  class Example extends Entity {
34
35
  // one-to-one relationship with a User instance
@@ -48,6 +49,7 @@ class Example extends Entity {
48
49
  ```
49
50
  Each relational property will create a junction table named `className___propName_jt`.
50
51
 
52
+ ** **For more in-depth documentation regarding class definitions **[click here](https://github.com/MasqueradeORM/MasqueradeORM/blob/master/docs/in-depth-class-definitions.md)**.** **
51
53
 
52
54
  # Booting Up the ORM
53
55
 
@@ -78,7 +80,7 @@ const yourDbConnection = new Pool({
78
80
 
79
81
  ## 2) Configuration Object:
80
82
  ```ts
81
- import type { OrmConfigObj } from "masquerade"
83
+ import type { OrmConfigObj } from "masquerade-orm"
82
84
 
83
85
  const ormConfig: OrmConfigObj = {
84
86
  dbConnection: yourDbConnection,