Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Add Custom Code Guide #520

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions docs/getting-started/add-custom-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
id: add-custom-code
title: Adding Custom Code to Your Amplication Service
sidebar_label: Adding Custom Code
slug: /add-custom-code-to-your-service
---

# Adding Custom Code to Your Amplication Service

While Amplication generates a robust, production-ready backend for your application, you'll often need to add custom business logic or additional functionality. This guide explains how Amplication manages custom code alongside generated code, and provides best practices for adding your own code to an Amplication-generated service.

## Prerequisites

Before you begin, make sure you know to:

1. [Create your first service](/first-service/)
2. [Set up entities](/set-up-entities/) for your service
3. [Configure roles and permissions](/configure-roles-and-permissions/)
4. [Add plugins to your service](/add-plugins-service/)
5. [Commit changes and build a new version](/commit-and-build-new-versions/)

## Understanding Custom Code in Amplication

Amplication is designed to allow seamless integration of custom code with generated code through our [Smart Git Sync](/smart-git-sync) feature:

1. All code in your Amplication project can be customized.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of saying this- we can say that custom code can be added to all files or such.

2. Amplication uses a specific folder structure to manage custom and generated code.
3. The `base` folder contains generated files that Amplication updates with each build.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amplication can update the files in the base folder in each build, but also may update generated code in other files

4. Files outside the `base` folder are intended for your custom code and are preserved across builds.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They may not be "preserved" as the generated code can be updated there. So I would say something like-
Files outside the base folder are intended for your custom code.

5. Amplication uses [smart merging](/smart-git-sync) to update your project while preserving your custom code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be more clear here and avoid using the word merging (as we merge nothing but suggest a PR that it can be merged).
We should say that Amplication will always respect the custom code that was created by the user and never overwrite it


:::note
For more a more in-depth explanation, read [Understanding Custom Code in Amplication](/custom-code-overview/)
:::

## How Amplication Handles Custom Code

Amplication preserves your custom code during updates:

1. Base files in the `base` folder are regenerated with each build.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user will get updates in the base file only in case there are relevant changes.
Not sure it's important to mention that the base files (and actually all the generated code) is regenerated every time

2. Non-base files (like `user.service.ts`) are preserved during updates.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again- that's NOT correct. That is exactly the code change that started this PR (amplication/amplication#8895).
All the code and files may be updated due to changes in Amplication platform. However- we know to respect the custom code, and sync it with the generated code (in all files).

3. If necessary, changes to non-base files are required (e.g., removing references to a deleted plugin), Amplication will make these changes automatically while preserving your custom code.

## Adding Custom Code: A Simple Example

Let's walk through a simple example of adding custom code to your service.

### Step 1: Create A New Feature Branch

Ensure that your local repository is up-to-date with the latest Amplication-generated code:

```bash
git checkout main && git merge amplication && git push origin main
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about the 'origin'- what is it?

```

Next, create a new branch from the main branch to make your custom code changes:

```bash
git checkout -b feature/user-full-name
```

### Step 2: Locate the Correct Files

Navigate to your service's `src` folder and find the `user` folder:

```
src
└── user
├── base
│ ├── user.controller.base.ts
│ ├── user.service.base.ts
│ └── ...
├── user.controller.ts
├── user.module.ts
├── user.resolver.ts
└── user.service.ts
```

We'll be modifying `user.service.ts` to add our custom functionality.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need to show also the content of the base file, and say that the API was generated in Amplication and now we are adding not the "functionality" but the business logic or such


### Step 3: Add Custom Logic to the Service

Open `src/user/user.service.ts`. This file extends the base service and is where we'll add our custom method.

```typescript
import { Injectable } from "@nestjs/common";
import { UserServiceBase } from "./base/user.service.base";

@Injectable()
export class UserService extends UserServiceBase {
async getUserFullName(userId: string): Promise<string> {
const user = await this.findOne({ where: { id: userId } });
return `${user.firstName} ${user.lastName}`;
}
}
```

This example adds a simple method to get a user's full name. Note how it uses the `findOne` method from the base service.

### Step 4: Push Your Changes

After adding your custom code, commit the changes to your git repository:

```bash
git add .
git commit -m "Added full name functionality"
git push origin feature/user-full-name
```

After going through any review process, merge the feature branch into your working branch:

```bash
git checkout main && git merge feature/user-full-name && git push origin main
```

## Best Practices for Custom Code

When adding custom code to your Amplication service, keep these best practices in mind:

1. Add custom code to non-base files (e.g., `user.service.ts` instead of `user.service.base.ts`).
2. Use types and interfaces generated by Amplication to ensure type safety.
3. Leverage existing services and utilities provided by Amplication.
4. Document your custom code thoroughly.
5. Create a new branch for significant custom code changes.
6. Regularly pull and merge the latest Amplication-generated code from the `amplication` branch into your working branch.

