fix code, readme and lint

This commit is contained in:
Yusuf Yilmaz 2022-06-08 11:26:32 +02:00
parent 42c60c64c2
commit 350abbdf3b
14 changed files with 158 additions and 153 deletions

View File

@ -1,6 +1,6 @@
module.exports = {
env: {
node: true,
node: true
},
extends: [
'eslint:recommended',
@ -10,47 +10,44 @@ module.exports = {
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'prettier',
],
plugins: [
'import',
'@typescript-eslint'
'prettier'
],
plugins: ['import', '@typescript-eslint'],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts'],
'@typescript-eslint/parser': ['.ts']
},
'import/resolver': {
node: {
extensions: ['.js', '.ts'],
moduleDirectory: ['node_modules', 'src/'],
moduleDirectory: ['node_modules', 'src/']
},
typescript: {
alwaysTryTypes: true,
project: '.',
},
},
project: '.'
}
}
},
overrides: [
{
env: {
jest: true,
jest: true
},
files: ['**/__tests__/**/*.[jt]s', '**/?(*.)+(spec|test).[jt]s'],
extends: ['plugin:jest/recommended'],
rules: {
'import/no-extraneous-dependencies': [
'off',
{ devDependencies: ['**/?(*.)+(spec|test).[jt]s'] },
{ devDependencies: ['**/?(*.)+(spec|test).[jt]s'] }
],
camelcase: ['off'],
},
},
camelcase: ['off']
}
}
],
ignorePatterns: ['**/*.js', 'node_modules', 'dist'],
parserOptions: {
root: true,
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
project: ['./tsconfig.json']
}
}

View File

@ -2,7 +2,7 @@ name: Close inactive issues and PRs
on:
workflow_dispatch:
schedule:
- cron: "30 1 * * *"
- cron: '30 1 * * *'
jobs:
close-stale:
@ -15,16 +15,16 @@ jobs:
with:
days-before-stale: 30
days-before-close: 14
stale-issue-label: "stale"
stale-pr-label: "stale"
stale-issue-label: 'stale'
stale-pr-label: 'stale'
exempt-issue-labels: backlog,triage,nostale
exempt-pr-labels: backlog,triage,nostale
stale-pr-message: "This PR is stale because it has been open for 30 days with no activity."
close-pr-message: "This PR was closed because it has been inactive for 14 days since being marked as stale."
stale-pr-message: 'This PR is stale because it has been open for 30 days with no activity.'
close-pr-message: 'This PR was closed because it has been inactive for 14 days since being marked as stale.'
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
stale-issue-message: 'This issue is stale because it has been open for 30 days with no activity.'
close-issue-message: 'This issue was closed because it has been inactive for 14 days since being marked as stale.'
repo-token: ${{ secrets.GITHUB_TOKEN }}

2
.prettierignore Normal file
View File

@ -0,0 +1,2 @@
static
/node_modules

View File

