modelence 0.9.0 → 0.9.2

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.
@@ -122,6 +122,38 @@ type StrictRootFilterOperators<TSchema> = {
122
122
  $expr?: any;
123
123
  $jsonSchema?: any;
124
124
  };
125
+ /**
126
+ * Helper type to extract array element type
127
+ * @internal
128
+ */
129
+ type ArrayElement<T> = T extends (infer E)[] ? E : never;
130
+ /**
131
+ * Helper type for $in/$nin that accepts any array/tuple where elements are assignable to T
132
+ * This solves the issue where TypeScript infers ['a', 'b'] as a tuple instead of ('a' | 'b')[]
133
+ * and where Array<Union> gets distributed into Union1[] | Union2[] | ...
134
+ * We wrap the Exclude in a tuple check to prevent distribution
135
+ * @internal
136
+ */
137
+ type NonUndefined<T> = T extends undefined ? never : T;
138
+ type ArrayLikeOfUnion<T> = [NonUndefined<T>] extends [never] ? never : ReadonlyArray<NonUndefined<T>> | Array<NonUndefined<T>>;
139
+ /**
140
+ * Enhanced FilterOperators that fixes $in and $nin to properly accept arrays of union types
141
+ * MongoDB's native FilterOperators has issues with union types in $in/$nin arrays
142
+ * because TypeScript distributes Array<Union> into Array1 | Array2 | ...
143
+ * @internal
144
+ */
145
+ type EnhancedFilterOperators<T> = Omit<FilterOperators<T>, '$in' | '$nin'> & {
146
+ $in?: ArrayLikeOfUnion<T>;
147
+ $nin?: ArrayLikeOfUnion<T>;
148
+ };
149
+ /**
150
+ * Custom filter value type that handles array fields specially:
151
+ * - For array fields: allows element type, full array type, or FilterOperators
152
+ * - For non-array fields: allows exact type or FilterOperators
153
+ * We use [T] to prevent distribution when T is a union type
154
+ * @internal
155
+ */
156
+ type FilterValue<T> = [T] extends [unknown[]] ? ArrayElement<T> | T | EnhancedFilterOperators<T> : [T] extends [never] ? never : T | EnhancedFilterOperators<[T] extends [never] ? never : T>;
125
157
  /**
126
158
  * Type-safe MongoDB filter that ensures only schema fields can be queried
127
159
  * while supporting all MongoDB query operators and dot notation for nested fields.
@@ -129,6 +161,7 @@ type StrictRootFilterOperators<TSchema> = {
129
161
  * This type combines:
130
162
  * - MongoDB's native `FilterOperators<T>` for field-level operators (comprehensive operator support)
131
163
  * - Custom `StrictRootFilterOperators<T>` for top-level operators without index signature
164
+ * - Custom array field handling: allows passing single element when field is an array
132
165
  * - Custom restriction: only strings containing dots are allowed for nested field queries
133
166
  *
134
167
  * @example
@@ -138,6 +171,7 @@ type StrictRootFilterOperators<TSchema> = {
138
171
  * name: schema.string(),
139
172
  * age: schema.number(),
140
173
  * tags: schema.array(schema.string()),
174
+ * collections: schema.array(schema.string()),
141
175
  * address: schema.object({
142
176
  * street: schema.string(),
143
177
  * city: schema.string(),
@@ -154,6 +188,9 @@ type StrictRootFilterOperators<TSchema> = {
154
188
  * await dbUsers.findOne({ tags: { $in: ['typescript', 'mongodb'] } });
155
189
  * await dbUsers.findOne({ $or: [{ name: 'John' }, { name: 'Jane' }] });
156
190
  *
191
+ * // ✅ Valid - array field with single element (checks if array contains the element)
192
+ * await dbUsers.findOne({ collections: 'users' });
193
+ *
157
194
  * // ✅ Valid - dot notation for nested fields (must contain a dot)
158
195
  * await dbUsers.findOne({ 'address.city': 'New York' });
159
196
  * await dbUsers.findOne({ 'emails.0.address': 'test@example.com' });
@@ -163,7 +200,7 @@ type StrictRootFilterOperators<TSchema> = {
163
200
  * ```
164
201
  */
165
202
  type TypedFilter<T> = {
166
- [K in keyof WithId<T>]?: WithId<T>[K] | FilterOperators<WithId<T>[K]>;
203
+ [K in keyof WithId<T>]?: FilterValue<WithId<T>[K]>;
167
204
  } & StrictRootFilterOperators<T> & {
168
205
  [K: `${string}.${string}`]: any;
169
206
  };
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { A as AppServer, E as ExpressMiddleware, M as ModelenceConfig } from './index-CwdohC5n.js';
2
2
  export { e as AppConfig, l as Args, d as AuthErrorProps, q as AuthProvider, A as AuthSuccessProps, j as ClientInfo, b as ConfigKey, C as ConfigSchema, o as ConfigType, p as Configs, k as ConnectionInfo, i as Context, D as DefaultRoles, H as Handler, n as Method, M as MethodDefinition, m as MethodType, P as Permission, h as Role, R as RoleDefinition, f as Session, U as User, g as UserInfo, a as WebsocketClientProvider, W as WebsocketServerProvider } from './types-BOFsm7A2.js';
3
- export { B as BodyConfig, h as CronJob, C as CronJobInputParams, i as CronJobMetadata, g as EmailAttachment, c as EmailPayload, E as EmailProvider, k as ExpressHandler, H as HttpMethod, I as InferDocumentType, M as ModelSchema, a as RateLimitRule, b as RateLimitType, R as RouteDefinition, d as RouteHandler, j as RouteHandlers, e as RouteParams, f as RouteResponse, s as schema } from './types-SXHKNPNY.js';
3
+ export { B as BodyConfig, h as CronJob, C as CronJobInputParams, i as CronJobMetadata, g as EmailAttachment, c as EmailPayload, E as EmailProvider, k as ExpressHandler, H as HttpMethod, I as InferDocumentType, M as ModelSchema, a as RateLimitRule, b as RateLimitType, R as RouteDefinition, d as RouteHandler, j as RouteHandlers, e as RouteParams, f as RouteResponse, s as schema } from './types-V9eDnP35.js';
4
4
  import 'express';
5
5
  import 'http';
6
6
  import 'mongodb';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "modelence",
4
- "version": "0.9.0",
4
+ "version": "0.9.2",
5
5
  "description": "The Node.js Framework for Real-Time MongoDB Apps",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/global.d.ts",