ChatGPT is like Google + Udemy on steroids. How this affects you?
The release of ChatGPT provoked another avalanche of “AI will replace developers” speculations with many people trying to generate a project from scratch using it. From my perspective, this is a pointless take on this matter. I would rather concentrate on the following idea and its consequences.
AI is a net for catching relevant information in the big ocean human knowledge.
AI can be thought of as a way to filter and organize vast amounts of information and knowledge, making it easier for people to find and access what they need. AI can help us make sense of complex and overwhelming data sets and extract valuable insights and knowledge from them.
At the moment systems like ChatGPT are bringing this capability to a whole new level by providing a human-friendly chat interface that is context aware. And context awareness is really what makes it stand out!!! I will follow up on this just a few lines later.
AI is like Google on steroids + Udemy
Just think of your usual way to write code in the language or framework you are not totally familiar with. It usually starts with these sources of inspiration:
- official documentation
- code samples and tutorials found Google
- StackOverflow
- online courses
And your role here is usually to cherry-pick relevant bits of information and put them in your project in the proper places.
And this is the place where context-aware ChatGPT is replacing you. It is aware of all this information and it can deliver exactly what you need based on your progress with your work. We as humans can’t always express ourselves exactly in one go. We usually start with a simple question and make our requests more complex as we progress. And sometimes we need to go back on our work and improve something we’ve already done. This is where context awareness really shines.
To demonstrate my thoughts above I made up a quick conversation with ChatGPT about creating a simple REST API with NestJS, Mongo, and NATS. The example below is not something sophisticated but it clearly demonstrates the benefits of this capability:
- you don’t need to write your request in full detail from the start
- you can ask for variations (a moment when I ask him to redo using annotations)
- you can go back on the work done and ask for an update based on the changed situation (a moment when I ask him to update the module file after adding NATS)
And during your entire journey, ChatGPT gives you detailed explanations of the code produced, enriching your knowledge.
As a bottom line before you continue to my sample conversation with ChatGPT: don’t take AI as a threat to your position or profession, but rather as an extension of your mind, a valuable companion, and a teacher in your journey to the new exciting goals. Don’t fear AI, embrace it and use it to your advantage.
PS: Some parts of this article were inspired, written, or improved by ChatGPT cause I code better than write texts or communicate with humans 🙂
Example
My replicas are marked as quotations. The rest of the text is ChatGPT output.
please generate a model in TypeScript for Post
Here is a basic model for a Post object in TypeScript:
class Post {
id: number;
title: string;
body: string;
constructor(id: number, title: string, body: string) {
this.id = id;
this.title = title;
this.body = body;
}
}
This model has three properties: id
, title
, and body
. The id
property is a number, the title
property is a string, and the body
property is a string. The constructor
function is used to create new instances of the Post
class and set the initial values for the id
, title
, and body
properties.
You can use this model to create new Post
objects like this:const myPost = new Post(1, ‘My Post Title’, ‘This is the body of my post.’);
I hope this helps! Let me know if you have any other questions.
Can you generate a Mongoose schema for it using NestJS
Sure, here is a Mongoose schema for a Post
object that can be used with NestJS:import * as mongoose from ‘mongoose’;
export const PostSchema = new mongoose.Schema({
id: { type: Number, required: true },
title: { type: String, required: true },
body: { type: String, required: true },
});
This schema defines the structure of a Post
object in a MongoDB database. It has three properties: id
, title
, and body
. The id
property is a number and is required, the title
property is a string and is required, and the body
property is a string and is also required.
To use this schema in your NestJS application, you can import it into your code and pass it to the @nestjs/mongoose
module’s forFeature
function. This will register the schema with Mongoose and allow you to use it in your application. Here is an example:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { PostSchema } from './post.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'Post', schema: PostSchema }]),
],
})
export class PostModule {}
You can then use the Post
schema in your application’s controllers and services to interact with the Post
documents in your MongoDB database.
I hope this helps! Let me know if you have any other questions.
Can you make schema using annotations?
Yes, you can use TypeScript’s decorators to create a schema for a Post
object that can be used with the Mongoose ODM. Here is an example:
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
@Schema()
export class Post extends Document {
@Prop({ required: true })
id: number;
@Prop({ required: true })
title: string;
@Prop({ required: true })
body: string;
}
export const PostSchema = SchemaFactory.createForClass(Post);
This code defines a Post
class that extends the Document
class from the mongoose
module. It uses TypeScript decorators to define the schema for the Post
class. The @Schema
decorator is used to define the overall schema for the class, and the @Prop
decorator is used to define the individual properties of the class.
The PostSchema
constant is then created by calling the SchemaFactory.createForClass
function and passing the Post
class as an argument. This creates a Mongoose schema that can be used with the @nestjs/mongoose
module.
To use this schema in your NestJS application, you can import it into your code and pass it to the @nestjs/mongoose
module’s forFeature
function, just like in the previous example.
I hope this helps! Let me know if you have any other questions.
Can you create controller for it using DTO
Yes, you can use a Data Transfer Object (DTO) to create a controller for a Post
object in NestJS. Here is an example:
import { Controller, Get, Post, Body } from '@nestjs/common';
import { PostDto } from './post.dto';
@Controller('posts')
export class PostController {
@Post()
create(@Body() postDto: PostDto) {
// Insert code here to create a new Post
}
@Get()
findAll() {
// Insert code here to find all Post objects
}
}
This controller defines two methods: create
and findAll
. The create
method is used to create a new Post
object and is decorated with the @Post
decorator. The @Body
decorator is used to extract the PostDto
object from the request body and pass it as an argument to the create
method.
The findAll
method is used to find all Post
objects in the database and is decorated with the @Get
decorator.
The PostDto
class is defined in a separate post.dto.ts
file and looks like this:
import { IsNumber, IsString } from 'class-validator';
export class PostDto {
@IsNumber()
id: number;
@IsString()
title: string;
@IsString()
body: string;
}
This class defines the structure of the data that is expected in a Post
object. It uses TypeScript decorators from the class-validator
module to define the data types and constraints for the properties of the Post
class.
I hope this helps! Let me know if you have any other questions.
Can you generate service?
Yes, you can use a service to manage the data for a Post
object in NestJS. Here is an example:
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Post } from './post.schema';
import { PostDto } from './post.dto';
@Injectable()
export class PostService {
constructor(@InjectModel(Post.name) private readonly postModel: Model<Post>) {}
async create(postDto: PostDto): Promise<Post> {
const createdPost = new this.postModel(postDto);
return createdPost.save();
}
async findAll(): Promise<Post[]> {
return this.postModel.find().exec();
}
}
This service defines two methods: create
and findAll
. The create
method is used to create a new Post
object and save it to the database. It takes a PostDto
object as an argument and uses the postModel
property (which is injected using the @InjectModel
decorator) to create a new Post
object and save it to the database.
The findAll
method is used to find all Post
objects in the database. It uses the postModel
property to query the database and returns an array of Post
objects.
I hope this helps! Let me know if you have any other questions.
Can you update controller to use this service?
Yes, you can update the PostController
to use the PostService
to manage the data for Post
objects. Here is an example:
import { Controller, Get, Post, Body } from '@nestjs/common';
import { PostDto } from './post.dto';
import { PostService } from './post.service';
@Controller('posts')
export class PostController {
constructor(private readonly postService: PostService) {}
@Post()
create(@Body() postDto: PostDto) {
return this.postService.create(postDto);
}
@Get()
findAll() {
return this.postService.findAll();
}
}
In this updated version of the PostController
, the create
and findAll
methods are removed and the PostService
is injected using the constructor. The create
and findAll
methods are then delegated to the PostService
instance, and the controller simply returns the results of those methods.
This separates the business logic for managing Post
objects into the PostService
, making the controller’s code simpler and easier to understand. It also makes the PostController
more testable, since you can easily mock the PostService
when testing the controller.
I hope this helps! Let me know if you have any other questions.
Great! Could you also send a message to NATS once a post is created?
Yes, you can use the NATS messaging system to send a message when a new Post
object is created. Here is an example of how you might update the PostService
to do this:
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Post } from './post.schema';
import { PostDto } from './post.dto';
import { Client, Message } from 'nats';
@Injectable()
export class PostService {
constructor(
@InjectModel(Post.name) private readonly postModel: Model<Post>,
private readonly natsClient: Client,
) {}
async create(postDto: PostDto): Promise<Post> {
const createdPost = new this.postModel(postDto);
const savedPost = await createdPost.save();
// Create a NATS message
const message = JSON.stringify({
id: savedPost.id,
title: savedPost.title,
body: savedPost.body,
});
// Publish the message to the 'posts' NATS subject
this.natsClient.publish('posts', message);
return savedPost;
}
async findAll(): Promise<Post[]> {
return this.postModel.find().exec();
}
}
This updated version of the PostService
injects the NATS client using the constructor. Then, in the create
method, after the Post
object is saved to the database, a NATS message is created and published to the posts
subject.
The NATS message contains the id
, title
, and body
of the Post
object that was just created. Other services or applications that are subscribed to the posts
subject will receive this message and can take action based on the contents of the message.
I hope this helps! Let me know if you have any other questions.
Could you update module file based on these changes?
Yes, you can update the module file to include the PostService
and the NATS client. Here is an example of how the PostModule
might be updated:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { ClientModule } from '@nestjs/microservices';
import { PostController } from './post.controller';
import { PostService } from './post.service';
import { PostSchema } from './post.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'Post', schema: PostSchema }]),
ClientModule.register({
options: {
url: 'nats://localhost:4222',
},
}),
],
controllers: [PostController],
providers: [PostService],
})
export class PostModule {}
This updated version of the PostModule
imports the ClientModule
from the @nestjs/microservices
package and registers the NATS client with the module. It also adds the PostService
to the list of providers for the module.
This allows the PostService
to be injected into the PostController
and the NATS client to be injected into the PostService
.
I hope this helps! Let me know if you have any other questions.