fixed mongo
This commit is contained in:
parent
c172ecc6d3
commit
2437628591
5 changed files with 133 additions and 130 deletions
|
|
@ -12,7 +12,8 @@
|
|||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": { "@stock-bot/config": "*",
|
||||
"dependencies": {
|
||||
"@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"mongodb": "^6.3.0",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import type {
|
|||
} from './types';
|
||||
import { MongoDBHealthMonitor } from './health';
|
||||
import { schemaMap } from './schemas';
|
||||
import { z } from 'zod';
|
||||
import * as yup from 'yup';
|
||||
|
||||
/**
|
||||
* MongoDB Client for Stock Bot
|
||||
|
|
@ -147,15 +147,15 @@ export class MongoDBClient {
|
|||
} as T; // Validate document if schema exists
|
||||
if (collectionName in schemaMap) {
|
||||
try {
|
||||
(schemaMap as any)[collectionName].parse(docWithTimestamps);
|
||||
(schemaMap as any)[collectionName].validateSync(docWithTimestamps);
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
if (error instanceof yup.ValidationError) {
|
||||
this.logger.error(`Document validation failed for ${collectionName}:`, error.errors);
|
||||
throw new Error(`Document validation failed: ${error.errors.map(e => e.message).join(', ')}`);
|
||||
throw new Error(`Document validation failed: ${error.errors?.map(e => e).join(', ')}`);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
} const result = await collection.insertOne(docWithTimestamps as OptionalUnlessRequiredId<T>);
|
||||
}const result = await collection.insertOne(docWithTimestamps as OptionalUnlessRequiredId<T>);
|
||||
return { ...docWithTimestamps, _id: result.insertedId } as T;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,124 +1,124 @@
|
|||
import * as yup from 'yup';
|
||||
|
||||
/**
|
||||
* Zod Schemas for MongoDB Document Validation
|
||||
* Yup Schemas for MongoDB Document Validation
|
||||
*/
|
||||
|
||||
// Base schema for all documents
|
||||
export const documentBaseSchema = z.object({
|
||||
_id: z.any().optional(),
|
||||
created_at: z.date(),
|
||||
updated_at: z.date(),
|
||||
source: z.string(),
|
||||
metadata: z.record(z.any()).optional(),
|
||||
export const documentBaseSchema = yup.object({
|
||||
_id: yup.mixed().optional(),
|
||||
created_at: yup.date().required(),
|
||||
updated_at: yup.date().required(),
|
||||
source: yup.string().required(),
|
||||
metadata: yup.object().optional(),
|
||||
});
|
||||
|
||||
// Sentiment Data Schema
|
||||
export const sentimentDataSchema = documentBaseSchema.extend({
|
||||
symbol: z.string().min(1).max(10),
|
||||
sentiment_score: z.number().min(-1).max(1),
|
||||
sentiment_label: z.enum(['positive', 'negative', 'neutral']),
|
||||
confidence: z.number().min(0).max(1),
|
||||
text: z.string().min(1),
|
||||
source_type: z.enum(['reddit', 'twitter', 'news', 'forums']),
|
||||
source_id: z.string(),
|
||||
timestamp: z.date(),
|
||||
processed_at: z.date(),
|
||||
language: z.string().default('en'),
|
||||
keywords: z.array(z.string()),
|
||||
entities: z.array(z.object({
|
||||
name: z.string(),
|
||||
type: z.string(),
|
||||
confidence: z.number().min(0).max(1),
|
||||
})),
|
||||
export const sentimentDataSchema = documentBaseSchema.shape({
|
||||
symbol: yup.string().min(1).max(10).required(),
|
||||
sentiment_score: yup.number().min(-1).max(1).required(),
|
||||
sentiment_label: yup.string().oneOf(['positive', 'negative', 'neutral']).required(),
|
||||
confidence: yup.number().min(0).max(1).required(),
|
||||
text: yup.string().min(1).required(),
|
||||
source_type: yup.string().oneOf(['reddit', 'twitter', 'news', 'forums']).required(),
|
||||
source_id: yup.string().required(),
|
||||
timestamp: yup.date().required(),
|
||||
processed_at: yup.date().required(),
|
||||
language: yup.string().default('en'),
|
||||
keywords: yup.array(yup.string()).required(),
|
||||
entities: yup.array(yup.object({
|
||||
name: yup.string().required(),
|
||||
type: yup.string().required(),
|
||||
confidence: yup.number().min(0).max(1).required(),
|
||||
})).required(),
|
||||
});
|
||||
|
||||
// Raw Document Schema
|
||||
export const rawDocumentSchema = documentBaseSchema.extend({
|
||||
document_type: z.enum(['html', 'pdf', 'text', 'json', 'xml']),
|
||||
content: z.string(),
|
||||
content_hash: z.string(),
|
||||
url: z.string().url().optional(),
|
||||
title: z.string().optional(),
|
||||
author: z.string().optional(),
|
||||
published_date: z.date().optional(),
|
||||
extracted_text: z.string().optional(),
|
||||
processing_status: z.enum(['pending', 'processed', 'failed']),
|
||||
size_bytes: z.number().positive(),
|
||||
language: z.string().optional(),
|
||||
export const rawDocumentSchema = documentBaseSchema.shape({
|
||||
document_type: yup.string().oneOf(['html', 'pdf', 'text', 'json', 'xml']).required(),
|
||||
content: yup.string().required(),
|
||||
content_hash: yup.string().required(),
|
||||
url: yup.string().url().optional(),
|
||||
title: yup.string().optional(),
|
||||
author: yup.string().optional(),
|
||||
published_date: yup.date().optional(),
|
||||
extracted_text: yup.string().optional(),
|
||||
processing_status: yup.string().oneOf(['pending', 'processed', 'failed']).required(),
|
||||
size_bytes: yup.number().positive().required(),
|
||||
language: yup.string().optional(),
|
||||
});
|
||||
|
||||
// News Article Schema
|
||||
export const newsArticleSchema = documentBaseSchema.extend({
|
||||
headline: z.string().min(1),
|
||||
content: z.string().min(1),
|
||||
summary: z.string().optional(),
|
||||
author: z.string(),
|
||||
publication: z.string(),
|
||||
published_date: z.date(),
|
||||
url: z.string().url(),
|
||||
symbols: z.array(z.string()),
|
||||
categories: z.array(z.string()),
|
||||
sentiment_score: z.number().min(-1).max(1).optional(),
|
||||
relevance_score: z.number().min(0).max(1).optional(),
|
||||
image_url: z.string().url().optional(),
|
||||
tags: z.array(z.string()),
|
||||
export const newsArticleSchema = documentBaseSchema.shape({
|
||||
headline: yup.string().min(1).required(),
|
||||
content: yup.string().min(1).required(),
|
||||
summary: yup.string().optional(),
|
||||
author: yup.string().required(),
|
||||
publication: yup.string().required(),
|
||||
published_date: yup.date().required(),
|
||||
url: yup.string().url().required(),
|
||||
symbols: yup.array(yup.string()).required(),
|
||||
categories: yup.array(yup.string()).required(),
|
||||
sentiment_score: yup.number().min(-1).max(1).optional(),
|
||||
relevance_score: yup.number().min(0).max(1).optional(),
|
||||
image_url: yup.string().url().optional(),
|
||||
tags: yup.array(yup.string()).required(),
|
||||
});
|
||||
|
||||
// SEC Filing Schema
|
||||
export const secFilingSchema = documentBaseSchema.extend({
|
||||
cik: z.string(),
|
||||
accession_number: z.string(),
|
||||
filing_type: z.string(),
|
||||
company_name: z.string(),
|
||||
symbols: z.array(z.string()),
|
||||
filing_date: z.date(),
|
||||
period_end_date: z.date(),
|
||||
url: z.string().url(),
|
||||
content: z.string(),
|
||||
extracted_data: z.record(z.any()).optional(),
|
||||
financial_statements: z.array(z.object({
|
||||
statement_type: z.string(),
|
||||
data: z.record(z.number()),
|
||||
export const secFilingSchema = documentBaseSchema.shape({
|
||||
cik: yup.string().required(),
|
||||
accession_number: yup.string().required(),
|
||||
filing_type: yup.string().required(),
|
||||
company_name: yup.string().required(),
|
||||
symbols: yup.array(yup.string()).required(),
|
||||
filing_date: yup.date().required(),
|
||||
period_end_date: yup.date().required(),
|
||||
url: yup.string().url().required(),
|
||||
content: yup.string().required(),
|
||||
extracted_data: yup.object().optional(),
|
||||
financial_statements: yup.array(yup.object({
|
||||
statement_type: yup.string().required(),
|
||||
data: yup.object().required(),
|
||||
})).optional(),
|
||||
processing_status: z.enum(['pending', 'processed', 'failed']),
|
||||
processing_status: yup.string().oneOf(['pending', 'processed', 'failed']).required(),
|
||||
});
|
||||
|
||||
// Earnings Transcript Schema
|
||||
export const earningsTranscriptSchema = documentBaseSchema.extend({
|
||||
symbol: z.string().min(1).max(10),
|
||||
company_name: z.string(),
|
||||
quarter: z.string(),
|
||||
year: z.number().min(2000).max(3000),
|
||||
call_date: z.date(),
|
||||
transcript: z.string(),
|
||||
participants: z.array(z.object({
|
||||
name: z.string(),
|
||||
title: z.string(),
|
||||
type: z.enum(['executive', 'analyst']),
|
||||
})),
|
||||
key_topics: z.array(z.string()),
|
||||
sentiment_analysis: z.object({
|
||||
overall_sentiment: z.number().min(-1).max(1),
|
||||
topic_sentiments: z.record(z.number()),
|
||||
export const earningsTranscriptSchema = documentBaseSchema.shape({
|
||||
symbol: yup.string().min(1).max(10).required(),
|
||||
company_name: yup.string().required(),
|
||||
quarter: yup.string().required(),
|
||||
year: yup.number().min(2000).max(3000).required(),
|
||||
call_date: yup.date().required(),
|
||||
transcript: yup.string().required(),
|
||||
participants: yup.array(yup.object({
|
||||
name: yup.string().required(),
|
||||
title: yup.string().required(),
|
||||
type: yup.string().oneOf(['executive', 'analyst']).required(),
|
||||
})).required(),
|
||||
key_topics: yup.array(yup.string()).required(),
|
||||
sentiment_analysis: yup.object({
|
||||
overall_sentiment: yup.number().min(-1).max(1).required(),
|
||||
topic_sentiments: yup.object().required(),
|
||||
}).optional(),
|
||||
financial_highlights: z.record(z.number()).optional(),
|
||||
financial_highlights: yup.object().optional(),
|
||||
});
|
||||
|
||||
// Analyst Report Schema
|
||||
export const analystReportSchema = documentBaseSchema.extend({
|
||||
symbol: z.string().min(1).max(10),
|
||||
analyst_firm: z.string(),
|
||||
analyst_name: z.string(),
|
||||
report_title: z.string(),
|
||||
report_date: z.date(),
|
||||
rating: z.enum(['buy', 'hold', 'sell', 'strong_buy', 'strong_sell']),
|
||||
price_target: z.number().positive().optional(),
|
||||
previous_rating: z.string().optional(),
|
||||
content: z.string(),
|
||||
summary: z.string(),
|
||||
key_points: z.array(z.string()),
|
||||
financial_projections: z.record(z.number()).optional(),
|
||||
export const analystReportSchema = documentBaseSchema.shape({
|
||||
symbol: yup.string().min(1).max(10).required(),
|
||||
analyst_firm: yup.string().required(),
|
||||
analyst_name: yup.string().required(),
|
||||
report_title: yup.string().required(),
|
||||
report_date: yup.date().required(),
|
||||
rating: yup.string().oneOf(['buy', 'hold', 'sell', 'strong_buy', 'strong_sell']).required(),
|
||||
price_target: yup.number().positive().optional(),
|
||||
previous_rating: yup.string().optional(),
|
||||
content: yup.string().required(),
|
||||
summary: yup.string().required(),
|
||||
key_points: yup.array(yup.string()).required(),
|
||||
financial_projections: yup.object().optional(),
|
||||
});
|
||||
|
||||
// Schema mapping for collections
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue