From 7be2818fba0b0b64c0cf343adb618a53f84e4a63 Mon Sep 17 00:00:00 2001 From: Soma Lucz Date: Sun, 27 Oct 2019 21:57:23 +0100 Subject: [PATCH] chore: Set up repository Closes #2. --- .eslintrc.json | 100 ++++++++++++++++++++++++++ .gitignore | 124 +++++++++++++++++++++++++++++++++ .nycrc.json | 4 ++ .prettierignore | 3 + .prettierrc.json | 6 ++ .travis.yml | 14 ++++ package.json | 76 ++++++++++++++++++++ scripts/check-release-tag.mjs | 33 +++++++++ scripts/sync-sonar-version.mjs | 23 ++++++ src/main.ts | 0 test/specs/empty.test.ts | 0 tsconfig.json | 18 +++++ tsconfig.test.json | 18 +++++ 13 files changed, 419 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .nycrc.json create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 .travis.yml create mode 100644 package.json create mode 100644 scripts/check-release-tag.mjs create mode 100644 scripts/sync-sonar-version.mjs create mode 100644 src/main.ts create mode 100644 test/specs/empty.test.ts create mode 100644 tsconfig.json create mode 100644 tsconfig.test.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..9df9ebe --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,100 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "prettier/@typescript-eslint", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:import/typescript", + "plugin:promise/recommended", + "plugin:prettier/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "project": "./tsconfig.json" + }, + "plugins": ["@typescript-eslint/eslint-plugin", "import", "promise"], + "rules": { + "no-console": ["error"], + "no-extra-parens": ["error"], + "no-import-assign": ["error"], + "no-template-curly-in-string": ["error"], + "curly": ["error", "all"], + "eqeqeq": ["error"], + "max-classes-per-file": ["error", 1], + "no-alert": ["error"], + "no-caller": ["error"], + "no-div-regex": ["error"], + "no-else-return": ["error", { "allowElseIf": false }], + "no-eq-null": ["error"], + "no-eval": ["error"], + "no-extend-native": ["error"], + "no-extra-bind": ["error"], + "no-extra-label": ["error"], + "no-floating-decimal": ["error"], + "no-implicit-coercion": ["error"], + "no-implicit-globals": ["error"], + "no-implied-eval": ["error"], + "no-invalid-this": ["error"], + "no-iterator": ["error"], + "no-labels": ["error"], + "no-lone-blocks": ["error"], + "no-loop-func": ["error"], + "no-multi-spaces": ["error"], + "no-multi-str": ["error"], + "no-new": ["error"], + "no-new-func": ["error"], + "no-new-wrappers": ["error"], + "no-octal-escape": ["error"], + "no-param-reassign": ["error"], + "no-proto": ["error"], + "no-return-assign": ["error", "always"], + "no-return-await": ["error"], + "no-script-url": ["error"], + "no-self-compare": ["error"], + "no-sequences": ["error"], + "no-throw-literal": ["error"], + "no-unmodified-loop-condition": ["error"], + "no-useless-call": ["error"], + "no-useless-concat": ["error"], + "no-useless-return": ["error"], + "prefer-named-capture-group": ["error"], + "prefer-promise-reject-errors": ["error"], + "prefer-regex-literals": ["error"], + "radix": ["error", "always"], + "require-unicode-regexp": ["error"], + "wrap-iife": ["error", "inside"], + "yoda": ["error", "never"], + "array-bracket-spacing": ["error", "never"], + "brace-style": ["error"], + "camelcase": ["error"], + "func-call-spacing": ["error"], + "no-lonely-if": ["error"], + "no-nested-ternary": ["error"], + "no-new-object": ["error"], + "no-trailing-spaces": ["error"], + "semi-spacing": ["error", { "before": false, "after": true }], + "promise/prefer-await-to-then": ["error"], + "promise/prefer-await-to-callbacks": ["error"], + "import/first": ["error"], + "import/exports-last": ["error"], + "import/extensions": ["error"], + "import/newline-after-import": ["error"], + "import/no-unassigned-import": ["error"], + "import/no-named-default": ["error"], + "import/no-default-export": ["error"], + "@typescript-eslint/array-type": ["error", { "default": "array-simple" }], + "@typescript-eslint/consistent-type-definitions": ["error", "interface"], + "@typescript-eslint/explicit-member-accessibility": ["error", { "accessibility": "explicit" }], + "@typescript-eslint/prefer-for-of": ["error"], + "@typescript-eslint/prefer-readonly": ["error"], + "@typescript-eslint/promise-function-async": ["error"], + "@typescript-eslint/restrict-plus-operands": ["error"], + "@typescript-eslint/strict-boolean-expressions": ["error"], + "@typescript-eslint/unified-signatures": ["error"] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1879c54 --- /dev/null +++ b/.gitignore @@ -0,0 +1,124 @@ +# Created by https://www.gitignore.io/api/node,macos,visualstudiocode +# Edit at https://www.gitignore.io/?templates=node,macos,visualstudiocode + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +# FuseBox cache +.fusebox/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/node,macos,visualstudiocode + +### Built files ### +dist/ diff --git a/.nycrc.json b/.nycrc.json new file mode 100644 index 0000000..079e2e9 --- /dev/null +++ b/.nycrc.json @@ -0,0 +1,4 @@ +{ + "extension": [".ts"], + "include": ["src/**/*.ts"] +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..82f6022 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +package.json +package-lock.json +tsconfig.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..6a667b9 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "printWidth": 120, + "singleQuote": true, + "trailingComma": "all", + "tabWidth": 4 +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ce80ab2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +dist: trusty + +language: node_js + +node_js: + - node + - lts/* + +install: npm ci + +script: + - commitlint-travis + - npm run build-and-test-everything + - sonar-scanner diff --git a/package.json b/package.json new file mode 100644 index 0000000..e644d75 --- /dev/null +++ b/package.json @@ -0,0 +1,76 @@ +{ + "name": "@diplomatiq/resily", + "version": "0.0.0", + "description": "Resily is a TypeScript resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback. Inspired by App-vNext/Polly.", + "main": "dist/main.js", + "module": "dist/main.js", + "types": "dist/main.d.ts", + "engines": { + "node": ">=9.0.0" + }, + "scripts": { + "build": "tsc", + "build-and-test-everything": "npm run lint && npm run build && npm run test", + "check-release-tag": "node --experimental-modules scripts/check-release-tag.mjs", + "clean": "rm -r ./dist/", + "lint": "eslint ./src/ --ext .ts", + "prepare": "npm run build-and-test-everything", + "prepublishOnly": "npm run check-release-tag", + "test": "cross-env-shell TS_NODE_PROJECT=tsconfig.test.json nyc --reporter=lcov --reporter=text mocha --require ts-node/register --require source-map-support/register --recursive test/specs/**/*.test.ts", + "version": "node --experimental-modules scripts/sync-sonar-version.mjs && conventional-changelog -p angular -i CHANGELOG.md -s && git add sonar-project.properties CHANGELOG.md" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Diplomatiq/resily.git" + }, + "keywords": [ + "resilience", + "fault-handling", + "retry", + "circuit-breaker", + "timeout", + "bulkhead-isolation", + "fallback" + ], + "author": "Diplomatiq", + "license": "MIT", + "bugs": { + "url": "https://github.com/Diplomatiq/resily/issues" + }, + "homepage": "https://github.com/Diplomatiq/resily#readme", + "devDependencies": { + "@commitlint/cli": "^8.1.0", + "@commitlint/travis-cli": "^8.1.0", + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^12.0.7", + "@types/sinon": "^7.0.12", + "@typescript-eslint/eslint-plugin": "^2.3.0", + "@typescript-eslint/parser": "^2.3.0", + "chai": "^4.2.0", + "conventional-changelog-cli": "^2.0.25", + "cross-env": "^6.0.0", + "eslint": "^6.4.0", + "eslint-config-prettier": "^6.3.0", + "eslint-plugin-import": "^2.18.2", + "eslint-plugin-prettier": "^3.1.0", + "eslint-plugin-promise": "^4.2.1", + "husky": "^3.0.5", + "mocha": "^6.1.4", + "nyc": "^14.1.1", + "prettier": "^1.18.2", + "sinon": "^7.3.2", + "source-map-support": "^0.5.12", + "ts-node": "^8.2.0", + "typescript": "^3.5.1" + }, + "files": [ + "dist/**/*" + ], + "husky": { + "hooks": { + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", + "pre-push": "npm run build-and-test-everything" + } + } +} diff --git a/scripts/check-release-tag.mjs b/scripts/check-release-tag.mjs new file mode 100644 index 0000000..e927bd7 --- /dev/null +++ b/scripts/check-release-tag.mjs @@ -0,0 +1,33 @@ +/** + * This script reads the version field from package.json + * and checks if the current git HEAD has a matching tag. + * + * E.g. if the current version is '1.0.0', the matching tag is 'v1.0.0'. + * + * Runs automatically on `npm publish`. + */ + +import { spawnSync } from 'child_process'; +import { readFileSync } from 'fs'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + +const { stdout } = spawnSync('git', ['describe', '--tags', '--exact-match'], { encoding: 'utf-8' }); +const tag = stdout.trim(); + +const currentDir = dirname(fileURLToPath(import.meta.url)); +const packageJsonPath = join(currentDir, '..', 'package.json'); +const packageJsonContents = readFileSync(packageJsonPath, { encoding: 'utf-8' }); +const packageJson = JSON.parse(packageJsonContents); +const packageVersion = packageJson.version; + +if (tag !== `v${packageVersion}`) { + if (tag) { + console.log( + `Current tag (${tag}) does not match package version (${packageVersion}). Publishing from wrong branch?`, + ); + } else { + console.log(`Current commit has no tag. Publishing from wrong branch?`); + } + process.exit(1); +} diff --git a/scripts/sync-sonar-version.mjs b/scripts/sync-sonar-version.mjs new file mode 100644 index 0000000..d9314f9 --- /dev/null +++ b/scripts/sync-sonar-version.mjs @@ -0,0 +1,23 @@ +/** + * This script reads the version from package.json and writes it into + * the sonar-project.properties file's sonar.projectVersion field. + * + * Runs automatically on `npm version`. + */ + +import { readFileSync, writeFileSync } from 'fs'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + +const sonarVersionRegex = /(sonar\.projectVersion=)[^\s]*/; + +const currentDir = dirname(fileURLToPath(import.meta.url)); + +const packageJsonPath = join(currentDir, '..', 'package.json'); +const packageJsonContents = readFileSync(packageJsonPath, { encoding: 'utf-8' }); +const packageJson = JSON.parse(packageJsonContents); + +const sonarPropsPath = join(currentDir, '..', 'sonar-project.properties'); +let sonarProps = readFileSync(sonarPropsPath, { encoding: 'utf-8' }); +sonarProps = sonarProps.replace(sonarVersionRegex, `$1${packageJson.version}`); +writeFileSync(sonarPropsPath, sonarProps, { encoding: 'utf-8' }); diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/specs/empty.test.ts b/test/specs/empty.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..49cd075 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "dist", + "module": "esnext", + "moduleResolution": "node", + "noErrorTruncation": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist", + "rootDir": "src", + "strict": true, + "target": "esnext" + }, + "files": ["src/main.ts"] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..35845f8 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "dist", + "module": "commonjs", + "moduleResolution": "node", + "noErrorTruncation": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist", + "rootDir": "src", + "strict": true, + "target": "es2017" + }, + "files": ["src/main.ts"] +}