Skip to content

Commit

Permalink
docs(core): adjust documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
nartc committed Mar 12, 2023
1 parent e82e9a1 commit 193d541
Show file tree
Hide file tree
Showing 73 changed files with 13,550 additions and 1 deletion.
20 changes: 20 additions & 0 deletions packages/documentation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
/node_modules

# Production
/build

# Generated files
.docusaurus
.cache-loader

# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
41 changes: 41 additions & 0 deletions packages/documentation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Website

This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.

### Installation

```
$ yarn
```

### Local Development

```
$ yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

### Build

```
$ yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

### Deployment

Using SSH:

```
$ USE_SSH=true yarn deploy
```

Not using SSH:

```
$ GIT_USER=<Your GitHub username> yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
3 changes: 3 additions & 0 deletions packages/documentation/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};
12 changes: 12 additions & 0 deletions packages/documentation/blog/2019-05-28-first-blog-post.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
slug: first-blog-post
title: First Blog Post
authors:
name: Gao Wei
title: Docusaurus Core Team
url: https://github.com/wgao19
image_url: https://github.com/wgao19.png
tags: [hola, docusaurus]
---

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
44 changes: 44 additions & 0 deletions packages/documentation/blog/2019-05-29-long-blog-post.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
slug: long-blog-post
title: Long Blog Post
authors: endi
tags: [hello, docusaurus]
---

This is the summary of a very long blog post,

Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.

<!--truncate-->

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
20 changes: 20 additions & 0 deletions packages/documentation/blog/2021-08-01-mdx-blog-post.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
slug: mdx-blog-post
title: MDX Blog Post
authors: [slorber]
tags: [docusaurus]
---

Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).

:::tip

Use the power of React to create interactive blog posts.

```js
<button onClick={() => alert('button clicked!')}>Click me!</button>
```

<button onClick={() => alert('button clicked!')}>Click me!</button>

:::
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions packages/documentation/blog/2021-08-26-welcome/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
slug: welcome
title: Welcome
authors: [slorber, yangshun]
tags: [facebook, hello, docusaurus]
---

[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).

Simply add Markdown files (or folders) to the `blog` directory.

Regular blog authors can be added to `authors.yml`.

The blog post date can be extracted from filenames, such as:

- `2019-05-30-welcome.md`
- `2019-05-30-welcome/index.md`

A blog post folder can be convenient to co-locate blog post images:

![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)

The blog supports tags as well!

**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
17 changes: 17 additions & 0 deletions packages/documentation/blog/authors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
endi:
name: Endilie Yacop Sucipto
title: Maintainer of Docusaurus
url: https://github.com/endiliey
image_url: https://github.com/endiliey.png

yangshun:
name: Yangshun Tay
title: Front End Engineer @ Facebook
url: https://github.com/yangshun
image_url: https://github.com/yangshun.png

slorber:
name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
123 changes: 123 additions & 0 deletions packages/documentation/docs/fundamentals/auto-flattening.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
id: auto-flattening
title: Auto Flattening
sidebar_label: Auto Flattening
sidebar_position: 4
---

One of the common usages of object-object mapping is to take a complex object model and flatten it to a simpler model. If we set up the models following the convention, AutoMapper can help with flattening automatically. To enable Auto Flattening, we need to set the [NamingConvention](./naming-convention) for our models.

Let's assume we have the following complex models:

```ts
class Product {
@AutoMap()
price!: number;
@AutoMap()
name!: string;

constructor(price: number, name: string) {
this.price = price;
this.name = name;
}
}

class Customer {
@AutoMap()
name!: string;

constructor(name: string) {
this.name = name;
}
}

class OrderItem {
@AutoMap(() => Product)
product!: Product;
@AutoMap()
quantity!: number;

constructor(product: Product, quantity: number) {
this.product = product;
this.quantity = quantity;
}

get total() {
return this.product.price * this.quantity;
}
}

class Order {
@AutoMap(() => [OrderItem])
items: OrderItem[] = [];
@AutoMap(() => Customer)
customer!: Customer;

constructor(customer: Customer) {
this.customer = customer;
}

@AutoMap() // 👇 need to specify the type for getter
get total(): number {
return this.items.reduce((sum, item) => sum + item.total, 0);
}

addItem(product: Product, quantity: number) {
this.items.push(new OrderItem(product, quantity));
}
}
```

Now, we want to map the complex `Order` model to a simpler `OrderDto` that contains only the data needed for a certain scenario:

```ts
class OrderDto {
@AutoMap()
customerName!: string;
@AutoMap()
total!: number;
}
```

Assuming we have Auto Flattening enabled by applying a `NamingConvention`, AutoMapper will attempt to match the properties on `OrderDto` against `Order` and its child models (`Product` and `Customer`) when we call `createMap(mapper, Order, OrderDto)`

```ts
// complex model
const product = new Product(5, 'Fried Chicken');
const customer = new Customer('Chau Tran');
const order = new Order(customer);
order.addItem(product, 10);
/**
* Order {
* customer: Customer {
* name: 'Chau Tran'
* },
* items: [
* OrderItem {
* product: Product {
* price: 5,
* name: 'Fried Chicken
* },
* quantity: 10
* }
* ]
* }
*/

