hysteria-orm 10.4.4 → 10.4.5

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/lib/index.d.cts CHANGED
@@ -3418,6 +3418,16 @@ type UpdateOptions = {
3418
3418
  */
3419
3419
  type RelationQueryBuilderType<T extends Model, A extends Record<string, any> = {}, R extends Record<string, any> = {}> = Omit<ModelQueryBuilder<T, A, R>, "increment" | "decrement" | "first" | "firstOrFail" | "paginate" | "pluck" | "truncate" | "many" | "one" | "oneOrFail" | "insert" | "insertMany" | "update" | "delete" | "softDelete" | "getSum" | "getAvg" | "getMin" | "getMax" | "getCount" | "getMin" | "getMax" | "getCount">;
3420
3420
 
3421
+ /**
3422
+ * Helper type to determine if annotation overrides model field or goes to $annotations
3423
+ * If K is a key of the model T, it overrides that field in the model.
3424
+ * Otherwise, it goes into the annotations object A.
3425
+ */
3426
+ type AnnotationResult<T extends Model, A extends Record<string, any>, R extends Record<string, any>, K extends string, V> = K extends keyof T ? ModelQueryBuilder<T & {
3427
+ [P in K]: V;
3428
+ }, A, R> : ModelQueryBuilder<T, A & {
3429
+ [P in K]: V;
3430
+ }, R>;
3421
3431
  declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> = {}, R extends Record<string, any> = {}> extends QueryBuilder<T> {
3422
3432
  relation: Relation;
3423
3433
  protected sqlModelManagerUtils: SqlModelManagerUtils<T>;
@@ -3512,11 +3522,11 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3512
3522
  /**
3513
3523
  * @description Inserts a new record into the database, it is not advised to use this method directly from the query builder if using a ModelQueryBuilder (`Model.query()`), use the `Model.insert` method instead.
3514
3524
  */
3515
- insert(...args: Parameters<typeof this$1.model.insert>): ReturnType<typeof this$1.model.insert>;
3525
+ insert(...args: Parameters<typeof this$1.model.insert<T>>): ReturnType<typeof this$1.model.insert>;
3516
3526
  /**
3517
3527
  * @description Inserts multiple records into the database, it is not advised to use this method directly from the query builder if using a ModelQueryBuilder (`Model.query()`), use the `Model.insertMany` method instead.
3518
3528
  */
3519
- insertMany(...args: Parameters<typeof this$1.model.insertMany>): ReturnType<typeof this$1.model.insertMany>;
3529
+ insertMany(...args: Parameters<typeof this$1.model.insertMany<T>>): ReturnType<typeof this$1.model.insertMany>;
3520
3530
  update(data: Partial<ModelWithoutRelations<T>>, options?: UpdateOptions): Promise<number>;
3521
3531
  softDelete(options?: SoftDeleteOptions<T>): Promise<number>;
3522
3532
  delete(options?: DeleteOptions): Promise<number>;
@@ -3542,32 +3552,26 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3542
3552
  select(...columns: (ModelKey<T> | "*")[]): this;
3543
3553
  /**
3544
3554
  * @description Annotates a column with a SQL method or a simple alias
3545
- * @description If using a model, the result will be available in the $annotations property of the model, else it will be available in the result of the query
3555
+ * @description If the alias matches a model field name, it overrides that field. Otherwise, it's available in $annotations
3546
3556
  * @example
3547
3557
  * ```ts
3548
3558
  * const user = await User.query().annotate("max", "id", "maxId").first(); // max(id) as maxId
3549
3559
  * const user = await User.query().annotate("id", "superId").first(); // id as superId
3560
+ * // If alias matches model field, it overrides it:
3561
+ * const user = await User.query().annotate("COUNT(*)", "email").first(); // user.email is now a number
3550
3562
  * ```
3551
3563
  */
3552
- annotate<K extends string, V = any>(column: string, alias: K): ModelQueryBuilder<T, A & {
3553
- [P in K]: V;
3554
- }, R>;
3555
- annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: string, column: string, alias: K): ModelQueryBuilder<T, A & {
3556
- [P in K]: V;
3557
- }, R>;
3558
- annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): ModelQueryBuilder<T, A & {
3559
- [P in K]: V;
3560
- }, R>;
3561
- annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): ModelQueryBuilder<T, A & {
3562
- [P in K]: V;
3563
- }, R>;
3564
+ annotate<K extends string, V = any>(column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3565
+ annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: string, column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3566
+ annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3567
+ annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3564
3568
  /**
3565
3569
  * @description Selects a JSON value at the specified path and returns it as JSON
3566
3570
  * @param column The column containing JSON data
3567
3571
  * @param path The JSON path to extract (standardized format: "$.user.name", "user.name", or ["user", "name"])
3568
3572
  * @param alias The alias for the selected value
3569
3573
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3570
- * @description Result will be available in model.$annotations[alias]
3574
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3571
3575
  * @example
3572
3576
  * ```ts
3573
3577
  * // All these path formats are supported:
@@ -3590,24 +3594,24 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3590
3594
  * // 6. Root object
3591
3595
  * await User.query().selectJson("data", "$", "allData").first();
3592
3596
  *
3593
- * // Access the result
3597
+ * // Access the result - in $annotations if not a model field
3594
3598
  * const user = await User.query().selectJson("data", "user.name", "userName").first();
3595
3599
  * console.log(user?.$annotations?.userName); // Typed as any
3600
+ *
3601
+ * // If alias matches model field, it overrides it
3602
+ * const user2 = await User.query().selectJson("data", "$.name", "email").first();
3603
+ * console.log(user2?.email); // Overrides model's email field
3596
3604
  * ```
3597
3605
  */
3598
- selectJson<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3599
- [P in K]: any;
3600
- }, R>;
3601
- selectJson<K extends string>(column: string, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3602
- [P in K]: any;
3603
- }, R>;
3606
+ selectJson<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any>;
3607
+ selectJson<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any>;
3604
3608
  /**
3605
3609
  * @description Selects a JSON value at the specified path and returns it as text
3606
3610
  * @param column The column containing JSON data
3607
3611
  * @param path The JSON path to extract (standardized format)
3608
3612
  * @param alias The alias for the selected value
3609
3613
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3610
- * @description Result will be available in model.$annotations[alias]
3614
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3611
3615
  * @example
3612
3616
  * ```ts
3613
3617
  * // All these path formats are supported:
@@ -3628,24 +3632,20 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3628
3632
  * // 5. Deep nesting
3629
3633
  * await User.query().selectJsonText("data", "user.profile.bio", "biography").first();
3630
3634
  *
3631
- * // Access the result
3632
- * const user = await User.query().selectJsonText("data", "user.email", "email").first();
3633
- * console.log(user?.$annotations?.email); // Typed as string
3635
+ * // Access the result - in $annotations if not a model field
3636
+ * const user = await User.query().selectJsonText("data", "user.email", "userEmail").first();
3637
+ * console.log(user?.$annotations?.userEmail); // Typed as string
3634
3638
  * ```
3635
3639
  */
