-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0eaf098
Showing
57 changed files
with
1,326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
dist | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"singleQuote": true, | ||
"trailingComma": "all" | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
18
src/competitor-analysis/competitor-analysis.controller.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
18
src/competitor-analysis/competitor-analysis.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
18
src/content-optimization/content-optimization.controller.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); |
Oops, something went wrong.