## Next Steps

Now that you know how to add custom code to your Amplication service, you can:

- Implement complex business logic specific to your application
- Extend generated services with additional methods
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Amplication to add APIs and DTOs?

- Create custom utilities and helpers
- Integrate with external services or APIs
- Implement advanced validation and data processing
3 changes: 2 additions & 1 deletion docs/getting-started/generated-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,5 @@ For Node.js services, the Admin project provides a React application with ready-

## Learn more

- [How to add custom code to your application](/how-to/custom-code)
- [Understanding Custom Code in Amplication](/custom-code-overview/)
- [Add Custom Code To Your Service](/add-custom-code-to-your-service)
4 changes: 2 additions & 2 deletions docs/getting-started/view-generated-code.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
id: view-generated-code
title: Viewing the generated code
sidebar_label: View the generated code
sidebar_label: Code View Explained
slug: /getting-started/view-generated-code
---

# Viewing the Generated Code
# Code View Explained

Use **Code View** to view and explore the generated code. You can see the updated code before it is synced with GitHub or downloaded.

Expand Down
117 changes: 54 additions & 63 deletions docs/how-to/add-custom-code.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,86 @@
---
id: add-custom-code
title: How to add custom code to your services
sidebar_label: Add custom code to your services
slug: /how-to/custom-code
id: custom-code-overview
title: Understanding Custom Code in Amplication
sidebar_label: Understanding Custom Code
slug: /custom-code-overview
pagination_next: getting-started/add-custom-code
---

# Add custom code to your services
# Understanding Custom Code in Amplication
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is the best title that reflects the content of the page. The page is not about understanding custom code, but more about the relations / separation between custom code and generated code in Amplication

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to this comment-
Not sure I understand why we have two separate pages for the custom code. It seems like there is redundancy between the files and the content repeats itself.
I can understand the need to have one page to explain the concepts of the generated code, and custom code, and the other to show an example of updating custom code or such but then- we need to make sure each page has its own "uniqueness" and contribute different things to the subject.
WDYT?


Although your application built with Amplication is fully functional and you can start using it as it was shipped, you probably want to add your core business logic and other functionality to your server.
Amplication allows seamless integration of custom code with generated code, empowering you to add custom business logic while continuing to use Amplication for updating your data model, permissions, roles, and more.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add APIs, and integrations as well


## The Vision
## How It Works

Our vision is that you will be able to add custom code to the server while keeping the ability to work on Amplication to update your data model, change permissions, add roles, and more.
Amplication uses a specific folder structure and smart merging using [Smart Git Sync](/smart-git-sync) to manage custom and generated code:

To do so, Amplication will merge changes via Git, based on pre-defined policies that will allow you to add and update services, controllers, resolvers, and more without losing the link to Amplication. You will have the freedom and power of code while saving time on repetitive tasks with Amplication.
1. All code in your Amplication project can be customized.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments in the other file regarding this part

2. Amplication generates a folder structure that separates base files from non-base files intended for custom code.
3. Updates to your Amplication configuration regenerate base files while preserving your custom code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again- it's not accurate. All the code and files are regenerated (but we don't need to say it), and we create a PR with the required code updates


:::info
This document describes the method to customize the server code only.
### Folder Structure

Customizing the client application (Admin UI) code is not supported. You can use the generated client application as a boilerplate and keep developing it, but Amplication will not be able to merge your code changes with the newly generated code.

In case you decide to customize the client application, it is recommended to first clone the entire **Admin** folder to a separate folder or a separate repository and work on the cloned code instead of the original folder.
:::

## How it works

Your server application is created with a folder structure that allows easy and maintainable customization and development, with a clear separation between customizable code and non-customizable code.

### The 'entity' folder

Each entity has a dedicated folder under the 'src' folder.
For example:
Each entity has a dedicated folder under the `src` folder:

```
└── src
├── customer
├── user
├── project
└── task
├── customer
├── user
├── project
└── task
```

The entity folder contains all the modules and files required to work with a specific entity, i.e. GraphQL resolver, REST API controller, service, and DTOs.

The files are split into two groups:
Within each entity folder, files are split into two groups:

- Base files - the base files are the ones that are automatically generated by Amplication with every change. These files should not be altered or customized as they will be overwritten and the changes will not be preserved. All the base files exist in a separate folder named "base".
1. **Base files**: Located in the 'base' folder, these are automatically generated by Amplication with every build. While these can be modified, changes to these files may be lost in subsequent builds.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"While these can be modified, changes to these files may be lost in subsequent builds." - That's incorrect and let's avoid saying so! We are not losing any code of the user....!


