rakeshsharmaspyne: add nest js cron
GitHub Copilot: Enable Claude Sonnet 3.5 for all clients [object Object]
rakeshsharmaspyne: @GitHubCopilot Enable: "Enable Claude Sonnet 3.5 for all clients"
GitHub Copilot: I'll help you add NestJS cron functionality to your application. You'll need to install the required package first and then modify the service to include a cron job.
- First, install the required package by running this in your terminal:
npm install @nestjs/schedule- Then update your app.module.ts and app.service.ts files:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [ScheduleModule.forRoot()],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
@Cron(CronExpression.EVERY_10_SECONDS)
handleCron() {
console.log('Called every 10 seconds');
}
// Example of custom cron expression
@Cron('45 * * * * *')
handleCustomCron() {
console.log('Called every minute at 45 seconds');
}
}This implementation:
- Adds the
ScheduleModuleto your application - Creates two example cron jobs in the AppService
- One runs every 10 seconds using predefined
CronExpression - Another runs at 45 seconds of every minute using a custom cron expression
You can modify the cron expressions based on your needs. Some common CronExpression options:
EVERY_MINUTEEVERY_HOUREVERY_DAY_AT_MIDNIGHTEVERY_WEEK
For custom cron expressions, the format is:
* * * * * * (seconds minutes hours day-of-month months day-of-week)
rakeshsharmaspyne: docker build -t market-anlayzer:1 . [+] Building 0.1s (1/1) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 2B 0.0s ERROR: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory (base) smaclapotop-28@Rakesh-CM43 market-anlayzer %
GitHub Copilot: The error occurs because the Dockerfile has an incorrect name. It's named .Dockerfile but Docker looks for Dockerfile by default. Here's how to fix it:
- First, rename the file:
mv .Dockerfile Dockerfile- Then, uncomment the build stage in the Dockerfile. Here's the corrected version:
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 1337
CMD ["npm", "run", "start:prod"]- Now you can build the Docker image:
docker build -t market-anlayzer:1 .The error occurred because:
- The Dockerfile was hidden (started with a dot)
- The build stage was commented out, which would cause the
--from=builderinstruction to fail - Docker by default looks for a file named exactly
Dockerfile
After making these changes, the Docker build should work correctly.
rakeshsharmaspyne: [+] Building 2.1s (4/4) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 417B 0.0s => ERROR [internal] load metadata for docker.io/library/builder:latest 2.0s => [internal] load metadata for docker.io/library/node:18-alpine 0.6s => [auth] library/builder:pull token for registry-1.docker.io 0.0s
[internal] load metadata for docker.io/library/builder:latest:
18 | RUN npm install --only=production 19 | 20 | >>> COPY --from=builder /app/dist ./dist 21 | 22 | EXPOSE 1337
ERROR: failed to solve: builder: failed to resolve source metadata for docker.io/library/builder:latest: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
GitHub Copilot: The error occurs because the build stage is commented out but we're trying to copy from it. Let's fix the Dockerfile by uncommenting the build stage and ensuring proper syntax:
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 1337
CMD ["npm", "run", "start:prod"]Now you can build the Docker image again:
docker build -t market-anlayzer:1 .The error occurred because:
- The build stage was commented out
- The
COPY --from=builderinstruction was trying to copy from a non-existent build stage - Docker was attempting to pull a non-existent image called "builder"
This fix:
- Uncomments the build stage
- Creates a proper multi-stage build
- Properly sets up the builder stage with the
AS builderalias - Maintains the production stage that copies the built artifacts from the builder stage
rakeshsharmaspyne: in docker file i am using expose 1337 but in main file using 3000 docker run -d --rm -p 1337:1337 --name market-anlayzer 5b1872e1d20a 0f4e2e18a60436fbe6b8b7cbdefe90e108d8f6822baf428eecc94224aeb8b143
GitHub Copilot: I understand the port mismatch issue. If your NestJS application is running on port 3000 but Docker is exposing port 1337, you'll need to align these. Here's how to fix it:
- First, update your Dockerfile to use port 3000:
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["npm", "run", "start:prod"]- Then, update your Docker run command to map port 3000:
docker run -d --rm -p 3000:3000 --name market-anlayzer market-anlayzer:1Alternatively, if you want to keep the external port as 1337 but your application runs on 3000 internally, use this command:
docker run -d --rm -p 1337:3000 --name market-anlayzer market-anlayzer:1This maps:
- External port 1337 (accessible from host) to
- Internal port 3000 (where your NestJS app runs)
Make sure your NestJS main.ts file is using port 3000:
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}rakeshsharmaspyne: i want to use aws client where should i create it
GitHub Copilot: I'll help you set up the AWS client in your NestJS application. Here's a step-by-step guide:
- First, install the AWS SDK:
npm install @aws-sdk/client-s3- Create a new service for AWS configurations:
import { Injectable } from '@nestjs/common';
import { S3Client } from '@aws-sdk/client-s3';
@Injectable()
export class AwsService {
private readonly s3Client: S3Client;
constructor() {
this.s3Client = new S3Client({
region: process.env.AWS_REGION || 'us-east-1',
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
});
}
getS3Client(): S3Client {
return this.s3Client;
}
}- Create AWS module:
import { Module } from '@nestjs/common';
import { AwsService } from './aws.service';
@Module({
providers: [AwsService],
exports: [AwsService],
})
export class AwsModule {}- Update your AppModule to import the AWS module:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AwsModule } from './aws/aws.module';
@Module({
imports: [
ScheduleModule.forRoot(),
AwsModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}- Now you can use the AWS client in your AppService:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
@Injectable()
export class AppService {
constructor(private readonly awsService: AwsService) {}
getHello(): string {
return 'Hello World!';
}
@Cron(CronExpression.EVERY_10_SECONDS)
async handleCron() {
const s3Client = this.awsService.getS3Client();
// Use s3Client here
console.log('AWS S3 client ready');
}
}- Create a
.envfile in your project root:
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=your_region
Don't forget to:
- Add
.envto your.gitignorefile - Install
@nestjs/configpackage for environment variables support:
npm install @nestjs/configThis structure:
- Keeps AWS configuration isolated and reusable
- Uses dependency injection
- Follows NestJS best practices
- Keeps credentials secure using environment variables
rakeshsharmaspyne: in handleCron i want to run mysql query , where should i create mysql connection
GitHub Copilot: Let me help you set up MySQL connection in your NestJS application.
- First, install the required dependencies:
npm install @nestjs/typeorm typeorm mysql2- Create a database module and service:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DatabaseService } from './database.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 3306,
username: process.env.DB_USERNAME || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'market_analyzer',
entities: [],
synchronize: true,
}),
],
providers: [DatabaseService],
exports: [DatabaseService],
})
export class DatabaseModule {}op-28/githubspyne/market-anlayzer/src/database/database.service.ts
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
@Injectable()
export class DatabaseService {
constructor(private dataSource: DataSource) {}
async executeQuery(query: string, parameters?: any[]): Promise<any> {
return await this.dataSource.query(query, parameters);
}
}- Update your AppModule to import the DatabaseModule:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { DatabaseModule } from './database/database.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ScheduleModule.forRoot(),
DatabaseModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}- Now you can use the database service in your AppService:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
import { DatabaseService } from './database/database.service';
@Injectable()
export class AppService {
constructor(
private readonly awsService: AwsService,
private readonly databaseService: DatabaseService
) {}
getHello(): string {
return 'Hello World!';
}
@Cron(CronExpression.EVERY_10_SECONDS)
async handleCron() {
try {
const result = await this.databaseService.executeQuery(
'SELECT * FROM your_table WHERE condition = ?',
['value']
);
console.log('Query result:', result);
} catch (error) {
console.error('Database query failed:', error);
}
}
}- Create a .env file in your project root:
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=your_username
DB_PASSWORD=your_password
DB_NAME=market_analyzer
Don't forget to:
- Add .env to your .gitignore file
- Install
@nestjs/configif not already installed:
npm install @nestjs/configThis structure:
- Uses TypeORM for database interactions
- Follows NestJS dependency injection patterns
- Keeps database logic isolated in a separate module
- Uses environment variables for configuration
- Provides error handling for database queries
Similar code found with 1 license type
rakeshsharmaspyne: let prompt = { "model": "gpt-4o", "temperature": 0.2, "input": [ { "role": "system", "content": `You are a professional equity research analyst specializing in public company analysis, stock performance tracking, and financial reporting interpretation.
For the given stock/company, prepare a complete analytical summary including:
- Market Prediction — analyst consensus (buy/sell/hold), sentiment trend, and target price range.
- Price Metrics — current market price, 52-week high/low, monthly average, and short-term movement (percentage change).
- Latest Company News — fetch only from verified company or exchange portals (NSE/BSE filings, company investor site) and top-tier financial media (Bloomberg, Moneycontrol, Economic Times, Reuters). Summarize headlines briefly.
- Quarterly Results — include revenue, profit, EPS, YoY and QoQ comparisons with numeric values.
- Major Developments — highlight recent partnerships, management commentary, product launches, or business shifts (last 30 days).
- Statistical Summary — show min, max, average, and percentage growth metrics for key figures (price, revenue, EPS).
- Outlook — provide both short-term and long-term outlook with reasoning (bullish, bearish, or neutral).
Return the data strictly as JSON with the following structure:
{
"Stock Name": string,
"Predictions": {
"Analyst Consensus": string,
"Target Price": number,
"Sentiment": string
},
"Price Metrics": {
"Current Price": number,
"52WeekHigh": number,
"52WeekLow": number,
"MonthlyAverage": number,
"DailyChangePercent": number
},
"Latest News": [
{
"Headline": string,
"Summary": string,
"Source": string,
"Date": string
}
],
"Quarterly Results": {
"Revenue": {
"Current": number,
"YoYChangePercent": number,
"QoQChangePercent": number
},
"NetProfit": {
"Current": number,
"YoYChangePercent": number,
"QoQChangePercent": number
},
"EPS": {
"Current": number,
"YoYChangePercent": number,
"QoQChangePercent": number
}
},
"Recent Developments": [
{
"Title": string,
"Description": string,
"Date": string
}
],
"Statistical Summary": {
"MinValue": number,
"MaxValue": number,
"AverageValue": number,
"GrowthPercent": number
},
"Outlook": {
"ShortTerm": string,
"LongTerm": string,
"Reasoning": string
}
}}, { "role": "user", "content":Stock: ${stock_name}\nFetch all the above information from reliable and verified sources (NSE/BSE filings, company portal, or top financial websites). Return the final result strictly in JSON format.`
}
]
}
i want to add this file where should i add this
GitHub Copilot: I'll help you create a new service for stock analysis. Here's how to structure it:
- First, create a new stock analysis service:
import { Injectable } from '@nestjs/common';
interface StockAnalysis {
StockName: string;
Predictions: {
AnalystConsensus: string;
TargetPrice: number;
Sentiment: string;
};
PriceMetrics: {
CurrentPrice: number;
'52WeekHigh': number;
'52WeekLow': number;
MonthlyAverage: number;
DailyChangePercent: number;
};
LatestNews: Array<{
Headline: string;
Summary: string;
Source: string;
Date: string;
}>;
QuarterlyResults: {
Revenue: {
Current: number;
YoYChangePercent: number;
QoQChangePercent: number;
};
NetProfit: {
Current: number;
YoYChangePercent: number;
QoQChangePercent: number;
};
EPS: {
Current: number;
YoYChangePercent: number;
QoQChangePercent: number;
};
};
RecentDevelopments: Array<{
Title: string;
Description: string;
Date: string;
}>;
StatisticalSummary: {
MinValue: number;
MaxValue: number;
AverageValue: number;
GrowthPercent: number;
};
Outlook: {
ShortTerm: string;
LongTerm: string;
Reasoning: string;
};
}
@Injectable()
export class StockAnalysisService {
async analyzeStock(stockName: string): Promise<StockAnalysis> {
// Implement your stock analysis logic here
// This is where you'll fetch data from various sources
return {
StockName: stockName,
Predictions: {
AnalystConsensus: 'Buy',
TargetPrice: 0,
Sentiment: 'Positive'
},
// ... implement other fields
};
}
}- Create a stock module:
import { Module } from '@nestjs/common';
import { StockAnalysisService } from './stock-analysis.service';
@Module({
providers: [StockAnalysisService],
exports: [StockAnalysisService]
})
export class StockModule {}- Update your AppService to use the stock analysis:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
import { DatabaseService } from './database/database.service';
import { StockAnalysisService } from './stock/stock-analysis.service';
@Injectable()
export class AppService {
constructor(
private readonly awsService: AwsService,
private readonly databaseService: DatabaseService,
private readonly stockAnalysisService: StockAnalysisService
) {}
@Cron(CronExpression.EVERY_10_SECONDS)
async handleCron() {
try {
const stocks = await this.databaseService.executeQuery(
'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
[]
);
for (const stock of stocks) {
const analysis = await this.stockAnalysisService.analyzeStock(stock.name);
console.log('Stock analysis:', analysis);
// Store analysis results or send to AWS
}
} catch (error) {
console.error('Stock analysis failed:', error);
}
}
}- Update your AppModule to include the new StockModule:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { DatabaseModule } from './database/database.module';
import { AwsModule } from './aws/aws.module';
import { StockModule } from './stock/stock.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ScheduleModule.forRoot(),
DatabaseModule,
AwsModule,
StockModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}This structure:
- Separates stock analysis logic into its own service
- Uses TypeScript interfaces for type safety
- Integrates with your existing cron job
- Follows NestJS module organization patterns
- Keeps the code maintainable and testable
Don't forget to implement the actual stock analysis logic in the analyzeStock method of StockAnalysisService according to your data sources and requirements.
rakeshsharmaspyne: this is only prompt which i will gite it to the chatgpt
GitHub Copilot: I'll help you structure this prompt configuration for your NestJS application.
- First, create a config folder and prompt configuration file:
export const STOCK_ANALYSIS_PROMPT = {
model: "gpt-4",
temperature: 0.2,
input: [
{
role: "system",
content: `You are a professional equity research analyst specializing in public company analysis, stock performance tracking, and financial reporting interpretation...`
},
{
role: "user",
content: `Stock: \${stockName}\nFetch all the above information from reliable and verified sources...`
}
]
};- Create a prompt service to handle the template:
import { Injectable } from '@nestjs/common';
import { STOCK_ANALYSIS_PROMPT } from '../config/prompt.config';
@Injectable()
export class PromptService {
generateStockAnalysisPrompt(stockName: string): any {
return {
...STOCK_ANALYSIS_PROMPT,
input: STOCK_ANALYSIS_PROMPT.input.map(input => ({
...input,
content: input.content.replace('${stockName}', stockName)
}))
};
}
}- Update your app service to use the prompt:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
import { DatabaseService } from './database/database.service';
import { PromptService } from './prompt/prompt.service';
@Injectable()
export class AppService {
constructor(
private readonly awsService: AwsService,
private readonly databaseService: DatabaseService,
private readonly promptService: PromptService
) {}
@Cron(CronExpression.EVERY_10_SECONDS)
async handleCron() {
try {
const stocks = await this.databaseService.executeQuery(
'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
[]
);
for (const stock of stocks) {
const prompt = this.promptService.generateStockAnalysisPrompt(stock.name);
// Use prompt with your AI service
console.log('Generated prompt:', prompt);
}
} catch (error) {
console.error('Failed to process stocks:', error);
}
}
}- Create a prompt module:
import { Module } from '@nestjs/common';
import { PromptService } from './prompt.service';
@Module({
providers: [PromptService],
exports: [PromptService]
})
export class PromptModule {}- Update your app module:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PromptModule } from './prompt/prompt.module';
@Module({
imports: [
ScheduleModule.forRoot(),
PromptModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}This structure:
- Separates prompt configuration into its own module
- Makes prompts reusable and maintainable
- Follows NestJS best practices
- Provides type safety with TypeScript
- Allows for easy modification of prompt templates
Remember to install any required dependencies and handle the actual AI service integration separately.
rakeshsharmaspyne: let result = await axios.post('https://api.openai.com/v1/responses', prompt, {
headers: {
'Authorization': Bearer ${sails.config.custom.openaiKey}
}
})
where should i add this
GitHub Copilot: Let's add the OpenAI API call to your PromptService. First, install the required package:
npm install axiosThen modify your PromptService:
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import { STOCK_ANALYSIS_PROMPT } from '../config/prompt.config';
@Injectable()
export class PromptService {
constructor(private configService: ConfigService) {}
generateStockAnalysisPrompt(stockName: string): any {
return {
...STOCK_ANALYSIS_PROMPT,
input: STOCK_ANALYSIS_PROMPT.input.map(input => ({
...input,
content: input.content.replace('${stockName}', stockName)
}))
};
}
async getOpenAIResponse(prompt: any): Promise<any> {
try {
const result = await axios.post('https://api.openai.com/v1/responses', prompt, {
headers: {
'Authorization': `Bearer ${this.configService.get('OPENAI_API_KEY')}`,
'Content-Type': 'application/json'
}
});
return result.data;
} catch (error) {
console.error('OpenAI API call failed:', error.response?.data || error.message);
throw error;
}
}
async analyzeStock(stockName: string): Promise<any> {
const prompt = this.generateStockAnalysisPrompt(stockName);
return await this.getOpenAIResponse(prompt);
}
}Add environment variable to your .env file:
OPENAI_API_KEY=your_openai_api_key_here
Make sure to install @nestjs/config if not already installed:
npm install @nestjs/configUpdate your AppModule to use ConfigModule:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PromptModule } from './prompt/prompt.module';
@Module({
imports: [
ConfigModule.forRoot(),
ScheduleModule.forRoot(),
PromptModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Now you can use the updated service in your AppService:
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
try {
const stocks = await this.databaseService.executeQuery(
'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
[]
);
for (const stock of stocks) {
const analysis = await this.promptService.analyzeStock(stock.name);
console.log('Stock analysis:', analysis);
}
} catch (error) {
console.error('Analysis failed:', error);
}
}This implementation:
- Adds proper error handling
- Uses environment variables for API key
- Separates API call logic
- Provides a clean interface for stock analysis
- Follows NestJS best practices
rakeshsharmaspyne: now i want to use mongodb
GitHub Copilot: I'll help you modify the DatabaseService to use MongoDB instead of TypeORM. First, install the required packages:
npm install @nestjs/mongoose mongooseThen update your DatabaseService:
import { Injectable } from '@nestjs/common';
import { InjectConnection } from '@nestjs/mongoose';
import { Connection } from 'mongoose';
@Injectable()
export class DatabaseService {
constructor(@InjectConnection() private connection: Connection) {}
async executeQuery(collection: string, query: any): Promise<any> {
try {
const result = await this.connection
.collection(collection)
.find(query)
.toArray();
return result;
} catch (error) {
console.error('MongoDB query failed:', error);
throw error;
}
}
async insertDocument(collection: string, document: any): Promise<any> {
try {
return await this.connection
.collection(collection)
.insertOne(document);
} catch (error) {
console.error('MongoDB insert failed:', error);
throw error;
}
}
}Create a new Database Module:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DatabaseService } from './database.service';
@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/market_analyzer', {
useNewUrlParser: true,
useUnifiedTopology: true,
}),
],
providers: [DatabaseService],
exports: [DatabaseService],
})
export class DatabaseModule {}Update your AppService to use MongoDB queries:
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
try {
const result = await this.databaseService.executeQuery('stock_cron_config', {
is_active: 1,
next_run_at: { $lte: new Date() }
});
// ...rest of your code...
} catch (error) {
console.error('Database query failed:', error);
}
}Add MongoDB connection details to your .env file:
MONGODB_URI=mongodb://localhost:27017/market_analyzer
This implementation:
- Uses Mongoose for MongoDB integration
- Provides basic query and insert operations
- Includes error handling
- Uses environment variables for configuration
- Follows NestJS best practices for MongoDB integration
Make sure MongoDB is installed and running on your Mac. You can install it using Homebrew:
brew install mongodb-community
brew services start mongodb-communityrakeshsharmaspyne: Object literal may only specify known properties, and 'useNewUrlParser' does not exist in type 'MongooseModuleOptions'.ts(2353)
GitHub Copilot: The error occurs because recent versions of Mongoose have deprecated some options. Let's update the MongoDB connection options in your database module:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DatabaseService } from './database.service';
@Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017/market_analyzer'),
],
providers: [DatabaseService],
exports: [DatabaseService],
})
export class DatabaseModule {}For better configuration management, you can also use environment variables:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseService } from './database.service';
@Module({
imports: [
MongooseModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
uri: configService.get<string>('MONGODB_URI'),
}),
inject: [ConfigService],
}),
],
providers: [DatabaseService],
exports: [DatabaseService],
})
export class DatabaseModule {}Then add to your .env file:
MONGODB_URI=mongodb://localhost:27017/market_analyzer
The changes:
- Removed deprecated options
- Added ConfigModule support for environment variables
- Uses async configuration
- Follows current Mongoose best practices
Make sure you have installed the required packages:
npm install @nestjs/config @nestjs/mongoose mongooseSimilar code found with 1 license type
rakeshsharmaspyne: i have create stock schema with stock service i want to use in app.service.ts
GitHub Copilot: I'll help you integrate the StockService into your AppService. Here's how to do it:
- First, make sure your StockModule exports the StockService:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { StockService } from './stock.service';
import { Stock, StockSchema } from './schemas/stock.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: Stock.name, schema: StockSchema }])
],
providers: [StockService],
exports: [StockService]
})
export class StockModule {}- Update your AppService to use the StockService:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { MySQLDatabaseService } from './database/mysql/mysql.service';
import { MongoDatabaseService } from './database/mongo/mongo.service';
import { PromptService } from './prompt/prompt.service';
import { StockService } from './stock/stock.service';
@Injectable()
export class AppService {
constructor(
private readonly mysqlDB: MySQLDatabaseService,
private readonly mongoDB: MongoDatabaseService,
private readonly promptService: PromptService,
private readonly stockService: StockService
) {}
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
try {
const result = await this.mysqlDB.executeQuery(
'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
[]
);
const analysis = await this.promptService.analyzeStock(result[0].name);
let responseText = analysis?.output?.[0]?.content?.[0]?.text;
let cleanJson = responseText.replace(/```json\n|```/g, '');
let jsonData = JSON.parse(cleanJson);
// Save the analysis to MongoDB
await this.stockService.createStock({
name: result[0].name,
analysis: jsonData,
createdAt: new Date()
});
console.log('Query result:', result);
console.log('Generated Prompt:', jsonData);
} catch (error) {
console.error('Analysis failed:', error);
}
}
}- Update your AppModule to import the StockModule:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { StockModule } from './stock/stock.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ScheduleModule.forRoot(),
StockModule,
// ...other modules
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}This setup:
- Injects the StockService into AppService
- Uses the createStock method to save analysis results
- Properly structures the modules and dependencies
- Maintains separation of concerns
- Follows NestJS dependency injection patterns
Now your cron job will:
- Fetch stocks from MySQL
- Get analysis from the prompt service
- Save the results to MongoDB using the StockService
rakeshsharmaspyne: also add below information while createing entry in mongodb export class Stock { @Prop({ required: true, unique: true }) stockId: string;
@Prop({ required: true }) stockName: string;
@Prop({ required: true, enum: ['mid', 'large', 'small'], default: 'mid' }) stockSize: 'mid' | 'large' | 'small';
@Prop() stockDescription?: string;
// ✅ Added fields @Prop({ required: true, unique: true, uppercase: true }) symbol: string; // e.g., "TCS", "INFY", "WIPRO"
@Prop({ required: true, enum: ['NSE', 'BSE'], default: 'NSE' }) exchange: 'NSE' | 'BSE';
@Prop({ type: Number, required: true }) currentPrice: number; // current market price
@Prop({ type: Number, default: 0 }) changePercent?: number; // percentage change
@Prop({ type: Number, default: 0 }) volume?: number; // traded volume
@Prop({ type: String }) sector?: string; // IT, Banking, Pharma, etc.
@Prop({ type: Boolean, default: true }) isActive: boolean;
@Prop({ type: Date }) lastUpdatedAt?: Date; }
GitHub Copilot: I'll help you update the AppService to include all the required stock information when creating an entry in MongoDB. Here's the modified code:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { MySQLDatabaseService } from './database/mysql/mysql.service';
import { MongoDatabaseService } from './database/mongo/mongo.service';
import { PromptService } from './prompt/prompt.service';
import { StockService } from './stock/stock.service';
@Injectable()
export class AppService {
constructor(
private readonly mysqlDB: MySQLDatabaseService,
private readonly mongoDB: MongoDatabaseService,
private readonly promptService: PromptService,
private readonly stockService: StockService
) {}
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
try {
const result = await this.mysqlDB.executeQuery(
'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
[]
);
const analysis = await this.promptService.analyzeStock(result[0].name);
let responseText = analysis?.output?.[0]?.content?.[0]?.text;
let cleanJson = responseText.replace(/```json\n|```/g, '');
let jsonData = JSON.parse(cleanJson);
// Create stock entry with all required fields
await this.stockService.createStock({
stockName: result[0].name,
stockSize: 'mid', // You might want to determine this based on market cap
stockDescription: jsonData.Outlook.Reasoning,
symbol: result[0].symbol.toUpperCase(),
exchange: 'NSE', // Or get from your configuration
currentPrice: jsonData.PriceMetrics.CurrentPrice,
changePercent: jsonData.PriceMetrics.DailyChangePercent,
volume: jsonData.PriceMetrics.Volume || 0,
sector: result[0].sector || 'Unknown',
isActive: true,
lastUpdatedAt: new Date(),
analysis: jsonData // Additional analysis data
});
console.log('Stock analysis saved successfully');
} catch (error) {
console.error('Analysis failed:', error);
}
}
}You'll also need to update your MySQL query to include the additional fields:
SELECT
name,
symbol,
sector,
is_active,
next_run_at
FROM stock_cron_config
WHERE is_active = 1
AND next_run_at <= NOW()This implementation:
- Includes all fields from your Stock schema
- Sets default values where appropriate
- Handles the timestamp automatically
- Maps the AI analysis data to the correct fields
- Maintains data integrity with required fields
- Uses uppercase for stock symbols
- Includes error handling
Make sure your MySQL database table stock_cron_config has the corresponding columns to provide this information.
rakeshsharmaspyne: ERROR [ExceptionHandler] UnknownDependenciesException [Error]: Nest can't resolve dependencies of the AppService (MySQLDatabaseService, MongoDatabaseService, PromptService, ?). Please make sure that the argument StockService at index [3] is available in the AppModule context.
Potential solutions:
- Is AppModule a valid NestJS module?
- If StockService is a provider, is it part of the current AppModule?
- If StockService is exported from a separate @Module, is that module imported within AppModule? @Module({ imports: [ /* the Module containing StockService */ ] })
For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errors at Injector.lookupComponentInParentModules (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:286:19) at process.processTicksAndRejections (node:internal/process/task_queues:105:5) at async resolveParam (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:141:38) at async Promise.all (index 3) at async Injector.resolveConstructorParams (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:169:27) at async Injector.loadInstance (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:75:13) at async Injector.loadProvider (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:103:9) at async /Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/instance-loader.js:56:13 at async Promise.all (index 3) at async InstanceLoader.createInstancesOfProviders (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/instance-loader.js:55:9) { type: 'AppService', context: { index: 3, dependencies: [ [class MySQLDatabaseService], [class MongoDatabaseService], [class PromptService], [class StockService] ], name: [class StockService] }, metadata: { id: '3d077ecdcb79b4e6d62dd' }, moduleRef: { id: 'b64b8033453f217376b18' } }
GitHub Copilot: The error occurs because the StockService is not properly imported in the AppModule. Let's fix this by updating the module configurations:
- First, ensure your
StockModuleis properly configured:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { StockService } from './stock.service';
import { Stock, StockSchema } from './schemas/stock.schema';
@Module({
imports: [
MongooseModule.forFeature([{ name: Stock.name, schema: StockSchema }])
],
providers: [StockService],
exports: [StockService] // Make sure to export the service
})
export class StockModule {}- Then update your
AppModuleto import all required modules:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { StockModule } from './stock/stock.module';
import { MySQLDatabaseModule } from './database/mysql/mysql.module';
import { MongoDatabaseModule } from './database/mongo/mongo.module';
import { PromptModule } from './prompt/prompt.module';
@Module({
imports: [
ConfigModule.forRoot(),
MongooseModule.forRoot(process.env.MONGODB_URI),
ScheduleModule.forRoot(),
StockModule,
MySQLDatabaseModule,
MongoDatabaseModule,
PromptModule
],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}- Make sure all your service modules export their services:
@Module({
providers: [MySQLDatabaseService],
exports: [MySQLDatabaseService]
})@Module({
providers: [MongoDatabaseService],
exports: [MongoDatabaseService]
})@Module({
providers: [PromptService],
exports: [PromptService]
})This will:
- Properly export all services
- Import all required modules in AppModule
- Set up dependency injection correctly
- Resolve the unknown dependencies error
Make sure you have all environment variables set up in your .env file:
MONGODB_URI=mongodb://localhost:27017/market_analyzer
rakeshsharmaspyne: Error creating stock: Error: Stock validation failed: symbol: Path symbol is required.
at ValidationError.inspect (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/error/validation.js:52:26)
at formatValue (node:internal/util/inspect:877:19)
at inspect (node:internal/util/inspect:404:10)
at formatWithOptionsInternal (node:internal/util/inspect:2402:40)
at formatWithOptions (node:internal/util/inspect:2264:10)
at console.value (node:internal/console/constructor:336:14)
at console.log (node:internal/console/constructor:384:61)
at StockService.createStock (/Users/smaclapotop-28/githubspyne/market-anlayzer/src/stock/stock.service.ts:23:21)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async AppService.handleCron (/Users/smaclapotop-28/githubspyne/market-anlayzer/src/app.service.ts:42:6) {
errors: {
symbol: ValidatorError: Path symbol is required.
at validate (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/schemaType.js:1417:13)
at SchemaType.doValidate (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/schemaType.js:1401:7)
at /Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/document.js:3115:18
at process.processTicksAndRejections (node:internal/process/task_queues:85:11) {
properties: [Object],
kind: 'required',
path: 'symbol',
value: undefined,
reason: undefined,
Symbol(mongoose#validatorError): true
}
},
_message: 'Stock validation failed'
}
GitHub Copilot: The error occurs because the symbol field is required in your Stock schema but it's not being provided when creating a new stock. Let's modify the AppService to ensure all required fields are included:
@Injectable()
export class AppService {
// ...existing code...
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
try {
const result = await this.mysqlDB.executeQuery(
'SELECT name, symbol, sector FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW() LIMIT 1',
[]
);
if (!result || !result[0] || !result[0].symbol) {
console.error('No valid stock data found or missing symbol');
return;
}
const analysis = await this.promptService.analyzeStock(result[0].name);
let responseText = analysis?.output?.[0]?.content?.[0]?.text;
let cleanJson = responseText.replace(/```json\n|```/g, '');
let jsonData = JSON.parse(cleanJson);
const stockData = {
stockName: result[0].name,
stockSize: 'mid',
stockDescription: jsonData?.Outlook?.Reasoning || 'No description available',
symbol: result[0].symbol.toUpperCase(), // Ensure symbol is provided and uppercase
exchange: 'NSE',
currentPrice: jsonData?.PriceMetrics?.CurrentPrice || 0,
changePercent: jsonData?.PriceMetrics?.DailyChangePercent || 0,
volume: jsonData?.PriceMetrics?.Volume || 0,
sector: result[0].sector || 'Unknown',
isActive: true,
lastUpdatedAt: new Date(),
analysis: jsonData
};
console.log('Creating stock with data:', stockData);
const savedStock = await this.stockService.createStock(stockData);
console.log('Stock created successfully:', savedStock);
} catch (error) {
console.error('Analysis failed:', error);
}
}
}Key changes made:
- Added validation for required fields
- Updated SQL query to explicitly select needed fields
- Added error handling for missing data
- Added logging to track data flow
- Ensured symbol is provided and uppercase
- Added default values for optional fields
Also, make sure your MySQL table has the correct columns:
CREATE TABLE `stock_cron_config` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`frequency_minutes` int NOT NULL,
`last_run_at` datetime DEFAULT NULL,
`next_run_at` datetime GENERATED ALWAYS AS ((case when (`last_run_at` is not null) then (`last_run_at` + interval `frequency_minutes` minute) else NULL end)) STORED,
`is_active` tinyint(1) DEFAULT '1',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)rakeshsharmaspyne: optimize app.service.ts code
GitHub Copilot: ````typescript import { Injectable, Logger } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; import { MySQLDatabaseService } from './database/mysql/mysql.service'; import { MongoDatabaseService } from './database/mongo/mongo.service'; import { PromptService } from './prompt/prompt.service'; import { StockService } from './stock/stock.service';
@Injectable() export class AppService { private readonly logger = new Logger(AppService.name);
constructor( private readonly mysqlDB: MySQLDatabaseService, private readonly mongoDB: MongoDatabaseService, private readonly promptService: PromptService, private readonly stockService: StockService ) {}
getHello(): string { return 'Hello World!'; }
private safeParseAnalysis(text: string): any | null {
if (!text) return null;
try {
const clean = text.replace(/json\n|/g, '');
return JSON.parse(clean);
} catch (err) {
this.logger.warn('Failed to parse analysis JSON', err as any);
return null;
}
}
private buildStockPayload(row: any, jsonData: any) { return { stockName: row.name, stockSize: 'mid', stockDescription: jsonData?.Outlook?.Reasoning || 'No description available', symbol: (row.symbol || row.symbolName || '').toUpperCase(), exchange: row.exchange || 'NSE', currentPrice: jsonData?.PriceMetrics?.CurrentPrice || 0, changePercent: jsonData?.PriceMetrics?.DailyChangePercent || 0, volume: jsonData?.PriceMetrics?.Volume || 0, sector: row.sector || jsonData?.Sector || 'Unknown', isActive: true, lastUpdatedAt: new Date(), analysis: jsonData || {} }; }
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron(): Promise {
try {
const rows = await this.mysqlDB.executeQuery(
SELECT name, symbol, sector, IFNULL(exchange, 'NSE') as exchange FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW() LIMIT 10,
[]
);
if (!rows || rows.length === 0) {
this.logger.debug('No stocks to process');
return;
}
await Promise.all(
rows.map(async (row: any) => {
if (!row?.symbol) {
this.logger.warn(`Skipping row with missing symbol: ${JSON.stringify(row)}`);
return;
}
try {
const analysisResp = await this.promptService.analyzeStock(row.name);
const responseText = analysisResp?.output?.[0]?.content?.[0]?.text;
const jsonData = this.safeParseAnalysis(responseText);
if (!jsonData) {
this.logger.warn(`No valid analysis for ${row.name}`);
return;
}
const payload = this.buildStockPayload(row, jsonData);
const saved = await this.stockService.createStock(payload);
if (saved) {
this.logger.log(`Saved analysis for ${payload.symbol}`);
} else {
this.logger.error(`Failed to save stock for ${payload.symbol}`);
}
} catch (err) {
this.logger.error(`Error processing stock ${row.name}`, err as any);
}
})
);
} catch (error) {
this.logger.error('handleCron failed', error as any);
}
}
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) async dailyStockAnalysis(): Promise { try { const analysisResp = await this.promptService.dailyStockAnalysis(); const responseText = analysisResp?.output?.[0]?.content?.[0]?.text; const jsonData = this.safeParseAnalysis(responseText); if (!jsonData) { this.logger.warn('dailyStockAnalysis returned invalid JSON'); return; }
const payload = {
stockName: jsonData.StockName || 'Unknown',
stockSize: 'mid',
stockDescription: jsonData?.Outlook?.Reasoning || 'No description available',
symbol: (jsonData?.Symbol || jsonData?.StockName || '').toUpperCase(),
exchange: 'NSE',
currentPrice: jsonData?.PriceMetrics?.CurrentPrice || 0,
changePercent: jsonData?.PriceMetrics?.DailyChangePercent || 0,
volume: jsonData?.PriceMetrics?.Volume || 0,
sector: jsonData?.Sector || 'Unknown',
isActive: true,
lastUpdatedAt: new Date(),
analysis: jsonData
};
const saved = await this.stockService.createStock(payload);
if (saved) this.logger.log(`dailyStockAnalysis saved ${payload.symbol}`);
} catch (error) {
this.logger.error('dailyStockAnalysis failed', error as any);
}
} }
rakeshsharmaspyne: i am getting multiple stocks in
jsonData.Stocks
i want to bulk push in stockservice.createStock
jsonData.Stocks
GitHub Copilot: ````typescript
// ...existing code...
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Stock } from './schemas/stock.schema'
import { v4 as uuidv4 } from 'uuid';
@Injectable()
export class StockService {
private readonly logger = new Logger(StockService.name);
constructor(
@InjectModel(Stock.name) private stockModel: Model<Stock>
) {}
async createStock(body): Promise<Stock | null> {
const stockId = uuidv4();
try {
const stock = new this.stockModel({ ...body, stockId });
const savedStock = await stock.save();
// this.logger.log(`Successfully created stock with ID: ${savedStock.id}`);
return savedStock;
} catch (error) {
this.logger.error('Error creating stock:', error);
return null;
}
}
// Added bulk insert method
async createStocksBulk(bodies: Partial<Stock>[]): Promise<{ insertedCount: number; insertedDocs: any[]; errors?: any[] }> {
if (!Array.isArray(bodies) || bodies.length === 0) {
return { insertedCount: 0, insertedDocs: [] };
}
const docs = bodies.map(b => ({
stockId: b.stockId || uuidv4(),
stockName: b.stockName,
stockSize: b.stockSize || 'mid',
stockDescription: b.stockDescription || b?.analysis?.Outlook?.Reasoning || 'No description available',
symbol: (b.symbol || b.stockName || '').toUpperCase(),
exchange: b.exchange || 'NSE',
currentPrice: (b.currentPrice ?? 0),
changePercent: (b.changePercent ?? 0),
volume: (b.volume ?? 0),
sector: b.sector || 'Unknown',
isActive: (typeof b.isActive === 'boolean') ? b.isActive : true,
lastUpdatedAt: b.lastUpdatedAt || new Date(),
analysis: b.analysis || {}
}));
try {
const inserted = await this.stockModel.insertMany(docs, { ordered: false });
return { insertedCount: inserted.length, insertedDocs: inserted };
} catch (err: any) {
// insertMany may throw on duplicates; it may still have insertedDocs / writeErrors
const insertedDocs = err?.insertedDocs ?? err?.result?.insertedIds ?? [];
const writeErrors = err?.writeErrors ?? [err];
this.logger.warn('Bulk insert had errors, partial success', writeErrors);
return { insertedCount: Array.isArray(insertedDocs) ? insertedDocs.length : 0, insertedDocs: insertedDocs, errors: writeErrors };
}
}
}
// ...existing code...
// ...existing code...
@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron(): Promise<void> {
try {
const rows = await this.mysqlDB.executeQuery(
`SELECT name, symbol, sector, IFNULL(exchange, 'NSE') as exchange
FROM stock_cron_config
WHERE is_active = 1 AND next_run_at <= NOW()
LIMIT 10`,
[]
);
if (!rows || rows.length === 0) {
this.logger.debug('No stocks to process');
return;
}
await Promise.all(
rows.map(async (row: any) => {
if (!row?.symbol) {
this.logger.warn(`Skipping row with missing symbol: ${JSON.stringify(row)}`);
return;
}
try {
const analysisResp = await this.promptService.analyzeStock(row.name);
const responseText = analysisResp?.output?.[0]?.content?.[0]?.text;
const jsonData = this.safeParseAnalysis(responseText);
if (!jsonData) {
this.logger.warn(`No valid analysis for ${row.name}`);
return;
}
// If analysis contains multiple stocks, bulk insert them
if (Array.isArray(jsonData.Stocks) && jsonData.Stocks.length > 0) {
const payloads = jsonData.Stocks.map((s: any) => ({
stockName: s['Stock Name'] || s.StockName || row.name,
stockSize: s.stockSize || 'mid',
stockDescription: s.stockDescription || s?.Outlook?.Reasoning || 'No description available',
symbol: (s.Symbol || s.symbol || s['Stock Name'] || row.symbol).toUpperCase(),
exchange: s.Exchange || row.exchange || 'NSE',
currentPrice: s?.PriceMetrics?.CurrentPrice || 0,
changePercent: s?.PriceMetrics?.DailyChangePercent || 0,
volume: s?.PriceMetrics?.Volume || 0,
sector: s.Sector || row.sector || 'Unknown',
isActive: true,
lastUpdatedAt: new Date(),
analysis: s
}));
const result = await this.stockService.createStocksBulk(payloads);
this.logger.log(`Bulk insert result for ${row.symbol}: inserted ${result.insertedCount}`);
} else {
// Single stock fallback (existing flow)
const payload = this.buildStockPayload(row, jsonData);
const saved = await this.stockService.createStock(payload);
if (saved) {
this.logger.log(`Saved analysis for ${payload.symbol}`);
} else {
this.logger.error(`Failed to save stock for ${payload.symbol}`);
}
}
} catch (err) {
this.logger.error(`Error processing stock ${row.name}`, err as any);
}
})
);
} catch (error) {
this.logger.error('handleCron failed', error as any);
}
}
// ...existing code...Notes:
- Added StockService.createStocksBulk using insertMany with ordered: false to continue on duplicates.
- AppService now checks jsonData.Stocks and prepares payloads to call createStocksBulk.
- Payload mapping ensures required fields (symbol, stockName, currentPrice, etc.) are present/defaulted.
- Logs partial successes and errors; adjust according to your deduplication/upsert needs.
rakeshsharmaspyne: i have create process.env.DB_HOST but .env is not used why
GitHub Copilot: To use environment variables from .env file in NestJS, you need to set up the ConfigModule. Here's how to fix it:
- First, install the config package if not already installed:
npm install @nestjs/config- Update your MySQL module to use ConfigModule and ConfigService:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MySQLDatabaseService } from './mysql.service';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'mysql',
host: configService.get('DB_HOST') || 'localhost',
port: configService.get('DB_PORT') || 3307,
username: configService.get('DB_USERNAME') || 'root',
password: configService.get('DB_PASSWORD') || '1234',
database: configService.get('DB_NAME') || 'market_analyzer',
entities: [],
synchronize: true,
}),
}),
],
providers: [MySQLDatabaseService],
exports: [MySQLDatabaseService],
})
export class MySQLDatabaseModule {}- Create or update your .env file in the project root:
DB_HOST=localhost
DB_PORT=3307
DB_USERNAME=root
DB_PASSWORD=1234
DB_NAME=market_analyzer
- Make sure .env is in your .gitignore:
# Environment variables
.env
.env.*
- Update your main
AppModuleto import ConfigModule globally:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MySQLDatabaseModule } from './database/mysql/mysql.module';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
MySQLDatabaseModule,
// ...other modules
],
// ...rest of module config
})
export class AppModule {}These changes will:
- Load environment variables from .env file
- Make ConfigModule available globally
- Use ConfigService to access environment variables
- Provide type safety for configuration
- Allow for different environments (development, production, etc.)
rakeshsharmaspyne: create readme file for this project
GitHub Copilot: # Market Analyzer
A NestJS application for analyzing stock market data using AI-powered insights and managing stock information across MySQL and MongoDB databases.
- Real-time stock analysis using OpenAI GPT
- Dual database architecture (MySQL + MongoDB)
- Automated data collection via cron jobs
- REST API endpoints for stock data
- Environment-based configuration
- TypeScript support
- Node.js (v18 or later)
- MySQL (v8.0 or later)
- MongoDB (v6.0 or later)
- OpenAI API key
# Clone the repository
git clone <repository-url>
cd market-analyzer
# Install dependencies
npm installCreate a .env file in the project root:
# Database Configuration
DB_HOST=localhost
DB_PORT=3307
DB_USERNAME=root
DB_PASSWORD=your_password
DB_NAME=market_analyzer
# MongoDB Configuration
MONGODB_URI=mongodb://localhost:27017/market_analyzer
# OpenAI Configuration
OPENAI_API_KEY=your_openai_api_key
-- Create MySQL database and tables
CREATE DATABASE IF NOT EXISTS market_analyzer;
USE market_analyzer;
CREATE TABLE `stock_cron_config` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`frequency_minutes` int NOT NULL,
`last_run_at` datetime DEFAULT NULL,
`next_run_at` datetime GENERATED ALWAYS AS ((case when (`last_run_at` is not null) then (`last_run_at` + interval `frequency_minutes` minute) else NULL end)) STORED,
`is_active` tinyint(1) DEFAULT '1',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)# Development mode
npm run start:dev
# Production mode
npm run build
npm run start:prod# Build Docker image
docker build -t market-analyzer:1.0 .
# Run container
docker run -d -p 3000:3000 --name market-analyzer market-analyzer:1.0market-analyzer/
├── src/
│ ├── app.module.ts
│ ├── app.service.ts
│ ├── database/
│ │ ├── mysql/
│ │ └── mongo/
│ ├── stock/
│ │ ├── schemas/
│ │ └── services/
│ └── prompt/
├── test/
├── Dockerfile
└── package.json
GET /api/stocks // Get all stocks
POST /api/stocks // Create new stock
GET /api/stocks/:symbol // Get stock by symbolEVERY_30_SECONDS: Fetches and analyzes configured stocksEVERY_3_HOURS: Updates stock dataEVERY_DAY_AT_MIDNIGHT: Performs daily analysis
# Unit tests
npm run test
# E2E tests
npm run test:e2e| Variable | Description | Default |
|---|---|---|
| DB_HOST | MySQL host | localhost |
| DB_PORT | MySQL port | 3307 |
| DB_USERNAME | MySQL username | root |
| DB_PASSWORD | MySQL password | - |
| DB_NAME | MySQL database name | market_analyzer |
| MONGODB_URI | MongoDB connection URI | mongodb://localhost:27017/market_analyzer |
| OPENAI_API_KEY | OpenAI API key | - |
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a new Pull Request
MIT License
For support, please open an issue in the repository.
rakeshsharmaspyne: create readme file and push into it
GitHub Copilot: # Market Analyzer - AI-Powered Stock Analysis
Real-time stock market analysis using NestJS, OpenAI GPT, and dual database architecture (MySQL + MongoDB).
- NestJS (v10+)
- MySQL v8.0
- MongoDB v6.0
- OpenAI GPT-4
- TypeScript
- Docker
npm installCreate .env file:
# Database
DB_HOST=localhost
DB_PORT=3307
DB_USERNAME=root
DB_PASSWORD=your_password
DB_NAME=market_analyzer
# MongoDB
MONGODB_URI=mongodb://localhost:27017/market_analyzer
# OpenAI
OPENAI_API_KEY=your_api_key
CREATE DATABASE IF NOT EXISTS market_analyzer;
USE market_analyzer;
CREATE TABLE `stock_cron_config` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`frequency_minutes` int NOT NULL,
`last_run_at` datetime DEFAULT NULL,
`next_run_at` datetime GENERATED ALWAYS AS ((case when (`last_run_at` is not null) then (`last_run_at` + interval `frequency_minutes` minute) else NULL end)) STORED,
`is_active` tinyint(1) DEFAULT '1',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)# Development
npm run start:dev
# Production
npm run build
npm run start:prod# Build
docker build -t market-analyzer:1.0 .
# Run
docker run -d -p 3000:3000 market-analyzer:1.0market-analyzer/
├── src/
│ ├── app.module.ts # Main application module
│ ├── database/ # Database connections
│ │ ├── mysql/
│ │ └── mongo/
│ ├── stock/ # Stock analysis
│ │ ├── schemas/
│ │ └── services/
│ └── prompt/ # OpenAI integration
├── test/
└── docker/
- Real-time stock analysis
- Automated data collection (cron)
- Dual database architecture
- REST API endpoints
- Docker support
- Environment-based config
- Every 30s: Stock analysis
- Every 3h: Data updates
- Daily: Market summary
GET /api/stocks // List stocks
POST /api/stocks // Create stock
GET /api/stocks/:symbol // Get by symbol- Node.js v18+
- MySQL v8.0+
- MongoDB v6.0+
- OpenAI API access
# Unit tests
npm run test
# E2E tests
npm run test:e2e| Variable | Description | Default |
|---|---|---|
| DB_HOST | MySQL host | localhost |
| DB_PORT | MySQL port | 3307 |
| DB_USERNAME | MySQL username | root |
| DB_PASSWORD | MySQL password | - |
| DB_NAME | Database name | market_analyzer |
| MONGODB_URI | MongoDB URI | mongodb://localhost:27017/market_analyzer |
| OPENAI_API_KEY | OpenAI key | - |
- Fork repository
- Create feature branch
- Commit changes
- Push to branch
- Create Pull Request
MIT
Open an issue in repository for support.
Save this content in a file named README.md in your project root:
# Market Analyzer - AI-Powered Stock Analysis
[Rest of the content from above...]