Skip to content

Commit

Permalink
docs: Next.JS Monorepo Guide (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohitxskull authored Nov 2, 2024
1 parent 3fdd339 commit 1ad92d4
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 12 deletions.
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
144 changes: 144 additions & 0 deletions docs/content/docs/next-js.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
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.

You can find an example of it in this [repository](https://github.com/mohitxskull/tuyau-nextjs-adonisjs-stackblitz-demo).

# Monorepo

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

Let's create an empty folder called `acme` and initialize `package.json` with `pnpm` :

```sh
pnpm init
```

Now we need to tell `pnpm` where our apps are located in the folder and for that we need to add a `apps` folder and [`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/*
```
As a result, we'll have a `acme` folder with the following structure:

```
acme
├── package.json
├── apps
└── pnpm-workspace.yaml
```
## 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
└── pnpm-workspace.yaml
```

## 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
└── pnpm-workspace.yaml
```

### 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
}
}
```

### Testing

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

For that add the `typecheck` script to the `package.json` in `./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, add required reference files 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 reference files here.
2 changes: 1 addition & 1 deletion pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
packages:
- packages/*
- playgrounds/*
- docs
- docs

0 comments on commit 1ad92d4

Please sign in to comment.