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: Next.JS Monorepo Guide #13

Merged
merged 4 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
2 changes: 0 additions & 2 deletions docs/content/docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ As you can see, the `api` is not a type, but a real runtime object. You might as
If you're not interested in using the route names in your frontend project, you can simply import the `ApiDefinition` type from the `@tuyau/client` package and ignore the `api` object:

```ts
/// <reference path="../../adonisrc.ts" />

import { createTuyau } from '@tuyau/client'
import type { ApiDefinition } from '@your-monorepo/server/.adonisjs/api'

Expand Down
6 changes: 6 additions & 0 deletions docs/content/docs/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,11 @@
"title": "OpenAPI",
"contentPath": "./openapi.md",
"category": "Guides"
},
{
"permalink": "next-js",
"title": "Next.js",
"contentPath": "/next-js.md",
"category": "Guides"
}
]
27 changes: 18 additions & 9 deletions docs/content/docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,21 @@ And an appropriate `.adonisjs/api.ts` file will be generated in your project.

### Sharing the API definition

The command will generate a file called `.adonisjs/api.ts` in your project. This file will contain the definition of your API. You must export this file in your project to use the client package.
The command will generate a file called `.adonisjs/api.ts` in your project. This file will contain the definition of your API.

Now let's create a file called `.adonisjs/index.ts` in your server workspace :

```ts
/// <reference path="../adonisrc.ts" />

export * from './api.ts'
```

:::warning
We must reference the `adonisrc.ts` file at the top of the file. By doing that, the frontend project will be aware of some types defined in the AdonisJS project.
:::

You must export this file in your project to use the client package.

So, let's say your monorepo structure is like this :

Expand All @@ -56,7 +70,7 @@ apps
server
```