3636
- selectJsonText<K extends string>(column: ModelKey<T>, path: any, alias: K): ModelQueryBuilder<T, A & {
3637
- [P in K]: string;
3638
- }, R>;
3639
- selectJsonText<K extends string>(column: string, path: any, alias: K): ModelQueryBuilder<T, A & {
3640
- [P in K]: string;
3641
- }, R>;
3640
+ selectJsonText<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, string>;
3641
+ selectJsonText<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, string>;
3642
3642
  /**
3643
3643
  * @description Selects the length of a JSON array
3644
3644
  * @param column The column containing JSON array data
3645
3645
  * @param path The JSON path to the array (standardized format, use "$" or "" for root)
3646
3646
  * @param alias The alias for the length value
3647
3647
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3648
- * @description Result will be available in model.$annotations[alias]
3648
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3649
3649
  * @warning Not supported in SQLite
3650
3650
  * @example
3651
3651
  * ```ts
@@ -3671,24 +3671,20 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3671
3671
  * // 6. Deeply nested arrays
3672
3672
  * await User.query().selectJsonArrayLength("data", "level1.level2.items", "deepCount").first();
3673
3673
  *
3674
- * // Access the result
3674
+ * // Access the result - in $annotations if not a model field
3675
3675
  * const user = await User.query().selectJsonArrayLength("data", "items", "count").first();
3676
3676
  * console.log(user?.$annotations?.count); // Typed as number
3677
3677
  * ```
3678
3678
  */
