这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
28 changes: 16 additions & 12 deletions examples/with-nestjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@ npx create-turbo@latest -e with-nestjs

## What's inside?

This Turborepo includes the following packages/apps:
This Turborepo includes the following packages & apps:

### Apps and Packages

.
├── apps
│ ├── api # NestJS app (https://nestjs.com).
│ └── web # Next.js app (https://nextjs.org).
└── packages
├── @repo/api # Shared `NestJS` resources.
├── @repo/eslint-config # `eslint` configurations (includes `prettier`)
├── @repo/jest-config # `jest` configurations
├── @repo/typescript-config # `tsconfig.json`s used throughout the monorepo
└── @repo/ui # Shareable stub React component library.
```shell
.
├── apps
│ ├── api # NestJS app (https://nestjs.com).
│ └── web # Next.js app (https://nextjs.org).
└── packages
├── @repo/api # Shared `NestJS` resources.
├── @repo/eslint-config # `eslint` configurations (includes `prettier`)
├── @repo/jest-config # `jest` configurations
├── @repo/typescript-config # `tsconfig.json`s used throughout the monorepo
└── @repo/ui # Shareable stub React component library.
```

Each package and application are 100% [TypeScript](https://www.typescriptlang.org/) safe.
Each package and application are mostly written in [TypeScript](https://www.typescriptlang.org/).

### Utilities

Expand Down Expand Up @@ -110,6 +112,8 @@ npx turbo link

## Useful Links

This example take some inspiration the [with-nextjs](https://github.com/vercel/turborepo/tree/main/examples/with-nextjs) `Turbo` example and [01-cats-app](https://github.com/nestjs/nest/tree/master/sample/01-cats-app) `NestJs` sample.

Learn more about the power of Turborepo:

- [Tasks](https://turborepo.com/docs/crafting-your-repository/running-tasks)
Expand Down
2 changes: 1 addition & 1 deletion examples/with-nestjs/apps/api/.prettierrc.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import config from "@repo/eslint-config/prettier-base";
import config from '@repo/eslint-config/prettier-base';

/** @type {import("prettier").Config} */
export default config;
9 changes: 5 additions & 4 deletions examples/with-nestjs/apps/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ First, run the development server:

```bash
pnpm run dev
# Also works with NPM, YARN, BUN, ...
```

By default, your server will run at [http://localhost:3000](http://localhost:3000). You can use your favorite API platform like [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/) to test your APIs
By default, your server will run at [localhost:3000](http://localhost:3000). You can use your favorite API platform like [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/) to test your APIs

You can start editing the demo **APIs** by modifying [linksService](./src/links/links.service.ts) provider.

### ⚠️ Note about build
### Important Note 🚧

If you plan to only build this app. Please make sure you've built the packages first.
If you plan to `build` or `test` the app. Please make sure to build the `packages/*` first.

## Learn More

To learn more about NestJs, take a look at the following resources:
Learn more about `NestJs` with following resources:

- [Official Documentation](https://docs.nestjs.com) - A progressive Node.js framework for building efficient, reliable and scalable server-side applications.
- [Official NestJS Courses](https://courses.nestjs.com) - Learn everything you need to master NestJS and tackle modern backend applications at any scale.
Expand Down
9 changes: 7 additions & 2 deletions examples/with-nestjs/apps/api/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { nestJsConfig } from "@repo/eslint-config/nest-js";
import { nestJsConfig } from '@repo/eslint-config/nest-js';

/** @type {import("eslint").Linter.Config} */
export default nestJsConfig;
export default [
...nestJsConfig,
{
ignores: ['.prettierrc.mjs', 'eslint.config.mjs'],
},
];
6 changes: 3 additions & 3 deletions examples/with-nestjs/apps/api/src/links/links.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import {
Param,
Delete,
} from '@nestjs/common';
import { LinksService } from './links.service';

import { CreateLinkDto } from '@repo/api/links/dto/create-link.dto';
import { UpdateLinkDto } from '@repo/api/links/dto/update-link.dto';
import type { CreateLinkDto, UpdateLinkDto } from '@repo/api';

import { LinksService } from './links.service';

@Controller('links')
export class LinksController {
Expand Down
39 changes: 14 additions & 25 deletions examples/with-nestjs/apps/api/src/links/links.service.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,48 @@
import { Injectable } from '@nestjs/common';

import { Link } from '@repo/api/links/entities/link.entity';

import { CreateLinkDto } from '@repo/api/links/dto/create-link.dto';
import { UpdateLinkDto } from '@repo/api/links/dto/update-link.dto';
import { Link, CreateLinkDto, UpdateLinkDto } from '@repo/api';

@Injectable()
export class LinksService {
private readonly _links: Link[] = [
{
id: 0,
title: 'Docs',
url: 'https://turborepo.com/docs',
description:
'Find in-depth information about Turborepo features and API.',
title: 'Installation',
url: 'https://turborepo.com/docs/getting-started/installation',
description: 'Get started with Turborepo in a few moments using',
},
{
id: 1,
title: 'Learn',
url: 'https://turborepo.com/docs/handbook',
description: 'Learn more about monorepos with our handbook.',
title: 'Crafting',
url: 'https://turborepo.com/docs/crafting-your-repository',
description: 'Architecting a monorepo is a careful process.',
},
{
id: 2,
title: 'Templates',
url: 'https://turborepo.com/docs/getting-started/from-example',
description:
'Choose from over 15 examples and deploy with a single click.',
},
{
id: 3,
title: 'Deploy',
url: 'https://vercel.com/new',
title: 'Add Repositories',
url: 'https://turborepo.com/docs/getting-started/add-to-existing-repository',
description:
'Instantly deploy your Turborepo to a shareable URL with Vercel.',
'Turborepo can be incrementally adopted in any repository, single or multi-package, to speed up the developer and CI workflows of the repository.',
},
];

create(createLinkDto: CreateLinkDto) {
return `This action adds a new link ${createLinkDto}`;
return `TODO: This action should add a new link '${createLinkDto.title}'`;
}

findAll() {
return this._links;
}

findOne(id: number) {
return `This action returns a #${id} link`;
return `TODO: This action should return a Link with id #${id}`;
}

update(id: number, updateLinkDto: UpdateLinkDto) {
return `This action updates a #${id} link ${updateLinkDto}`;
return `TODO: This action should update a #${id} link ${updateLinkDto.title}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return `TODO: This action should update a #${id} link ${updateLinkDto.title}`;
return `TODO: This action should update a #${id} link`;

The update method accesses updateLinkDto.title directly, but UpdateLinkDto extends PartialType(CreateLinkDto) making all properties optional, which will result in "undefined" appearing in the returned string when title is not provided.

View Details

Analysis

Template string displays "undefined" when optional title not provided in LinksService.update()

What fails: LinksService.update() at line 42 in examples/with-nestjs/apps/api/src/links/links.service.ts accesses updateLinkDto.title in template string, but UpdateLinkDto extends PartialType(CreateLinkDto) making all properties optional

How to reproduce:

// Test with missing title property
const updateLinkDto = { url: "https://example.com" };
const result = `TODO: This action should update a # 

Result: Returns string containing literal text "undefined" when PATCH request omits title field

Expected: Should return clean message without "undefined" text when optional properties are omitted

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is just demonstration purposes. Don't worry about it.

}

remove(id: number) {
return `This action removes a #${id} link`;
return `TODO: This action should remove a #${id} link`;
}
}
2 changes: 2 additions & 0 deletions examples/with-nestjs/apps/api/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { NestFactory } from '@nestjs/core';

import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(3000);
}

Expand Down
15 changes: 4 additions & 11 deletions examples/with-nestjs/apps/web/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started
# Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
# Also works with NPM, YARN, BUN, ...
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Browse [localhost:3001](http://localhost:3001) to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:
Learn more about `Next.js` with the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
Expand Down
49 changes: 47 additions & 2 deletions examples/with-nestjs/apps/web/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Image, { type ImageProps } from 'next/image';
import type { Link } from '@repo/api';
import { Button } from '@repo/ui/button';
import Image, { type ImageProps } from 'next/image';

import styles from './page.module.css';

type Props = Omit<ImageProps, 'src'> & {
Expand All @@ -18,7 +20,26 @@ const ThemeImage = (props: Props) => {
);
};

export default function Home() {
async function getLinks(): Promise<Link[]> {
try {
const res = await fetch('http://localhost:3000/links', {
cache: 'no-store',
});

if (!res.ok) {
throw new Error('Failed to fetch links');
}

return res.json();
} catch (error) {
console.error('Error fetching links:', error);
return [];
}
}

export default async function Home() {
const links = await getLinks();

return (
<div className={styles.page}>
<main className={styles.main}>
Expand Down Expand Up @@ -63,10 +84,34 @@ export default function Home() {
Read our docs
</a>
</div>

<Button appName="web" className={styles.secondary}>
Open alert
</Button>

{links.length > 0 ? (
<div className={styles.ctas}>
{links.map((link) => (
<a
key={link.id}
href={link.url}
target="_blank"
rel="noopener noreferrer"
title={link.description}
className={styles.secondary}
>
{link.title}
</a>
))}
</div>
) : (
<div style={{ color: '#666' }}>
No links available. Make sure the NestJS API is running on port
3000.
</div>
)}
</main>

<footer className={styles.footer}>
<a
href="https://vercel.com/templates?search=turborepo&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
Expand Down
4 changes: 3 additions & 1 deletion examples/with-nestjs/apps/web/next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
allowedDevOrigins: ['http://localhost:3000'],
};

export default nextConfig;
1 change: 1 addition & 0 deletions examples/with-nestjs/apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"react-dom": "^19.1.0"
},
"devDependencies": {
"@repo/api": "workspace:*",
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/node": "^22.15.3",
Expand Down
15 changes: 4 additions & 11 deletions examples/with-nestjs/packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,18 @@
"build": "tsc -b -v",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\""
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"main": "./dist/entry.js",
"types": "./dist/entry.d.ts",
"files": [
"./dist/**"
],
"publishConfig": {
"access": "public"
},
"typesVersions": {
"*": {
"*": [
"src/*"
]
}
},
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js"
"import": "./dist/entry.js",
"require": "./dist/entry.js"
},
"./*": {
"import": "./dist/*.js",
Expand Down
3 changes: 3 additions & 0 deletions examples/with-nestjs/packages/api/src/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { Link } from './links/entities/link.entity';
export { CreateLinkDto } from './links/dto/create-link.dto';
export { UpdateLinkDto } from './links/dto/update-link.dto';
14 changes: 0 additions & 14 deletions examples/with-nestjs/packages/api/src/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export class CreateLinkDto {}
export class CreateLinkDto {
title: string;
url: string;
description: string;
}
10 changes: 5 additions & 5 deletions examples/with-nestjs/packages/jest-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
"publishConfig": {
"access": "public"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"main": "./dist/entry.js",
"types": "./dist/entry.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
"import": "./dist/entry.js",
"require": "./dist/entry.js",
"types": "./dist/entry.d.ts"
},
"./base": {
"import": "./dist/base.js",
Expand Down
Loading