@ -7,9 +7,9 @@ version can be found at [hastebin.com](http://hastebin.com)
Major design objectives:
* Be really pretty
* Be really simple
* Be easy to set up and use
- Be really pretty
- Be really simple
- Be easy to set up and use
Haste works really well with a little utility called
[haste-client](https://github.com/seejohnrun/haste-client), allowing you
@ -22,54 +22,54 @@ STDOUT. Check the README there for more details and usages.
## Tested Browsers
* Firefox 8
* Chrome 17
* Safari 5.3
- Firefox 8
- Chrome 17
- Safari 5.3
## Installation
1. Download the package, and expand it
3. `yarn add`
2. `yarn`
## Running the project
> Explore the settings inside of config.js, but the defaults should be good
> Explore the settings inside of project-config.js, but the defaults should be good
### Development
1. `yarn add`
1. `yarn`
2. `yarn dev` (you may specify an optional `<config-path>` as well)
### Production
1. `yarn add`
1. `yarn`
2. `yarn build` to build the package
3. `yarn start` to start the server
### Production with Docker
1. `docker compose up`
1. `docker-compose up`
## Settings
* `host` - the host the server runs on (default localhost)
* `port` - the port the server runs on (default 7777)
* `keyLength` - the length of the keys to user (default 10)
* `maxLength` - maximum length of a paste (default 400000)
* `staticMaxAge` - max age for static assets (86400)
* `recompressStaticAssets` - whether or not to compile static js assets (true)
* `documents` - static documents to serve (ex: http://hastebin.com/about.com)
- `host` - the host the server runs on (default localhost)
- `port` - the port the server runs on (default 7777)
- `keyLength` - the length of the keys to user (default 10)
- `maxLength` - maximum length of a paste (default 400000)
- `staticMaxAge` - max age for static assets (86400)
- `recompressStaticAssets` - whether or not to compile static js assets (true)
- `documents` - static documents to serve (ex: http://hastebin.com/about.com)
in addition to static assets. These will never expire.
* `storage` - storage options (see below)
* `logging` - logging preferences
* `keyGenerator` - key generator options (see below)
* `rateLimits` - settings for rate limiting (see below)
- `storage` - storage options (see below)
- `logging` - logging preferences
- `keyGenerator` - key generator options (see below)
- `rateLimits` - settings for rate limiting (see below)
## Rate Limiting
When present, the `rateLimits` option enables built-in rate limiting courtesy
of `connect-ratelimit`. Any of the options supported by that library can be
used and set in `config.js`.
used and set in `project-config.js`.
See the README for [connect-ratelimit](https://github.com/dharmafly/connect-ratelimit)
for more information!
@ -104,7 +104,7 @@ for the key.
### File
To use file storage (the default) change the storage section in `config.js` to
To use file storage (the default) change the storage section in `project-config.js` to
something like:
```json
@ -280,10 +280,7 @@ your bucket:
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Action": ["s3:GetObject", "s3:PutObject"],
"Effect": "Allow",
"Resource": "arn:aws:s3:::your-bucket-name-goes-here/*"
}
@ -401,6 +398,6 @@ SOFTWARE
### Other components:
* jQuery: MIT/GPL license
* highlight.js: Copyright © 2006, Ivan Sagalaev
* highlightjs-coffeescript: WTFPL - Copyright © 2011, Dmytrii Nagirniak
- jQuery: MIT/GPL license
- highlight.js: Copyright © 2006, Ivan Sagalaev
- highlightjs-coffeescript: WTFPL - Copyright © 2011, Dmytrii Nagirniak

View File

@ -24,17 +24,18 @@ and send it to people.
You can even take this a step further, and cut out the last step of copying the
URL with:
* osx: `cat something | haste | pbcopy`
* linux: `cat something | haste | xsel`
* windows: check out [WinHaste](https://github.com/ajryan/WinHaste)
- osx: `cat something | haste | pbcopy`
- linux: `cat something | haste | xsel`
- windows: check out [WinHaste](https://github.com/ajryan/WinHaste)
After running that, the STDOUT output of `cat something` will show up at a URL
which has been conveniently copied to your clipboard.
That's all there is to that, and you can install it with `gem install haste`
right now.
* osx: you will need to have an up to date version of Xcode
* linux: you will need to have rubygems and ruby-devel installed
- osx: you will need to have an up to date version of Xcode
- linux: you will need to have rubygems and ruby-devel installed
## Duration
@ -52,8 +53,8 @@ pastes.
Haste can easily be installed behind your network, and it's all open source!
* [haste-client](https://github.com/seejohnrun/haste-client)
* [haste-server](https://github.com/seejohnrun/haste-server)
- [haste-client](https://github.com/seejohnrun/haste-client)
- [haste-server](https://github.com/seejohnrun/haste-server)
## Author

View File

@ -5,10 +5,8 @@ module.exports = {
rootDir: '../',
testRegex: '\\.test\\.ts$',
reporters: ['default'],
roots: [
"test"
],
roots: ['test'],
moduleNameMapper: {
"src/(.*)": "<rootDir>/src/$1"
'src/(.*)': '<rootDir>/src/$1'
}
}

View File

@ -28,8 +28,8 @@ const {
RATE_LIMITS_BLACKLIST_TOTAL_REQUESTS,
RATE_LIMITS_BLACKLIST_EVERY_MILLISECONDS,
RATE_LIMITS_BLACKLIST,
DOCUMENTS,
} = process.env;
DOCUMENTS
} = process.env
const config = {
host: HOST,
@ -47,29 +47,29 @@ const config = {
{
level: LOGGING_LEVEL,
type: LOGGING_TYPE,
colorize: LOGGING_COLORIZE,
},
colorize: LOGGING_COLORIZE
}
],
keyGenerator: {
type: KEYGENERATOR_TYPE,
keyspace: KEY_GENERATOR_KEYSPACE,
keyspace: KEY_GENERATOR_KEYSPACE
},
rateLimits: {
whitelist: RATE_LIMITS_WHITELIST ? RATE_LIMITS_WHITELIST.split(",") : [],
blacklist: RATE_LIMITS_BLACKLIST ? RATE_LIMITS_BLACKLIST.split(",") : [],
whitelist: RATE_LIMITS_WHITELIST ? RATE_LIMITS_WHITELIST.split(',') : [],
blacklist: RATE_LIMITS_BLACKLIST ? RATE_LIMITS_BLACKLIST.split(',') : [],
categories: {
normal: {
totalRequests: RATE_LIMITS_NORMAL_TOTAL_REQUESTS,
every: RATE_LIMITS_NORMAL_EVERY_MILLISECONDS,
every: RATE_LIMITS_NORMAL_EVERY_MILLISECONDS
},
whitelist:
RATE_LIMITS_WHITELIST_EVERY_MILLISECONDS ||
RATE_LIMITS_WHITELIST_TOTAL_REQUESTS
? {
totalRequests: RATE_LIMITS_WHITELIST_TOTAL_REQUESTS,
every: RATE_LIMITS_WHITELIST_EVERY_MILLISECONDS,
every: RATE_LIMITS_WHITELIST_EVERY_MILLISECONDS
}
: null,
blacklist:
@ -77,10 +77,10 @@ const config = {
RATE_LIMITS_BLACKLIST_TOTAL_REQUESTS
? {
totalRequests: RATE_LIMITS_WHITELIST_TOTAL_REQUESTS,
every: RATE_LIMITS_BLACKLIST_EVERY_MILLISECONDS,
every: RATE_LIMITS_BLACKLIST_EVERY_MILLISECONDS
}
: null
}
: null,
},
},
storage: {
@ -94,15 +94,15 @@ const config = {
db: STORAGE_DB,
user: STORAGE_USERNAME,
password: STORAGE_PASSWORD,
path: STORAGE_FILEPATH,
path: STORAGE_FILEPATH
},
documents: DOCUMENTS
? DOCUMENTS.split(",").reduce((acc, item) => {
const keyAndValueArray = item.replace(/\s/g, "").split("=");
return { ...acc, [keyAndValueArray[0]]: keyAndValueArray[1] };
? DOCUMENTS.split(',').reduce((acc, item) => {
const keyAndValueArray = item.replace(/\s/g, '').split('=')
return { ...acc, [keyAndValueArray[0]]: keyAndValueArray[1] }
}, {})
: null,
};
: null
}
console.log(JSON.stringify(config));
console.log(JSON.stringify(config))

View File

@ -95,6 +95,6 @@
"dev": "nodemon",
"lint": "eslint src --fix",
"types:check": "tsc --noEmit --pretty",
"pretty": "prettier --write src"
"pretty": "prettier --write ."
}
}

View File

@ -12,7 +12,7 @@ class DocumentHandler {
maxLength?: number
public store: Store
store: Store
keyGenerator: KeyGenerator
@ -55,7 +55,7 @@ class DocumentHandler {
)
}
public handlePost(request: Request, response: Response) {
handlePost(request: Request, response: Response) {
// const this = this
let buffer = ''
let cancelled = false
@ -121,7 +121,7 @@ class DocumentHandler {
}
}
public handleRawGet(request: Request, response: Response) {
handleRawGet(request: Request, response: Response) {
const key = request.params.id.split('.')[0]
const skipExpire = !!this.config.documents[key]

View File

@ -23,29 +23,29 @@ export type BaseStoreConfig = {
export interface MongoStoreConfig extends BaseStoreConfig {
connectionUrl: string
type: StoreNames.mongo
type: StoreNames.Mongo
}
export interface MemcachedStoreConfig extends BaseStoreConfig {
host: string
port: number
type: StoreNames.memcached
type: StoreNames.Memcached
}
export interface FileStoreConfig extends BaseStoreConfig {
path: string
type: StoreNames.file
type: StoreNames.File
}
export interface AmazonStoreConfig extends BaseStoreConfig {
bucket: string
region: string
type: StoreNames.amazons3
type: StoreNames.AmazonS3
}
export interface PostgresStoreConfig extends BaseStoreConfig {
connectionUrl: string
type: StoreNames.postgres
type: StoreNames.Postgres
}
export interface RethinkDbStoreConfig extends BaseStoreConfig {
@ -54,7 +54,7 @@ export interface RethinkDbStoreConfig extends BaseStoreConfig {
db: string
user: string
password: string
type: StoreNames.rethinkdb
type: StoreNames.RethinkDb
}
export interface RedisStoreConfig extends BaseStoreConfig {
@ -65,11 +65,11 @@ export interface RedisStoreConfig extends BaseStoreConfig {
password?: string
host?: string
port?: string
type: StoreNames.redis
type: StoreNames.Redis
}
export interface GoogleStoreConfig extends BaseStoreConfig {
type: StoreNames.googledatastore
type: StoreNames.GoogleDataStore
}
export type StoreConfig =

View File

@ -1,11 +1,11 @@
// eslint-disable-next-line import/prefer-default-export
export enum StoreNames {
amazons3 = 'amazon-s3',
file = 'file',
googledatastore = 'google-datastore',
memcached = 'memcached',
mongo = 'mongo',
postgres = 'postgres',
redis = 'redis',
rethinkdb = 'rethinkdb'
AmazonS3 = 'amazon-s3',
File = 'file',
GoogleDataStore = 'google-datastore',
Memcached = 'memcached',
Mongo = 'mongo',
Postgres = 'postgres',
Redis = 'redis',
RethinkDb = 'rethinkdb'
}

View File

@ -1,25 +1,35 @@
import { createMock } from 'ts-auto-mock';
import { createMock } from 'ts-auto-mock'
import DocumentHandler from 'src/lib/document-handler/index'
import Generator from 'src/lib/key-generators/random'
import constants from 'src/constants'
import { Config } from 'src/types/config'
import { Store } from 'src/lib/document-stores';
import { Store } from 'src/lib/document-stores'
const store : Store = createMock<Store>();
const config : Config = createMock<Config>();
const store: Store = createMock<Store>()
const config: Config = createMock<Config>()
describe('document-handler', () => {
describe('with random key', () => {
it('should choose a key of the proper length', () => {
const gen = new Generator({ type: 'random' })
const dh = new DocumentHandler({ keyLength: 6, keyGenerator: gen, store, config})
expect(dh.acceptableKey()?.length).toEqual(6);
const dh = new DocumentHandler({
keyLength: 6,
keyGenerator: gen,
store,
config
})
expect(dh.acceptableKey()?.length).toEqual(6)
})
it('should choose a default key length', () => {
const gen = new Generator({ type: 'random' })
const dh = new DocumentHandler({ keyGenerator: gen, maxLength: 1, store, config })
expect(dh.keyLength).toEqual(constants.DEFAULT_KEY_LENGTH);
const dh = new DocumentHandler({
keyGenerator: gen,
maxLength: 1,
store,
config
})
expect(dh.keyLength).toEqual(constants.DEFAULT_KEY_LENGTH)
})
})
})

View File

@ -14,7 +14,7 @@ describe('Redis document store', () => {
it('should be able to set a key and have an expiration set', async () => {
store = new RedisDocumentStore({
expire: 10,
type: StoreNames.redis
type: StoreNames.Redis
})
return store.set('hello1', 'world', async () => {
const res = await store.client?.ttl('hello1')
@ -25,7 +25,7 @@ describe('Redis document store', () => {
it('should not set an expiration when told not to', async () => {
store = new RedisDocumentStore({
expire: 10,
type: StoreNames.redis
type: StoreNames.Redis
})
store.set(
@ -41,7 +41,7 @@ describe('Redis document store', () => {
it('should not set an expiration when expiration is off', async () => {
store = new RedisDocumentStore({
type: StoreNames.redis
type: StoreNames.Redis
})
store.set('hello3', 'world', async () => {

View File

@ -1,19 +1,19 @@
/* eslint-disable jest/no-conditional-expect */
import Generator from 'src/lib/key-generators/phonetic'
const vowels = 'aeiou';
const consonants = 'bcdfghjklmnpqrstvwxyz';
const vowels = 'aeiou'
const consonants = 'bcdfghjklmnpqrstvwxyz'
describe('PhoneticKeyGenerator', () => {
describe('generation', () => {
it('should return a key of the proper length', () => {
const gen = new Generator({ type: 'phonetic'});
expect(gen.createKey(6).length).toEqual(6);
});
const gen = new Generator({ type: 'phonetic' })
expect(gen.createKey(6).length).toEqual(6)
})
it('should alternate consonants and vowels', () => {
const gen = new Generator({ type: 'phonetic'});
const key = gen.createKey(3);
const gen = new Generator({ type: 'phonetic' })
const key = gen.createKey(3)
// if it starts with a consonant, we expect cvc
// if it starts with a vowel, we expect vcv
if (consonants.includes(key[0])) {
@ -25,6 +25,6 @@ describe('PhoneticKeyGenerator', () => {
expect(vowels.includes(key[2])).toBeTruthy()
expect(consonants.includes(key[1])).toBeTruthy()
}
});
});
});
})
})
})