3679
- selectJsonArrayLength<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3680
- [P in K]: number;
3681
- }, R>;
3682
- selectJsonArrayLength<K extends string>(column: string, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3683
- [P in K]: number;
3684
- }, R>;
3679
+ selectJsonArrayLength<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, number>;
3680
+ selectJsonArrayLength<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, number>;
3685
3681
  /**
3686
3682
  * @description Selects the keys of a JSON object
3687
3683
  * @param column The column containing JSON object data
3688
3684
  * @param path The JSON path to the object (standardized format, use "$" or "" for root)
3689
3685
  * @param alias The alias for the keys
3690
3686
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3691
- * @description Result will be available in model.$annotations[alias]
3687
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3692
3688
  * @warning Not supported in SQLite or MSSQL
3693
3689
  * @postgresql Returns a native array of keys
3694
3690
  * @mysql Returns a JSON array of keys
@@ -3716,22 +3712,18 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3716
3712
  * // 6. Deeply nested objects
3717
3713
  * await User.query().selectJsonKeys("data", "settings.display.theme", "themeKeys").first();
3718
3714
  *
3719
- * // Access the result
3715
+ * // Access the result - in $annotations if not a model field
3720
3716
  * const user = await User.query().selectJsonKeys("data", "settings", "keys").first();
3721
3717
  * console.log(user?.$annotations?.keys); // Typed as any[] - ["theme", "fontSize", "autoSave"]
3722
3718
  * ```
3723
3719
  */
3724
- selectJsonKeys<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3725
- [P in K]: any[];
3726
- }, R>;
3727
- selectJsonKeys<K extends string>(column: string, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3728
- [P in K]: any[];
3729
- }, R>;
3720
+ selectJsonKeys<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any[]>;
3721
+ selectJsonKeys<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any[]>;
3730
3722
  /**
3731
3723
  * @description Adds a raw JSON select expression for database-specific operations
3732
3724
  * @param raw The raw SQL expression (database-specific syntax)
3733
3725
  * @param alias The alias for the selected value
3734
- * @description Result will be available in model.$annotations[alias]
3726
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3735
3727
  * @description Use this for advanced JSON operations not covered by other selectJson* methods
3736
3728
  * @warning This bypasses path standardization - you must write database-specific SQL
3737
3729
  * @example
@@ -3757,14 +3749,12 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3757
3749
  * // SQLite - Extract value with json_extract
3758
3750
  * await User.query().selectJsonRaw("json_extract(data, '$.email')", "userEmail").first();
3759
3751
  *
3760
- * // Access the result
3761
- * const user = await User.query().selectJsonRaw("data->>'email'", "email").first();
3762
- * console.log(user?.$annotations?.email); // Typed as any
3752
+ * // Access the result - in $annotations if not a model field
3753
+ * const user = await User.query().selectJsonRaw("data->>'email'", "userEmail").first();
3754
+ * console.log(user?.$annotations?.userEmail); // Typed as any
3763
3755
  * ```
3764
3756
  */
3765
- selectJsonRaw<K extends string>(raw: string, alias: K): ModelQueryBuilder<T, A & {
3766
- [P in K]: any;
3767
- }, R>;
3757
+ selectJsonRaw<K extends string>(raw: string, alias: K): AnnotationResult<T, A, R, K, any>;
3768
3758
  /**
3769
3759
  * @description Removes annotations from the serialized model, by default, annotations are maintained in the serialized model if `annotate` is used
3770
3760
  */