- Customizable files - the customizable files inherit from the base files and they can be customized and will never be overwritten by Amplication. All the customizable files reside directly in the entity folder and can be freely customized and altered.
2. **Non-base files**: These inherit from the base files and are intended for your custom code. They reside directly in the entity folder and your custom code is preserved across builds.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom code is always preserved and respected (whenever it's added)


```
src
└── Customer
├── Base
│ ├── CreateCustomerArgs.ts
│ ├── CustomerFindManyArgs.ts
│ ├── CustomerFindUniqueArgs.ts
│ ├── customer.controller.base.spec.ts
│ ├── customer.controller.base.ts
│ ├── customer.resolver.base.ts
│ ├── customer.service.base.ts
│ ├── customer.ts
│ ├── CustomerCreateInput.ts
│ ├── CustomerUpdateInput.ts
│ ├── CustomerWhereInput.ts
│ ├── CustomerWhereUniqueInput.ts
│ ├── DeleteCustomerArgs.ts
│ └── updateCustomerArgs.ts
├── customer.controller.spec.ts
│ └── ...
├── customer.controller.ts
├── customer.module.ts
├── customer.resolver.ts
└── customer.service.ts

├── customer.service.ts
└── ...
```

### The 'base' folder
## Smart Git Sync

Amplication uses [Smart Git Sync](/smart-git-sync/) to merge changes, preserving your custom code while updating generated parts. This feature:

1. Regenerates base files with each build.
2. Preserves non-base files containing your custom code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again- all custom code is preserved...

3. Makes necessary updates to non-base files (e.g., removing references to deleted plugins) while maintaining your custom code.

## Best Practices for Custom Code

1. Add custom code to non-base files (e.g., `user.service.ts` instead of `user.service.base.ts`).
2. Use types and interfaces generated by Amplication to ensure type safety.
3. Leverage existing services and utilities provided by Amplication.
4. Document your custom code thoroughly.
5. Create a new branch for significant custom code changes.
6. Regularly pull and merge the latest Amplication-generated code into your working branch.

## Handling Conflicts

While Amplication strives to preserve your custom code, conflicts may arise, especially with significant changes to your data model or entity structure. If conflicts occur:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's emphasize that the conflict resolution should take place on 'amplication' branch, and then- merge the result to the main branch


The base folder contains all the base files that are automatically generated by Amplication with every change. These files should not be altered or customized as they will be overwritten and the changes will not be preserved.
1. Amplication will provide clear indications of the conflicting areas.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the known git mechanism

2. You may need to manually resolve these conflicts, merging your custom code with the updated generated code.
3. After resolving conflicts, thoroughly test your application to ensure everything works as expected.

- _entity_.ts - the entity model class with all the model's properties
- _entity_.service.base.ts - the base service that wraps the Prisma client with all the CRUD operations on the entity.
- _entity_.controller.base.ts - the base REST API controller that provides all the CRUD operations on the entity.
- _entity_.resolver.base.ts - the base GraphQL resolver that provides all the queries and mutations on the entity.
- DTOs - Args and Input classes that are used for transferring data to and from the controller and resolver.
## Considerations

## Examples
- While all code can be customized, we recommend focusing custom code in the non-base files for easier maintenance.
- Major changes to your data model or entity structure may require manual updates to your custom code.
- Client-side customization (Admin UI) is supported, but changes may not be automatically merged in future builds. Consider maintaining a separate repository for extensive client-side customizations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove it. I don't think it adds value here


Following are some examples of how to add custom code in different layers of the application.
## Next Steps

The purpose of these examples is to get familiar with the layers' structure and the responsibility of each of the components in the server.
Now that you understand how custom code works in Amplication, you're ready to start adding your own business logic and customizations. For a step-by-step guide, check out our [How To Add Custom Code To Your Service](/add-custom-code-to-your-service) guide.

- [Example: How to add business logic to a service](/custom-code/business-logic)
- [Example: How to add an action to a REST API controller](/custom-code/controller-action)
- [Example: How to add a query to a GraphQL resolver](/custom-code/graphql-query)
Happy coding!
8 changes: 5 additions & 3 deletions sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const sidebars = {
"getting-started/set-up-entities",
"getting-started/configure-roles-and-permissions",
"getting-started/add-plugins-for-service",
"getting-started/commit-changes-and-build-new-versions"
"getting-started/commit-changes-and-build-new-versions",
"getting-started/add-custom-code"
],
},
{
Expand All @@ -25,9 +26,10 @@ const sidebars = {
},
items: [
"getting-started/generated-app",
"getting-started/service-building-new-versions",
// "getting-started/service-building-new-versions",
"how-to/custom-code-overview",
"getting-started/view-generated-code",
"how-to/add-custom-code",
// "how-to/add-custom-code",
"getting-started/authentication",
"concepts/event-driven-architecture",
{
Expand Down
Loading