// configure AutoMapper with NamingConvention
const mapper = createMapper({
strategyInitializer: classes(),
// 👇 apply the CamelCaseNamingConvention
namingConventions: new CamelCaseNamingConvention(),
});

createMap(mapper, Order, OrderDto);

const dto = mapper.map(order, Order, OrderDto);
/**
* OrderDto {
* customerName: 'Chau Tran',
* total: 50
* }
*/
```
80 changes: 80 additions & 0 deletions packages/documentation/docs/fundamentals/mapper.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
id: mapper
title: Mapper
sidebar_label: Mapper
sidebar_position: 1
---

## Mapper

`Mapper` is the main character in AutoMapper TypeScript. Everything starts with a `Mapper`. To create a `Mapper`, call `createMapper()` along with a [Strategy](#mappingstrategy)

```ts
const mapper = createMapper({
strategyInitializer: classes(),
});
```

## MappingStrategy

In order for `Mapper` to map properties, `Mapper` needs to know about the properties' metadata. That's what the Strategy provides to the `Mapper`. A Strategy deals with:

- Discover the metadata: Based on the user input, a strategy needs to know how to discover the metadata of the models from that input. E.g: `@automapper/classes` can discover the metadata with `@AutoMap` decorator.
- Retrieve the metadata: A strategy has its own "storage" to store the raw metadata. In order for `Mapper` to work consistently, a Strategy needs to provide a way to retrieve this metadata in the shape that `Mapper` can understand. E.g: `@automapper/classes` stores the metadata in `Reflect` object.
- Apply the metadata: By default, `Mapper` knows how to apply the metadata for a specific model. However, the consumers can customize this behavior by passing in a custom `applyMetadata` function.

In addition to dealing with metadata, a Strategy also provides two hooks:

- `preMap`: Runs before the map operation starts. This step is usually to prepare the `sourceObject` before it goes into the `map` operation.
- `postMap`: Runs after the map operation starts. This step is usually to massage the result `destinationObject` before it gets returned to the user.

### Official Strategies

AutoMapper TypeScript comes with 4 official strategies:

| package | strategy | description |
| ----------------------- | ------------- | ----------------------------------------------------------------- |
| `@automapper/classes` | `classes()` | Works with TS/ES6 Classes |
| `@automapper/pojos` | `pojos()` | Works with Interfaces/Types |
| `@automapper/mikro` | `mikro()` | Works with TS/ES6 Classes and [MikroORM](https://mikro-orm.io/) |
| `@automapper/sequelize` | `sequelize()` | Works with TS/ES6 Classes and [Sequelize](https://sequelize.org/) |

:::info

`mikro()` and `sequelize()` are extensions of `classes()`. They call `classes()` with different `MappingStrategyInitializerOptions`

:::

## Logger

AutoMapper TypeScript exposes a logger via the symbol `AutoMapperLogger`. There are 4 log levels:

- `log`
- `warn`
- `info`
- `error`

By default, these log levels are implemented using the `console`'s counterparts in addition to having `[AutoMapper]` as the prefix.

```ts
console.log('some log'); // some log
AutoMapperLogger.log('some log'); // [AutoMapper]: some log
```

### Customization

We can customize `AutoMapperLogger` via `AutoMapperLogger.configure()`

```ts
// in your application's entry point, at the top
AutoMapperLogger.configure({
warn: null, // nullify "warn" completely
});
```

There is one caveat in terms of customizing `AutoMapperLogger` which is **having to** call `AutoMapperLogger.configure()` **as soon as possible** so we need to pick a file that is guaranteed to run **early**, preferably earlier than **decorators**.

- In NestJS, this can be `app.module.ts`
- In Angular, this can be `polyfills.ts`

The caveat stems from the fact that `@AutoMap` decorator from `@automapper/classes` does have a `AutoMapperLogger.warn` call when it fails to infer the type from Reflection. This might not be a desired behavior in certain environments.

0 comments on commit 193d541

Please sign in to comment.