@@ -4529,7 +4519,7 @@ declare class SqlDataSource<D extends SqlDataSourceType = SqlDataSourceType, T e
4529
4519
  private connectWithoutSettingPrimary;
4530
4520
  }
4531
4521
 
4532
- type ModelWithoutRelations<T extends Model> = Pick<T, ExcludeRelations<Omit<T, "*">>>;
4522
+ type ModelWithoutRelations<T extends Model> = Pick<Omit<T, "*">, ExcludeRelations<Omit<T, "*">>> & Pick<Model, keyof Model>;
4533
4523
  type NumberModelKey<T extends Model> = {
4534
4524
  [K in keyof T]: T[K] extends number | bigint ? K : never;
4535
4525
  }[keyof T];
@@ -5376,6 +5366,12 @@ declare abstract class Model extends Entity {
5376
5366
  * @throws {HysteriaError} If the model has no primary key valorized in the instance
5377
5367
  */
5378
5368
  refresh<T extends Model = this>(options?: Omit<BaseModelMethodOptions, "ignoreHooks">): Promise<T>;
5369
+ /**
5370
+ * @description Converts the model to a JSON object
5371
+ * @description Flattens all `$annotations` into the JSON object at first level including the relations
5372
+ * @warning Use with caution, this method flattens the `$annotations` into the JSON object at first level including the relations, so if you have conflicting column names between model columns and annotations, the annotation could override the model column value
5373
+ */
5374
+ toJSON(): Record<string, any>;
5379
5375
  }
5380
5376
 
