├── README.md ├── .eslintignore ├── kibibe-server ├── .eslintignore ├── tsconfig.json ├── nest-cli.json ├── tsconfig.build.json ├── test │ ├── jest-e2e.json │ └── app.e2e-spec.ts ├── src │ ├── app.service.ts │ ├── main.ts │ ├── schemas │ │ └── url.schema.ts │ ├── url │ │ ├── url.module.ts │ │ ├── url.service.spec.ts │ │ ├── url.controller.spec.ts │ │ ├── url.service.ts │ │ └── url.controller.ts │ ├── config │ │ ├── config.service.spec.ts │ │ └── config.service.ts │ ├── app.module.ts │ ├── app.controller.spec.ts │ └── app.controller.ts ├── .eslintrc.js ├── package.json └── README.md ├── .github ├── FUNDING.yml └── workflows │ ├── eslint.yml │ └── release.yml ├── config.json ├── tsconfig.json ├── commitlint.config.js ├── .eslintrc.js ├── .gitignore ├── package.json └── .vscode └── settings.json /README.md: -------------------------------------------------------------------------------- 1 | kibibe 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .eslintrc.js -------------------------------------------------------------------------------- /kibibe-server/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .eslintrc.js -------------------------------------------------------------------------------- /kibibe-server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: 2 | - https://paypal.me/thatkookooguy?locale.x=en_US 3 | -------------------------------------------------------------------------------- /kibibe-server/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mongoURI": "https://mongo.kibibit.duckdns.org", 3 | "baseURL": "http://localhost", 4 | "allowedClick": 10 5 | } -------------------------------------------------------------------------------- /kibibe-server/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /kibibe-server/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /kibibe-server/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | export interface IKibibeInfo { 4 | version: string; 5 | } 6 | 7 | @Injectable() 8 | export class AppService { 9 | getHello(): IKibibeInfo { 10 | return { 11 | version: process.env.npm_package_version 12 | }; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /kibibe-server/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | 3 | import { AppModule } from './app.module'; 4 | import { ConfigService } from './config/config.service'; 5 | 6 | async function bootstrap() { 7 | const config = new ConfigService(); 8 | const app = await NestFactory.create(AppModule); 9 | await app.listen(config.get('port')); 10 | } 11 | bootstrap(); 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ '@commitlint/config-angular' ], 3 | rules: { 4 | 'type-enum': [ 5 | 2, 6 | 'always', [ 7 | 'build', 8 | 'chore', 9 | 'ci', 10 | 'docs', 11 | 'feat', 12 | 'fix', 13 | 'perf', 14 | 'refactor', 15 | 'revert', 16 | 'style', 17 | 'test' 18 | ] 19 | ] 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /kibibe-server/src/schemas/url.schema.ts: -------------------------------------------------------------------------------- 1 | import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; 2 | import { Document } from 'mongoose'; 3 | 4 | export type UrlDocument = Url & Document; 5 | 6 | export class CreateUrlDto { 7 | longUrl: string; 8 | } 9 | 10 | @Schema() 11 | export class Url { 12 | @Prop() 13 | urlCode: string; 14 | 15 | @Prop() 16 | longUrl: string; 17 | 18 | @Prop() 19 | clickCount: number; 20 | } 21 | 22 | export const UrlSchema = SchemaFactory.createForClass(Url); 23 | -------------------------------------------------------------------------------- /kibibe-server/src/url/url.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { MongooseModule } from '@nestjs/mongoose'; 3 | import { UrlService } from './url.service'; 4 | import { Url, UrlSchema } from '../schemas/url.schema'; 5 | import { UrlController } from './url.controller'; 6 | 7 | @Module({ 8 | imports: [MongooseModule.forFeature([{ name: Url.name, schema: UrlSchema }])], 9 | providers: [UrlService], 10 | controllers: [UrlController], 11 | exports: [UrlService] 12 | }) 13 | export class UrlModule {} 14 | -------------------------------------------------------------------------------- /kibibe-server/src/url/url.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UrlService } from './url.service'; 3 | 4 | describe('UrlService', () => { 5 | let service: UrlService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [UrlService], 10 | }).compile(); 11 | 12 | service = module.get(UrlService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /kibibe-server/src/config/config.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ConfigService } from './config.service'; 3 | 4 | describe('ConfigService', () => { 5 | let service: ConfigService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [ConfigService], 10 | }).compile(); 11 | 12 | service = module.get(ConfigService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /kibibe-server/src/url/url.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UrlController } from './url.controller'; 3 | 4 | describe('UrlController', () => { 5 | let controller: UrlController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [UrlController], 10 | }).compile(); 11 | 12 | controller = module.get(UrlController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /kibibe-server/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { MongooseModule } from '@nestjs/mongoose'; 3 | 4 | import { AppController } from './app.controller'; 5 | import { AppService } from './app.service'; 6 | import { ConfigService } from './config/config.service'; 7 | import { UrlModule } from './url/url.module'; 8 | 9 | const config = new ConfigService(); 10 | 11 | @Module({ 12 | imports: [ 13 | MongooseModule.forRoot(config.get('mongo')), 14 | UrlModule, 15 | ], 16 | controllers: [AppController], 17 | providers: [AppService, ConfigService], 18 | }) 19 | export class AppModule {} 20 | -------------------------------------------------------------------------------- /kibibe-server/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | 3 | import { AppController } from './app.controller'; 4 | import { AppService } from './app.service'; 5 | 6 | describe('AppController', () => { 7 | let appController: AppController; 8 | 9 | beforeEach(async () => { 10 | const app: TestingModule = await Test.createTestingModule({ 11 | controllers: [AppController], 12 | providers: [AppService], 13 | }).compile(); 14 | 15 | appController = app.get(AppController); 16 | }); 17 | 18 | describe('root', () => { 19 | it('should return "Hello World!"', () => { 20 | expect(appController.getHello()).toBe('Hello World!'); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /kibibe-server/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /kibibe-server/src/config/config.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import * as nconf from 'nconf'; 3 | import { join } from 'path'; 4 | 5 | export interface IKibibeConfig { 6 | mongo: string; 7 | port: number; 8 | } 9 | 10 | @Injectable() 11 | export class ConfigService { 12 | readonly projectBase: string = __dirname.replace(/kibibe.*$/, 'kibibe'); 13 | private readonly nconf = nconf; 14 | defaults: IKibibeConfig = { 15 | mongo: 'mongodb://localhost:27017/kibibe', 16 | port: 10101 17 | } 18 | 19 | constructor() { 20 | this.nconf 21 | .argv() 22 | .env() 23 | .file({ file: join(this.projectBase, 'config.json') }) 24 | .defaults(this.defaults); 25 | } 26 | 27 | get(name: string) { 28 | return this.nconf.get(name); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.github/workflows/eslint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - next 8 | pull_request: 9 | branches: 10 | - master 11 | - next 12 | 13 | jobs: 14 | run-linters: 15 | name: Run linters 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Check out Git repository 20 | uses: actions/checkout@v2 21 | 22 | - name: Set up Node.js 23 | uses: actions/setup-node@v1 24 | with: 25 | node-version: 12 26 | 27 | # ESLint and Prettier must be in `package.json` 28 | - name: Install Node.js dependencies 29 | run: npm install 30 | 31 | - name: Run linters 32 | uses: wearerequired/lint-action@v1 33 | with: 34 | github_token: ${{ secrets.github_token }} 35 | # Enable linters 36 | eslint: true 37 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - next 7 | jobs: 8 | release: 9 | name: Release 10 | runs-on: ubuntu-18.04 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 0 16 | - name: Setup Node.js 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: 12 20 | - name: Install dependencies 21 | run: npm ci 22 | - name: Build 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 26 | run: npm run build 27 | - name: Release 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 31 | run: npx semantic-release 32 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | sourceType: 'module', 6 | }, 7 | plugins: ['@typescript-eslint/eslint-plugin'], 8 | extends: [ 9 | 'plugin:@typescript-eslint/recommended' 10 | ], 11 | root: true, 12 | env: { 13 | node: true, 14 | jest: true, 15 | }, 16 | rules: { 17 | "@typescript-eslint/naming-convention": [ 18 | "error", 19 | { 20 | "selector": "interface", 21 | "format": ["PascalCase"], 22 | "custom": { 23 | "regex": "^I[A-Z]", 24 | "match": true 25 | } 26 | } 27 | ], 28 | '@typescript-eslint/explicit-function-return-type': 'off', 29 | '@typescript-eslint/explicit-module-boundary-types': 'off', 30 | '@typescript-eslint/no-explicit-any': 'off', 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /kibibe-server/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | sourceType: 'module', 6 | }, 7 | plugins: ['@typescript-eslint/eslint-plugin'], 8 | extends: [ 9 | 'plugin:@typescript-eslint/recommended' 10 | ], 11 | root: true, 12 | env: { 13 | node: true, 14 | jest: true, 15 | }, 16 | rules: { 17 | "@typescript-eslint/naming-convention": [ 18 | "error", 19 | { 20 | "selector": "interface", 21 | "format": ["PascalCase"], 22 | "custom": { 23 | "regex": "^I[A-Z]", 24 | "match": true 25 | } 26 | } 27 | ], 28 | '@typescript-eslint/explicit-function-return-type': 'off', 29 | '@typescript-eslint/explicit-module-boundary-types': 'off', 30 | '@typescript-eslint/no-explicit-any': 'off', 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /kibibe-server/src/url/url.service.ts: -------------------------------------------------------------------------------- 1 | import { Model } from 'mongoose'; 2 | import { Injectable } from '@nestjs/common'; 3 | import { InjectModel } from '@nestjs/mongoose'; 4 | import { Url, UrlDocument } from '../schemas/url.schema'; 5 | 6 | @Injectable() 7 | export class UrlService { 8 | constructor(@InjectModel(Url.name) private urlModel: Model) {} 9 | 10 | async create(createUrlDto: Url): Promise { 11 | const createdUrl = new this.urlModel(createUrlDto); 12 | console.log('about to create ', createdUrl); 13 | return createdUrl.save(); 14 | } 15 | 16 | async update(url: Url) { 17 | return this.urlModel.update({ urlCode: url.urlCode }, url); 18 | } 19 | 20 | async findOne(findObj: Partial): Promise { 21 | return this.urlModel.findOne(findObj); 22 | } 23 | 24 | async findAll(): Promise { 25 | return this.urlModel.find().exec(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /kibibe-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kibibe-server", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "prebuild": "rimraf dist", 10 | "build": "nest build", 11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 12 | "start": "nest start", 13 | "start:dev": "nest start --watch", 14 | "start:debug": "nest start --debug --watch", 15 | "start:prod": "node dist/main", 16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"", 17 | "lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 18 | "test": "jest", 19 | "test:watch": "jest --watch", 20 | "test:cov": "jest --coverage", 21 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 22 | "test:e2e": "jest --config ./test/jest-e2e.json" 23 | }, 24 | "dependencies": { 25 | }, 26 | "devDependencies": { 27 | }, 28 | "jest": { 29 | "moduleFileExtensions": [ 30 | "js", 31 | "json", 32 | "ts" 33 | ], 34 | "rootDir": "src", 35 | "testRegex": ".*\\.spec\\.ts$", 36 | "transform": { 37 | "^.+\\.(t|j)s$": "ts-jest" 38 | }, 39 | "collectCoverageFrom": [ 40 | "**/*.(t|j)s" 41 | ], 42 | "coverageDirectory": "../coverage", 43 | "testEnvironment": "node" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /kibibe-server/src/url/url.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, HttpException, HttpStatus, Post } from '@nestjs/common'; 2 | import * as nconf from 'nconf'; 3 | import * as shortid from 'shortid'; 4 | import { isUri } from 'valid-url'; 5 | 6 | import { CreateUrlDto } from '../schemas/url.schema'; 7 | import { UrlService } from './url.service'; 8 | 9 | @Controller('url') 10 | export class UrlController { 11 | constructor(private readonly urlService: UrlService) {} 12 | 13 | @Post() 14 | async shortenUrl(@Body() shortenUrlDto: CreateUrlDto) { 15 | const longUrl = shortenUrlDto.longUrl; 16 | const baseUrl = nconf.get('baseURL'); 17 | 18 | if (!isUri(baseUrl)) { 19 | throw new HttpException( 20 | 'Internal error. Please come back later.', 21 | HttpStatus.INTERNAL_SERVER_ERROR, 22 | ); 23 | } 24 | 25 | const urlCode = shortid.generate(); 26 | 27 | if (!isUri(longUrl)) { 28 | throw new HttpException( 29 | 'Invalid URL. Please enter a vlaid url for shortening.', 30 | HttpStatus.UNPROCESSABLE_ENTITY, 31 | ); 32 | } 33 | 34 | try { 35 | let url = await this.urlService.findOne({ longUrl }); 36 | 37 | if (url) { 38 | return url; 39 | } 40 | 41 | url = await this.urlService.create({ 42 | longUrl, 43 | urlCode, 44 | clickCount: 0, 45 | }); 46 | 47 | return url; 48 | } catch (err) { 49 | throw new HttpException( 50 | `Internal Server error: ${err.message}`, 51 | HttpStatus.INTERNAL_SERVER_ERROR, 52 | ); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /kibibe-server/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Headers, HttpException, Param, Redirect, Req } from '@nestjs/common'; 2 | import { Request } from 'express'; 3 | import * as nconf from 'nconf'; 4 | import * as useragent from 'useragent'; 5 | 6 | import { AppService, IKibibeInfo } from './app.service'; 7 | import { UrlService } from './url/url.service'; 8 | 9 | @Controller() 10 | export class AppController { 11 | constructor( 12 | private readonly appService: AppService, 13 | private UrlService: UrlService, 14 | ) {} 15 | 16 | @Get() 17 | getHello(): IKibibeInfo { 18 | return this.appService.getHello(); 19 | } 20 | 21 | @Get('/:urlCode') 22 | @Redirect('https://docs.nestjs.com') 23 | async redirect( 24 | @Param('urlCode') urlCode, 25 | @Headers() clientInfo, 26 | @Req() request: Request, 27 | ) { 28 | console.log(clientInfo); 29 | const ip = request.header('x-forwarded-for') || request.connection.remoteAddress; 30 | 31 | console.log({ ...useragent.parse(clientInfo['user-agent']), ip}); 32 | 33 | const url = await this.UrlService.findOne({ urlCode }); 34 | 35 | const allowedClicks = nconf.get('allowedClick') || 50000; 36 | 37 | try { 38 | if (url) { 39 | let clickCount = url.clickCount; 40 | if (clickCount >= allowedClicks) { 41 | console.log( 42 | 'The click count for shortcode ' + 43 | urlCode + 44 | ' has passed the limit of ' + 45 | allowedClicks, 46 | ); 47 | throw new HttpException( 48 | 'The click count for shortcode ' + 49 | urlCode + 50 | ' has passed the limit of ' + 51 | allowedClicks, 52 | 400, 53 | ); 54 | } 55 | clickCount++; 56 | 57 | url.clickCount = clickCount; 58 | await this.UrlService.update(url); 59 | return { url: url.longUrl }; 60 | } else { 61 | throw new HttpException( 62 | `The short url doesn't exists in our system.`, 63 | 400, 64 | ); 65 | } 66 | } catch (err) { 67 | console.error( 68 | 'Error while retrieving long url for shorturlcode ' + urlCode, 69 | ); 70 | 71 | throw new HttpException('There is some internal error.', 500); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@kibibit/kibibe", 3 | "version": "0.0.0-development", 4 | "description": "a url shortner and tracker", 5 | "main": "dist/main.js", 6 | "files": [ 7 | "/dist" 8 | ], 9 | "scripts": { 10 | "prebuild": "rimraf dist", 11 | "build:server": "cd kibibe-server && npm run build", 12 | "build": "npm run build:server", 13 | "lint": "eslint \"{kibibe-server,kibibe-client,src,apps,libs,test}/**/*.ts\"", 14 | "lint:fix": "eslint \"{kibibe-server,kibibe-client,src,apps,libs,test}/**/*.ts\" --fix", 15 | "commit": "cz", 16 | "semantic-release": "semantic-release", 17 | "semantic-release:init": "semantic-release-cli setup", 18 | "test": "echo \"Error: no test specified\" && exit 1" 19 | }, 20 | "author": "thatkookooguy ", 21 | "license": "MIT", 22 | "dependencies": { 23 | "@nestjs/common": "^7.5.1", 24 | "@nestjs/core": "^7.5.1", 25 | "@nestjs/mongoose": "^7.1.2", 26 | "@nestjs/platform-express": "^7.5.1", 27 | "mongoose": "^5.10.16", 28 | "nconf": "^0.11.0", 29 | "reflect-metadata": "^0.1.13", 30 | "rimraf": "^3.0.2", 31 | "rxjs": "^6.6.3", 32 | "satelize": "^0.2.0", 33 | "shortid": "^2.2.16", 34 | "useragent": "^2.3.0", 35 | "valid-url": "^1.0.9" 36 | }, 37 | "devDependencies": { 38 | "@commitlint/cli": "^11.0.0", 39 | "@commitlint/config-angular": "^11.0.0", 40 | "@commitlint/config-conventional": "^11.0.0", 41 | "@types/nconf": "^0.10.0", 42 | "all-contributors-cli": "^6.19.0", 43 | "commitizen": "^4.2.2", 44 | "cz-conventional-changelog": "^3.3.0", 45 | "husky": "^4.3.0", 46 | "semantic-release": "^17.3.0", 47 | "semantic-release-cli": "^5.4.0", 48 | "@nestjs/cli": "^7.5.1", 49 | "@nestjs/schematics": "^7.1.3", 50 | "@nestjs/testing": "^7.5.1", 51 | "@types/express": "^4.17.8", 52 | "@types/jest": "^26.0.15", 53 | "@types/mongoose": "^5.10.1", 54 | "@types/node": "^14.14.6", 55 | "@types/shortid": "0.0.29", 56 | "@types/supertest": "^2.0.10", 57 | "@types/useragent": "^2.3.0", 58 | "@types/valid-url": "^1.0.3", 59 | "@typescript-eslint/eslint-plugin": "^4.8.2", 60 | "@typescript-eslint/parser": "^4.8.2", 61 | "eslint": "^7.14.0", 62 | "jest": "^26.6.3", 63 | "supertest": "^6.0.0", 64 | "ts-jest": "^26.4.3", 65 | "ts-loader": "^8.0.8", 66 | "ts-node": "^9.0.0", 67 | "tsconfig-paths": "^3.9.0", 68 | "typescript": "^4.0.5" 69 | }, 70 | "repository": { 71 | "type": "git", 72 | "url": "https://github.com/Kibibit/kibibe.git" 73 | }, 74 | "bugs": { 75 | "url": "https://github.com/Kibibit/kibibe/issues" 76 | }, 77 | "keywords": [ 78 | "nest", 79 | "nestjs", 80 | "url", 81 | "url-shortner" 82 | ], 83 | "config": { 84 | "commitizen": { 85 | "path": "./node_modules/cz-conventional-changelog" 86 | } 87 | }, 88 | "husky": { 89 | "hooks": { 90 | "prepare-commit-msg": "exec < /dev/tty && git cz --hook || true", 91 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 92 | } 93 | }, 94 | "publishConfig": { 95 | "access": "public" 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // Editor 3 | "editor.detectIndentation": false, 4 | "editor.insertSpaces": true, 5 | "editor.tabSize": 2, 6 | "editor.rulers": [80], 7 | "editor.fontFamily": "Hack, Menlo, Monaco, 'Courier New', monospace", 8 | "editor.matchBrackets": true, 9 | // Terminal 10 | "terminal.integrated.fontFamily": "Hack, Menlo, Monaco, 'Courier New', monospace", 11 | "terminal.integrated.fontSize": 12, 12 | // Workbench 13 | "workbench.colorTheme": "Andromeda", 14 | "workbench.editor.showIcons": true, 15 | "workbench.iconTheme": "vs-seti", 16 | // Bracket Pair Colorizer 17 | "bracketPairColorizer.colorMode": "Consecutive", 18 | "bracketPairColorizer.forceUniqueOpeningColor": true, 19 | "bracketPairColorizer.showBracketsInGutter": true, 20 | // Misc 21 | "files.insertFinalNewline": true, 22 | "githubPullRequests.includeRemotes": "all", 23 | "eslint.enable": true, 24 | "eslint.autoFixOnSave": true, 25 | "eslint.alwaysShowStatus": true, 26 | "editor.formatOnSave": true, 27 | "[javascript]": { 28 | "editor.formatOnSave": false 29 | }, 30 | "jshint.enable": false, 31 | "cSpell.enabled": false, 32 | // Jest 33 | "jest.autoEnable": true, 34 | "jest.coverageFormatter": "DefaultFormatter", 35 | "jest.debugCodeLens.showWhenTestStateIn": [ 36 | "fail", 37 | "unknown" 38 | ], 39 | "jest.debugMode": false, 40 | "jest.enableCodeLens": true, 41 | "jest.enableInlineErrorMessages": true, 42 | "jest.enableSnapshotPreviews": true, 43 | "jest.enableSnapshotUpdateMessages": true, 44 | "jest.pathToConfig": "", 45 | "jest.pathToJest": "npm test --", 46 | "jest.restartJestOnSnapshotUpdate": false, 47 | "jest.rootPath": "", 48 | "jest.runAllTestsFirst": true, 49 | "jest.showCoverageOnLoad": true, 50 | // Todo Highlight 51 | "todohighlight.isEnable": true, 52 | "todohighlight.keywords": [ 53 | "TODO", 54 | "NOTE", 55 | { 56 | "text": "BEWARE", 57 | "color": "#ff3860", 58 | "backgroundColor": "rgba(255, 221, 87, 1)", 59 | "overviewRulerColor": "grey" 60 | } 61 | ], 62 | "todohighlight.isCaseSensitive": true, 63 | "todohighlight.defaultStyle": { 64 | "color": "#ffdd57", 65 | "backgroundColor": "rgba(128,0,128, 1)", 66 | "overviewRulerColor": "rgba(128,0,128, 1)", 67 | "borderRadius": "2px", 68 | "isWholeLine": true, 69 | }, 70 | "window.title": "${activeEditorShort}${separator}${rootName} [kibibit]", 71 | "workbench.colorCustomizations": { 72 | "titleBar.activeForeground": "#ffdd57" 73 | }, 74 | "typescriptHero.imports.stringQuoteStyle": "'", 75 | "typescriptHero.imports.grouping": [ 76 | "Plains", 77 | "Modules", 78 | "/^@kb-/", 79 | "Workspace" 80 | 81 | ], 82 | "typescriptHero.imports.organizeOnSave": true, 83 | "typescriptHero.imports.multiLineTrailingComma": false, 84 | "tslint.autoFixOnSave": true, 85 | "editor.codeActionsOnSave": { 86 | "source.fixAll.eslint": true 87 | }, 88 | "jest.showCoverageOnLoad": false 89 | } -------------------------------------------------------------------------------- /kibibe-server/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master 6 | [travis-url]: https://travis-ci.org/nestjs/nest 7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux 8 | [linux-url]: https://travis-ci.org/nestjs/nest 9 | 10 |

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

