Skip to content

Commit

Permalink
first push
Browse files Browse the repository at this point in the history
  • Loading branch information
oguzhan18 committed Jul 29, 2024
0 parents commit 0eaf098
Show file tree
Hide file tree
Showing 57 changed files with 1,326 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
dist
.idea
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"trailingComma": "all"
}
Empty file added README.md
Empty file.
8 changes: 8 additions & 0 deletions nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}
74 changes: 74 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"name": "seo-tools-api",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^9.0.0",
"@nestjs/core": "^9.0.0",
"@nestjs/platform-express": "^9.0.0",
"@nestjs/swagger": "^7.4.0",
"axios": "^1.7.2",
"cheerio": "^1.0.0-rc.12",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.2.0",
"serpapi": "^2.1.0",
"swagger-ui-express": "^5.0.1"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.13",
"@types/jest": "29.5.0",
"@types/node": "18.15.11",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "29.5.0",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "29.0.5",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.2.0",
"typescript": "^4.7.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
25 changes: 25 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Module } from '@nestjs/common';
import { BacklinkCheckerModule } from './backlink-checker/backlink-checker.module';
import { RankCheckerModule } from './rank-checker/rank-checker.module';
import { SeoAuditModule } from './seo-audit/seo-audit.module';
import { SitemapGeneratorModule } from './sitemap-generator/sitemap-generator.module';
import { CompetitorAnalysisModule } from './competitor-analysis/competitor-analysis.module';
import { PageSpeedAnalyzerModule } from './page-speed-analyzer/page-speed-analyzer.module';
import { ContentOptimizationModule } from './content-optimization/content-optimization.module';
import { InternalLinkingModule } from './internal-linking/internal-linking.module';
import { SocialMediaIntegrationModule } from './social-media-integration/social-media-integration.module';

@Module({
imports: [
BacklinkCheckerModule,
RankCheckerModule,
SeoAuditModule,
SitemapGeneratorModule,
CompetitorAnalysisModule,
PageSpeedAnalyzerModule,
ContentOptimizationModule,
InternalLinkingModule,
SocialMediaIntegrationModule,
],
})
export class AppModule {}
18 changes: 18 additions & 0 deletions src/backlink-checker/backlink-checker.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { BacklinkCheckerController } from './backlink-checker.controller';

describe('BacklinkCheckerController', () => {
let controller: BacklinkCheckerController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [BacklinkCheckerController],
}).compile();

controller = module.get<BacklinkCheckerController>(BacklinkCheckerController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
20 changes: 20 additions & 0 deletions src/backlink-checker/backlink-checker.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Controller, Get, Query } from '@nestjs/common';
import { BacklinkCheckerService } from './backlink-checker.service';
import { ApiTags, ApiOperation, ApiQuery } from '@nestjs/swagger';

@ApiTags('backlink-checker')
@Controller('backlink-checker')
export class BacklinkCheckerController {
constructor(public readonly backlinkCheckerService: BacklinkCheckerService) {}

@Get()
@ApiOperation({ summary: 'Check backlinks of a given website' })
@ApiQuery({
name: 'url',
required: true,
description: 'Website URL to check for backlinks',
})
async getBacklinks(@Query('url') url: string): Promise<string[]> {
return this.backlinkCheckerService.checkBacklinks(url);
}
}
9 changes: 9 additions & 0 deletions src/backlink-checker/backlink-checker.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { BacklinkCheckerService } from './backlink-checker.service';
import { BacklinkCheckerController } from './backlink-checker.controller';

@Module({
providers: [BacklinkCheckerService],
controllers: [BacklinkCheckerController],
})
export class BacklinkCheckerModule {}
18 changes: 18 additions & 0 deletions src/backlink-checker/backlink-checker.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { BacklinkCheckerService } from './backlink-checker.service';

describe('BacklinkCheckerService', () => {
let service: BacklinkCheckerService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [BacklinkCheckerService],
}).compile();