5381
5377
  type BaseModelRelationType = {
package/lib/index.d.ts CHANGED
@@ -3418,6 +3418,16 @@ type UpdateOptions = {
3418
3418
  */
3419
3419
  type RelationQueryBuilderType<T extends Model, A extends Record<string, any> = {}, R extends Record<string, any> = {}> = Omit<ModelQueryBuilder<T, A, R>, "increment" | "decrement" | "first" | "firstOrFail" | "paginate" | "pluck" | "truncate" | "many" | "one" | "oneOrFail" | "insert" | "insertMany" | "update" | "delete" | "softDelete" | "getSum" | "getAvg" | "getMin" | "getMax" | "getCount" | "getMin" | "getMax" | "getCount">;
3420
3420
 
3421
+ /**
3422
+ * Helper type to determine if annotation overrides model field or goes to $annotations
3423
+ * If K is a key of the model T, it overrides that field in the model.
3424
+ * Otherwise, it goes into the annotations object A.
3425
+ */
3426
+ type AnnotationResult<T extends Model, A extends Record<string, any>, R extends Record<string, any>, K extends string, V> = K extends keyof T ? ModelQueryBuilder<T & {
3427
+ [P in K]: V;
3428
+ }, A, R> : ModelQueryBuilder<T, A & {
3429
+ [P in K]: V;
3430
+ }, R>;
3421
3431
  declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> = {}, R extends Record<string, any> = {}> extends QueryBuilder<T> {
3422
3432
  relation: Relation;
3423
3433
  protected sqlModelManagerUtils: SqlModelManagerUtils<T>;
@@ -3512,11 +3522,11 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3512
3522
  /**
3513
3523
  * @description Inserts a new record into the database, it is not advised to use this method directly from the query builder if using a ModelQueryBuilder (`Model.query()`), use the `Model.insert` method instead.
3514
3524
  */
3515
- insert(...args: Parameters<typeof this$1.model.insert>): ReturnType<typeof this$1.model.insert>;
3525
+ insert(...args: Parameters<typeof this$1.model.insert<T>>): ReturnType<typeof this$1.model.insert>;
3516
3526
  /**
3517
3527
  * @description Inserts multiple records into the database, it is not advised to use this method directly from the query builder if using a ModelQueryBuilder (`Model.query()`), use the `Model.insertMany` method instead.
3518
3528
  */
3519
- insertMany(...args: Parameters<typeof this$1.model.insertMany>): ReturnType<typeof this$1.model.insertMany>;
3529
+ insertMany(...args: Parameters<typeof this$1.model.insertMany<T>>): ReturnType<typeof this$1.model.insertMany>;
3520
3530
  update(data: Partial<ModelWithoutRelations<T>>, options?: UpdateOptions): Promise<number>;
3521
3531
  softDelete(options?: SoftDeleteOptions<T>): Promise<number>;
3522
3532
  delete(options?: DeleteOptions): Promise<number>;
@@ -3542,32 +3552,26 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3542
3552
  select(...columns: (ModelKey<T> | "*")[]): this;
3543
3553
  /**
3544
3554
  * @description Annotates a column with a SQL method or a simple alias
3545
- * @description If using a model, the result will be available in the $annotations property of the model, else it will be available in the result of the query
3555
+ * @description If the alias matches a model field name, it overrides that field. Otherwise, it's available in $annotations
3546
3556
  * @example
3547
3557
  * ```ts
3548
3558
  * const user = await User.query().annotate("max", "id", "maxId").first(); // max(id) as maxId
3549
3559
  * const user = await User.query().annotate("id", "superId").first(); // id as superId
3560
+ * // If alias matches model field, it overrides it:
3561
+ * const user = await User.query().annotate("COUNT(*)", "email").first(); // user.email is now a number
3550
3562
  * ```
3551
3563
  */
3552
- annotate<K extends string, V = any>(column: string, alias: K): ModelQueryBuilder<T, A & {
3553
- [P in K]: V;
3554
- }, R>;
3555
- annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: string, column: string, alias: K): ModelQueryBuilder<T, A & {
3556
- [P in K]: V;
3557
- }, R>;
3558
- annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): ModelQueryBuilder<T, A & {
3559
- [P in K]: V;
3560
- }, R>;
3561
- annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): ModelQueryBuilder<T, A & {
3562
- [P in K]: V;
3563
- }, R>;
3564
+ annotate<K extends string, V = any>(column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3565
+ annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: string, column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3566
+ annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3567
+ annotate<K extends string, S extends SqlMethod, V = CommonSqlMethodReturnType<S>>(sqlMethod: S, column: string, alias: K): AnnotationResult<T, A, R, K, V>;
3564
3568
  /**
3565
3569
  * @description Selects a JSON value at the specified path and returns it as JSON
3566
3570
  * @param column The column containing JSON data
3567
3571
  * @param path The JSON path to extract (standardized format: "$.user.name", "user.name", or ["user", "name"])
3568
3572
  * @param alias The alias for the selected value
3569
3573
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3570
- * @description Result will be available in model.$annotations[alias]
3574
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3571
3575
  * @example
3572
3576
  * ```ts
3573
3577
  * // All these path formats are supported:
@@ -3590,24 +3594,24 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3590
3594
  * // 6. Root object
3591
3595
  * await User.query().selectJson("data", "$", "allData").first();
3592
3596
  *
3593
- * // Access the result
3597
+ * // Access the result - in $annotations if not a model field
3594
3598
  * const user = await User.query().selectJson("data", "user.name", "userName").first();
3595
3599
  * console.log(user?.$annotations?.userName); // Typed as any
3600
+ *
3601
+ * // If alias matches model field, it overrides it
3602
+ * const user2 = await User.query().selectJson("data", "$.name", "email").first();
3603
+ * console.log(user2?.email); // Overrides model's email field
3596
3604
  * ```
3597
3605
  */
3598
- selectJson<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3599
- [P in K]: any;
3600
- }, R>;
3601
- selectJson<K extends string>(column: string, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3602
- [P in K]: any;
3603
- }, R>;
3606
+ selectJson<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any>;
3607
+ selectJson<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any>;
3604
3608
  /**
3605
3609
  * @description Selects a JSON value at the specified path and returns it as text
3606
3610
  * @param column The column containing JSON data
3607
3611
  * @param path The JSON path to extract (standardized format)
3608
3612
  * @param alias The alias for the selected value
3609
3613
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3610
- * @description Result will be available in model.$annotations[alias]
3614
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3611
3615
  * @example
3612
3616
  * ```ts
3613
3617
  * // All these path formats are supported:
@@ -3628,24 +3632,20 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3628
3632
  * // 5. Deep nesting
3629
3633
  * await User.query().selectJsonText("data", "user.profile.bio", "biography").first();
3630
3634
  *
3631
- * // Access the result
3632
- * const user = await User.query().selectJsonText("data", "user.email", "email").first();
3633
- * console.log(user?.$annotations?.email); // Typed as string
3635
+ * // Access the result - in $annotations if not a model field
3636
+ * const user = await User.query().selectJsonText("data", "user.email", "userEmail").first();
3637
+ * console.log(user?.$annotations?.userEmail); // Typed as string
3634
3638
  * ```
3635
3639
  */