11 |

12 | NPM Version 13 | Package License 14 | NPM Downloads 15 | Travis 16 | Linux 17 | Coverage 18 | Gitter 19 | Backers on Open Collective 20 | Sponsors on Open Collective 21 | 22 | 23 |

24 | 26 | 27 | ## Description 28 | 29 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 30 | 31 | ## Installation 32 | 33 | ```bash 34 | $ npm install 35 | ``` 36 | 37 | ## Running the app 38 | 39 | ```bash 40 | # development 41 | $ npm run start 42 | 43 | # watch mode 44 | $ npm run start:dev 45 | 46 | # production mode 47 | $ npm run start:prod 48 | ``` 49 | 50 | ## Test 51 | 52 | ```bash 53 | # unit tests 54 | $ npm run test 55 | 56 | # e2e tests 57 | $ npm run test:e2e 58 | 59 | # test coverage 60 | $ npm run test:cov 61 | ``` 62 | 63 | ## Support 64 | 65 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 66 | 67 | ## Stay in touch 68 | 69 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 70 | - Website - [https://nestjs.com](https://nestjs.com/) 71 | - Twitter - [@nestframework](https://twitter.com/nestframework) 72 | 73 | ## License 74 | 75 | Nest is [MIT licensed](LICENSE). 76 | --------------------------------------------------------------------------------