service = module.get<BacklinkCheckerService>(BacklinkCheckerService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
25 changes: 25 additions & 0 deletions src/backlink-checker/backlink-checker.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import * as cheerio from 'cheerio';

@Injectable()
export class BacklinkCheckerService {
async checkBacklinks(url: string): Promise<string[]> {
try {
const { data } = await axios.get(url);
const $ = cheerio.load(data);
const backlinks = [];

$('a').each((index, element) => {
const link = $(element).attr('href');
if (link) {
backlinks.push(link);
}
});

return backlinks;
} catch (error) {
throw new Error('Error fetching backlinks');
}
}
}
18 changes: 18 additions & 0 deletions src/competitor-analysis/competitor-analysis.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { CompetitorAnalysisController } from './competitor-analysis.controller';

describe('CompetitorAnalysisController', () => {
let controller: CompetitorAnalysisController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CompetitorAnalysisController],
}).compile();

controller = module.get<CompetitorAnalysisController>(CompetitorAnalysisController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
33 changes: 33 additions & 0 deletions src/competitor-analysis/competitor-analysis.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Controller, Get, Query } from '@nestjs/common';
import { CompetitorAnalysisService } from './competitor-analysis.service';
import { ApiTags, ApiOperation, ApiQuery } from '@nestjs/swagger';

@ApiTags('competitor-analysis')
@Controller('competitor-analysis')
export class CompetitorAnalysisController {
constructor(
private readonly competitorAnalysisService: CompetitorAnalysisService,
) {}

@Get()
@ApiOperation({
summary: "Analyze and compare competitor websites' SEO performance",
})
@ApiQuery({
name: 'urls',
required: true,
description: 'Comma-separated list of competitor URLs to analyze',
})
@ApiQuery({
name: 'keyword',
required: true,
description: 'Keyword to check the rank against',
})
async analyze(
@Query('urls') urls: string,
@Query('keyword') keyword: string,
): Promise<any> {
const urlList = urls.split(',');
return this.competitorAnalysisService.analyze(urlList, keyword);
}
}
9 changes: 9 additions & 0 deletions src/competitor-analysis/competitor-analysis.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { CompetitorAnalysisService } from './competitor-analysis.service';
import { CompetitorAnalysisController } from './competitor-analysis.controller';

@Module({
providers: [CompetitorAnalysisService],
controllers: [CompetitorAnalysisController]
})
export class CompetitorAnalysisModule {}
18 changes: 18 additions & 0 deletions src/competitor-analysis/competitor-analysis.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { CompetitorAnalysisService } from './competitor-analysis.service';

describe('CompetitorAnalysisService', () => {
let service: CompetitorAnalysisService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [CompetitorAnalysisService],
}).compile();

service = module.get<CompetitorAnalysisService>(CompetitorAnalysisService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
40 changes: 40 additions & 0 deletions src/competitor-analysis/competitor-analysis.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import * as cheerio from 'cheerio';

@Injectable()
export class CompetitorAnalysisService {
async getRank(url: string, keyword: string): Promise<number> {
try {
const searchUrl = `https://www.google.com/search?q=${encodeURIComponent(
keyword,
)}`;
const { data } = await axios.get(searchUrl);
const $ = cheerio.load(data);
let rank = -1;

$('a').each((index, element) => {
const link = $(element).attr('href');
if (link && link.includes(url)) {
rank = index + 1;
return false;
}
});

return rank;
} catch (error) {
throw new Error(`Error fetching rank data for ${url}`);
}
}

async analyze(urls: string[], keyword: string): Promise<any> {
const results = [];

for (const url of urls) {
const rank = await this.getRank(url, keyword);
results.push({ url, rank });
}

return results;
}
}
18 changes: 18 additions & 0 deletions src/content-optimization/content-optimization.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ContentOptimizationController } from './content-optimization.controller';

describe('ContentOptimizationController', () => {
let controller: ContentOptimizationController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ContentOptimizationController],
}).compile();

controller = module.get<ContentOptimizationController>(ContentOptimizationController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
Loading

0 comments on commit 0eaf098

Please sign in to comment.