3636
- selectJsonText<K extends string>(column: ModelKey<T>, path: any, alias: K): ModelQueryBuilder<T, A & {
3637
- [P in K]: string;
3638
- }, R>;
3639
- selectJsonText<K extends string>(column: string, path: any, alias: K): ModelQueryBuilder<T, A & {
3640
- [P in K]: string;
3641
- }, R>;
3640
+ selectJsonText<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, string>;
3641
+ selectJsonText<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, string>;
3642
3642
  /**
3643
3643
  * @description Selects the length of a JSON array
3644
3644
  * @param column The column containing JSON array data
3645
3645
  * @param path The JSON path to the array (standardized format, use "$" or "" for root)
3646
3646
  * @param alias The alias for the length value
3647
3647
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3648
- * @description Result will be available in model.$annotations[alias]
3648
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3649
3649
  * @warning Not supported in SQLite
3650
3650
  * @example
3651
3651
  * ```ts
@@ -3671,24 +3671,20 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3671
3671
  * // 6. Deeply nested arrays
3672
3672
  * await User.query().selectJsonArrayLength("data", "level1.level2.items", "deepCount").first();
3673
3673
  *
3674
- * // Access the result
3674
+ * // Access the result - in $annotations if not a model field
3675
3675
  * const user = await User.query().selectJsonArrayLength("data", "items", "count").first();
3676
3676
  * console.log(user?.$annotations?.count); // Typed as number
3677
3677
  * ```
3678
3678
  */
3679
- selectJsonArrayLength<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3680
- [P in K]: number;
3681
- }, R>;
3682
- selectJsonArrayLength<K extends string>(column: string, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3683
- [P in K]: number;
3684
- }, R>;
3679
+ selectJsonArrayLength<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, number>;
3680
+ selectJsonArrayLength<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, number>;
3685
3681
  /**
3686
3682
  * @description Selects the keys of a JSON object
3687
3683
  * @param column The column containing JSON object data
3688
3684
  * @param path The JSON path to the object (standardized format, use "$" or "" for root)
3689
3685
  * @param alias The alias for the keys
3690
3686
  * @description Path format is standardized across all databases - ORM converts to DB-specific syntax
3691
- * @description Result will be available in model.$annotations[alias]
3687
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3692
3688
  * @warning Not supported in SQLite or MSSQL
3693
3689
  * @postgresql Returns a native array of keys
3694
3690
  * @mysql Returns a JSON array of keys
@@ -3716,22 +3712,18 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3716
3712
  * // 6. Deeply nested objects
3717
3713
  * await User.query().selectJsonKeys("data", "settings.display.theme", "themeKeys").first();
3718
3714
  *
3719
- * // Access the result
3715
+ * // Access the result - in $annotations if not a model field
3720
3716
  * const user = await User.query().selectJsonKeys("data", "settings", "keys").first();
3721
3717
  * console.log(user?.$annotations?.keys); // Typed as any[] - ["theme", "fontSize", "autoSave"]
3722
3718
  * ```
3723
3719
  */
