ExpressWebJs 4 is now released!
Tags: expresswebjs, node, typescript, api
Published: 2022-09-21 17:17:22

[ExpressWebJs](https://expresswebjs.com/) version 4 is now released and it includes many new features, including:

- Mongoose and ObjectionJs ORM support.
- SQL database relationship addons.
- Multi-tenancy support for mongo DB.
- Route match.
- Route redirect.
- Improved middleware handler methods.
- Improved service registry handlers.
- Custom validation rules.
- Improved event class generation.
- Added Redis to the supported queue connections.
- Service communication for distributed services.
- Domain-driven design (DDD).
- Support for Restana platform service for faster request 
  processing.
- New utility features like `Optional( )`,`ObjectMapper( )`, 
 `FirstCharacterToLowerCase( )`, `Group( )`, `ObjectHasProperty( )`.
- New Collection feature which helps you work on advanced data 
  structures and algorithms.

> [ExpressWebJs](https://expresswebjs.com/) uses a variety of community driven packages for a number of features in the framework.

[ExpressWebJs](https://expresswebjs.com/) version 4 will receive bug fixes until November 2023 and security fixes until February 2024. Here are some of the features that we’ve covered in detail.

**We’ve added some relationship add-ons for the SQL database model.**
The relationship mapping method now has a nice way of handling relationships with the new `hasMany`, `belongsTo`, `hasOne`, `hasOneThrough`, `hasManyThrough` methods that also accept additional options.

**hasManyThrough()**
```ts
 export class UserModel extends Model {
  static tableName = "users";

  id!: string;
  name!: string;
  email!: string;
  password!: string;

  static relationMappings() {
    return {
      carOwner: this.hasManyThrough("App/Model/Cars_model",
      "App/Model/CarOwners_model", {
        join_final_foreign_key: "user_id",
        join_parent_foreign_key: "car_id",
      }),
    };
  }
}
```
**hasOneThrough()**
```ts
 export class UserModel extends Model {
  static tableName = "users";

  id!: string;
  name!: string;
  email!: string;
  password!: string;

  static relationMappings() {
    return {
      carOwner: this.hasOneThrough("App/Model/Cars_model", 
        "App/Model/CarOwners_model", {
        join_final_foreign_key: "user_id",
        join_parent_foreign_key: "car_id",
      }),
    };
  }
}
```

**hasOne()**
```ts
export class UserModel extends Model {
  static tableName = "users";

  id!: string;
  first_name!: string;
  last_name!: string;
  email!: string;
  password!: string;

  static relationMappings() {
    return {
      profile: this.hasOne("App/Model/Profile_model"),
    };
  }
}
```

**hasMany()**
```ts
export class UserModel extends Model {
  static tableName = "users";

  id!: string;
  first_name!: string;
  last_name!: string;
  email!: string;
  password!: string;

  static relationMappings() {
    return {
      profile: this.hasMany("App/Model/Cars_model"),
    };
  }
}
```

**belongsTo()**
```ts
export class Posts extends Model {
  static tableName = "posts";

  id!: string;
  name!: string;
  user_id!: string;

  static relationMappings() {
    return {
      users: this.belongsTo("App/Model/Users_model"),
    };
  }
}
```

**Relation filters**
You can also add some filters to your relationship mapping:

```ts
static relationMappings() {
    return {
      profile: this.hasMany("App/Model/Cars_model",{
        filter: (builder) => {
          builder.where("name", "Mercedes");
        },
      }),
    };
  }
```

Some route features are also added

**Route Match**
Sometimes you may need to register a route that responds to multiple HTTP verbs. You may do so using the match method. Or, you may even register a route that responds to all HTTP verbs using the all method:
```ts
  Route.match(["get", "post"], "/books", 
        "UserController@process");
```

**Route Redirect**
If you are defining a route that redirects to another URI, you may use the Route redirect method. This method provides a convenient shortcut so that you do not have to define a full route or controller for performing this task.

```ts
 Route.redirect("source_url", "destination_url");
```

You can see the complete list of new features and updates on [ExpressWebJs](https://expresswebjs.com/) website.

Kindly follow [ExpressWebJs](https://twitter.com/expresswebjs) on [twitter](https://twitter.com/expresswebjs).

And don't forget to star on [github](https://github.com/Alexigbokwe/ExpressWebJs).

You can also join the [discord](https://discord.com/invite/vrPGZCgJuj) channel