# Resource

In FastSchema, a Resource is a component that processes user requests and returns responses.

Source: https://fastschema.com/docs/framework/resource

In FastSchema, a Resource is a component that processes user requests and returns responses. It functions similarly to a controller in the MVC pattern or a resolver in GraphQL.

## Definition

```go
type Resource struct {
	id         string
	group      bool
	resources  []*Resource
	name       string
	handler    Handler
	meta       *Meta
	signatures Signatures
}
```

A resource is an object that created from a `fastschema.Resource` struct. It has the following properties:

- `id`: a unique identifier for the resource. This is generated automatically by The resource manager.
- `group`: a boolean value that indicates whether the resource is a group or not. A group resource contains other resources.
- `resources`: a list of resources that are contained within the group resource.
- `name`: the name of the resource.
- `handler`: a function that processes the request and returns a response.
- `meta`: a metadata object that contains additional information about the resource.
- `signatures`: a list of signatures that define the input and output of the resource.

## Resource manager

A resource manager is basically a normal resource with additional features.

```go
type ResourcesManager struct {
	*Resource
	Middlewares []Middleware
	Hooks       func() *Hooks
}
```

- **Middlewares:** Middlewares are functions that execute on every request. They do not have access or information about the resource handler. They can be used to add common functionalities like logging, authentication, etc.
- **Hooks:**: Hooks are functions that run before or after the main handler. They have access to the resource handler and can be used to modify the input/output or add additional functionalities.

### Create a resource manager

```go
resourceManager := fs.NewResourcesManager()
resourceManager.Add(
  fs.NewResource("hello", func(c fs.Context, _ any) (string, error) {
    return "Hello, World!", nil
  }, &fs.Meta{ Get: "/" }),
)
```

## Create Resource

**Example:**

```go
package main

import (
  "github.com/fastwego/fastschema/fs"
)

type Input struct {
  Name string `json:"name"`
}

type Output struct {
  Message string `json:"message"`
}

func main() {
  handler := func(c fs.Context, input *Input) (*Output, error) {
    return &Output{
      Message: "Hello, " + input.Name,
    }, nil
  }

  meta := &fs.Meta{Get: "/"}
  rs := fs.NewResource("hello", handler, &fs.Meta{Get: "/"})
}
```

**Let's break down the code above:**

1. We define two structs, `Input` and `Output`, that represent the input and output of the resource, we call them resource Signatures.
2. We define a handler function that processes the request and returns a response.
   - `c fs.Context` is the context object that contains information about the request.
   - `input *Input` is the input/payload data that the resource receives.
   - `*Output` is the output/response data that the resource returns.
3. We create a metadata object that contains information about the resource. In this case, we specify that the resource can be accessed via the HTTP `GET` method.
4. We create a new resource using the `NewResource` function. We pass in the name, handler function, and metadata object as parameters.

### NewResource

```go
func NewResource[Input, Output any](
	name string,
	handler HandlerFn[Input, Output],
	metas ...*Meta,
) *Resource
```

To create a resource, you can use the `NewResource` function. This function takes the following parameters:

- `name`: the name of the resource.
- `handler`: a function that processes the request and returns a response.
- `metas`: a list of metadata objects that contain additional information about the resource.

## Resource methods

Resource supports many convenient methods to help you build your application, these methods are also applicable to the resource manager.

### Clone

```go
func (r *Resource) Clone() *Resource
```

The `Clone` method creates a copy of the resource. This is useful when you want to create multiple resources with similar configurations.

### AddResource

```go
func (r *Resource) AddResource(
  name string,
  handler Handler,
  metas ...*Meta,
) (self *Resource)
```

The `AddResource` method adds a sub-resource to the resource. Sub-resources are resources that are nested within the main resource. They can be used to create hierarchical structures or to group related resources together.

`AddResource` returns the current resource, so you can chain multiple `AddResource` calls together.

This method is often used in the `ResourceManager` to create a resource hierarchy.

### Add

```go
func (r *Resource) Add(resources ...*Resource) (self *Resource)
```

The `Add` method adds one or more sub-resource to the resource. This is a convenient way to add multiple resources to the resource at once.

`Add` returns the current resource, so you can chain multiple `Add` calls together.

### Find

```go
func (r *Resource) Find(resourceID string) *Resource {
```

The `Find` method searches for a sub-resource by its ID. It returns the sub-resource if found, or `nil` if not found.

### Group

```go
Group(name string, metas ...*Meta) (group *Resource)
```

The `Group` method creates a new group resource. Group resources are used to group related resources together. They are similar to sub-resources, but they do not have a handler function.

### Other resource methods

- `ID() string`: Get the ID of the resource.
- `Name() string`: Get the name of the resource.
- `Path() string`: Get the path of the resource.
- `Handler() Handler`: Get the handler function of the resource.
- `Meta() *Meta`: Get the metadata of the resource.
- `Signature() Signatures`: Get the signature of the resource.
- `Resources() []*Resource`: Get the sub-resources of the resource.
- `IsGroup() bool`: Check if the resource is a group resource.
- `IsPublic() bool`: Check if the resource is public.
- `String() string`: Get the string representation of the resource.
- `Print()`: Print the resource to the console.
- `MarshalJSON() ([]byte, error)`: Marshal the resource to JSON.