3724
- selectJsonKeys<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3725
- [P in K]: any[];
3726
- }, R>;
3727
- selectJsonKeys<K extends string>(column: string, path: JsonPathInput, alias: K): ModelQueryBuilder<T, A & {
3728
- [P in K]: any[];
3729
- }, R>;
3720
+ selectJsonKeys<K extends string>(column: ModelKey<T>, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any[]>;
3721
+ selectJsonKeys<K extends string>(column: string, path: JsonPathInput, alias: K): AnnotationResult<T, A, R, K, any[]>;
3730
3722
  /**
3731
3723
  * @description Adds a raw JSON select expression for database-specific operations
3732
3724
  * @param raw The raw SQL expression (database-specific syntax)
3733
3725
  * @param alias The alias for the selected value
3734
- * @description Result will be available in model.$annotations[alias]
3726
+ * @description If alias matches a model field, it overrides that field. Otherwise, it's in $annotations
3735
3727
  * @description Use this for advanced JSON operations not covered by other selectJson* methods
3736
3728
  * @warning This bypasses path standardization - you must write database-specific SQL
3737
3729
  * @example
@@ -3757,14 +3749,12 @@ declare class ModelQueryBuilder<T extends Model, A extends Record<string, any> =
3757
3749
  * // SQLite - Extract value with json_extract
3758
3750
  * await User.query().selectJsonRaw("json_extract(data, '$.email')", "userEmail").first();
3759
3751
  *
3760
- * // Access the result
3761
- * const user = await User.query().selectJsonRaw("data->>'email'", "email").first();
3762
- * console.log(user?.$annotations?.email); // Typed as any
3752
+ * // Access the result - in $annotations if not a model field
3753
+ * const user = await User.query().selectJsonRaw("data->>'email'", "userEmail").first();
3754
+ * console.log(user?.$annotations?.userEmail); // Typed as any
3763
3755
  * ```
3764
3756
  */
3765
- selectJsonRaw<K extends string>(raw: string, alias: K): ModelQueryBuilder<T, A & {
3766
- [P in K]: any;
3767
- }, R>;
3757
+ selectJsonRaw<K extends string>(raw: string, alias: K): AnnotationResult<T, A, R, K, any>;
3768
3758
  /**
3769
3759
  * @description Removes annotations from the serialized model, by default, annotations are maintained in the serialized model if `annotate` is used
3770
3760
  */
@@ -4529,7 +4519,7 @@ declare class SqlDataSource<D extends SqlDataSourceType = SqlDataSourceType, T e
4529
4519
  private connectWithoutSettingPrimary;
4530
4520
  }
4531
4521
 
4532
- type ModelWithoutRelations<T extends Model> = Pick<T, ExcludeRelations<Omit<T, "*">>>;
4522
+ type ModelWithoutRelations<T extends Model> = Pick<Omit<T, "*">, ExcludeRelations<Omit<T, "*">>> & Pick<Model, keyof Model>;
4533
4523
  type NumberModelKey<T extends Model> = {
4534
4524
  [K in keyof T]: T[K] extends number | bigint ? K : never;
4535
4525
  }[keyof T];
@@ -5376,6 +5366,12 @@ declare abstract class Model extends Entity {
5376
5366
  * @throws {HysteriaError} If the model has no primary key valorized in the instance
5377
5367
  */
5378
5368
  refresh<T extends Model = this>(options?: Omit<BaseModelMethodOptions, "ignoreHooks">): Promise<T>;
5369
+ /**
5370
+ * @description Converts the model to a JSON object
5371
+ * @description Flattens all `$annotations` into the JSON object at first level including the relations
5372
+ * @warning Use with caution, this method flattens the `$annotations` into the JSON object at first level including the relations, so if you have conflicting column names between model columns and annotations, the annotation could override the model column value
5373
+ */
5374
+ toJSON(): Record<string, any>;
5379
5375
  }
5380
5376
 
5381
5377
  type BaseModelRelationType = {