You must export the `.adonisjs/api.ts` file from your server workspace using [subpath exports](https://nodejs.org/api/packages.html#subpath-exports) :
You must export the `.adonisjs/index.ts` file from your server workspace using [subpath exports](https://nodejs.org/api/packages.html#subpath-exports) :

```jsonc
// package.json
Expand All @@ -66,7 +80,7 @@ You must export the `.adonisjs/api.ts` file from your server workspace using [su
"version": "0.0.0",
"private": true,
"exports": {
"./api": "./.adonisjs/api.ts"
"./api": "./.adonisjs/index.ts"
},
}
```
Expand Down Expand Up @@ -101,8 +115,6 @@ import { api } from '@acme/server/api'
Once installed, you must create the tuyau client in your frontend project :

```ts
/// <reference path="../../adonisrc.ts" />

import { createTuyau } from '@tuyau/client'
import { api } from '@your-monorepo/server/.adonisjs/api'

Expand All @@ -114,17 +126,14 @@ export const tuyau = createTuyau({

Multiple things to note here :

- We must reference the `adonisrc.ts` file at the top of the file. By doing that, the frontend project will be aware of some types defined in the AdonisJS project.
- We must import `api` from the `.adonisjs/api` file in your AdonisJS project. You should change the path to match your project structure.
- We must import `api` from the `.adonisjs/index` file in your AdonisJS project. You should change the path to match your project structure.
- As you can see, the `api` is not a type, but a real object. You may ask why ? `api` is an object that contains two things :
- The definition of you API. This is just a type. No runtime code for that.
- The routes of your API. This is a "real" object that contains all the routes with their names and paths. Since we need to map the route names to the paths, we need to have some runtime code for that.

If you are not interested in using the route names in your frontend project, you can just import the `ApiDefinition` type from the `@tuyau/client` package and ignore the `api` object :

```ts
/// <reference path="../../adonisrc.ts" />

import { createTuyau } from '@tuyau/client'
import type { ApiDefinition } from '@your-monorepo/server/.adonisjs/api'

Expand Down
142 changes: 142 additions & 0 deletions docs/content/docs/next-js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
summary: Setup a Monorepo with AdonisJS, Next.js and Tuyau
---

In this guide, we'll be setting up a monorepo with AdonisJS, Next.js and Tuyau.

# Monorepo

We'll be using `pnpm` to manage the dependencies in our monorepo.

Let's create an empty folder called `acme` and initialize `pnpm`:

```sh
pnpm init
```

As a result, we'll have a `acme` folder with the following structure:

```
acme
├── package.json
```

Now we need to tell `pnpm` where our apps are located in the folder and for that we need to add a [`pnpm-workspace.yaml`](https://pnpm.io/workspaces) file as `pnpm` do not support the `workspaces` field in `package.json`:

```yaml
# pnpm-workspace.yaml
packages:
- apps
mohitxskull marked this conversation as resolved.
Show resolved Hide resolved
```

## AdonisJS

Now let's do a `cd` to our `apps` folder and create a adonisjs project:

```sh
pnpm create adonisjs@latest backend
```

For more information on creating an adonisjs project, check out [adonisjs](https://docs.adonisjs.com/guides/getting-started/installation)

```
acme
├── package.json
├── apps
└── apps/backend
```

## Tuyau

For installation of the Tuyau framework, check out the [installation](/docs/installation) guide.

## Next.js

To create a Next.js project, run the following command in `./acme/apps` folder:

```sh
pnpx create-next-app@latest frontend --typescript
```

For more information on creating a Next.js project, check out [create-next-app](https://nextjs.org/docs/getting-started/installation)

```
acme
├── package.json
├── apps
├── apps/backend
└── apps/frontend
```

### Importing the API Definition

To import the API definition from your AdonisJS project generated by the `tuyau:generate` command, you must import the `.adonisjs/index.ts` file in your Next.js project.

For that please follow the [installation](/docs/installation) guide from [here](/docs/installation#sharing-the-api-definition).

### Configuration

As we are directly importing `.ts` files into our Next.js project, we must configure the `tsconfig.json` and `next.config.ts` files.

```ts
// next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
reactStrictMode: true,
transpilePackages: ['@acme/backend'],
webpack: (config) => {
config.resolve.extensionAlias = {
'.js': ['.ts', '.tsx', '.js', '.jsx'],
'.mjs': ['.mts', '.mjs'],
'.cjs': ['.cts', '.cjs'],
};
return config;
},
};

export default nextConfig;
```

Decorators are not enabled by default in TypeScript, So we need to enable them in `tsconfig.json` else we'll see errors during `tsc --noEmit` (typecheck).

```json
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true
}
}
```

---

We have successfully created a monorepo with AdonisJS, Next.js and Tuyau, but let's check if everything is working as expected.

Add the `typecheck` script to the `package.json` of `./acme/apps/frontend`:

```json
// package.json
{
"scripts": {
"typecheck": "tsc --noEmit"
}
}
```

Run the `typecheck` script and see if everything is working as expected.

If you see any errors coming from `../backend` folder, check them and if they are related to missing types, reference them in the `./.adonisjs/index.ts` file like this:

```ts
/// <reference path="../adonisrc.ts" />
/// <reference path="../config/auth.ts" />

export * from './api.js'
```

As your project grows you will need to add more references to the types in the `./.adonisjs/index.ts` file.

---

You can find an example of AdonisJS, Next.js and Tuyau in the [examples](https://github.com/Julien-R44/tuyau/tree/main/examples/nextjs) folder.
mohitxskull marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@
"@tuyau/utils": "workspace:*"
}
},
"prettier": "@julr/tooling-configs/prettier"
"prettier": "@julr/tooling-configs/prettier",
"packageManager": "[email protected]+sha512.22721b3a11f81661ae1ec68ce1a7b879425a1ca5b991c975b074ac220b187ce56c708fe5db69f4c962c989452eee76c82877f4ee80f474cebd61ee13461b6228"

Check failure on line 46 in package.json

View workflow job for this annotation

GitHub Actions / lint

Expected object keys to be in specified order. 'packageManager' should be before 'pnpm'
mohitxskull marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ packages:
- packages/*
- playgrounds/*
- docs
- examples/*
Loading