├── .nvmrc ├── .eslintignore ├── .npmrc ├── NOTICE ├── packages ├── web-scripts-utils │ ├── .eslintignore │ ├── __fixtures__ │ │ └── demo-lib │ │ │ ├── src │ │ │ └── index.ts │ │ │ ├── tsconfig.json │ │ │ └── package.json │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ ├── get-consuming-root.ts │ │ ├── has-key-in-obj.ts │ │ ├── has-key-in-obj.test.ts │ │ ├── has-config.ts │ │ └── has-config.test.ts │ ├── package.json │ └── CHANGELOG.md ├── web-scripts │ ├── .eslintignore │ ├── __fixtures__ │ │ ├── index.js │ │ ├── index.ts │ │ ├── Component.jsx │ │ ├── Component.tsx │ │ ├── index.test.js │ │ ├── index.test.ts │ │ ├── Component.test.jsx │ │ └── Component.test.tsx │ ├── bin │ │ └── web-scripts │ ├── src │ │ ├── Tasks │ │ │ ├── FormatTask │ │ │ │ ├── __fixtures__ │ │ │ │ │ └── poorly-formatted-file.ts │ │ │ │ ├── index.ts │ │ │ │ └── index.test.ts │ │ │ ├── AuditTasks │ │ │ │ ├── __fixtures__ │ │ │ │ │ ├── 0 │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── 12 │ │ │ │ │ │ └── package.json │ │ │ │ │ └── 30 │ │ │ │ │ │ └── package.json │ │ │ │ ├── index.ts │ │ │ │ └── index.test.ts │ │ │ ├── TestTask.ts │ │ │ ├── LintTask.ts │ │ │ ├── BuildTask.ts │ │ │ └── CommitTasks.ts │ │ ├── Paths.test.ts │ │ ├── @types │ │ │ └── index.d.ts │ │ ├── Paths.ts │ │ ├── SharedTypes.ts │ │ ├── integration.test.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── config │ │ ├── README.md │ │ ├── tsconfig.json │ │ ├── eslintrc.js │ │ ├── prettier.config.js │ │ ├── jest.config.js │ │ ├── commitlint.config.js │ │ └── lint-staged.config.js │ ├── package.json │ └── README.md ├── create-web-scripts-library │ ├── bin │ │ └── create-web-scripts-library │ ├── tsconfig.json │ ├── .eslintignore │ ├── README.md │ ├── src │ │ ├── get-install-cmd.ts │ │ ├── cli.ts │ │ ├── messages.ts │ │ ├── index.ts │ │ └── integration.test.ts │ └── package.json ├── eslint-plugin │ ├── tsconfig.json │ ├── .eslintrc.json │ ├── src │ │ ├── rules │ │ │ └── best-practices │ │ │ │ ├── no-discouraged-words.md │ │ │ │ ├── no-discouraged-words.ts │ │ │ │ └── no-discouraged-words.test.ts │ │ ├── util │ │ │ ├── helpers.ts │ │ │ └── testHelpers.ts │ │ └── index.ts │ ├── README.md │ ├── package.json │ └── CHANGELOG.md ├── eslint-config │ ├── README.md │ ├── package.json │ └── index.js ├── prettier-config │ ├── README.md │ ├── package.json │ ├── index.js │ └── CHANGELOG.md ├── eslint-config-base │ ├── package.json │ ├── index.js │ ├── README.md │ ├── es6.js │ └── CHANGELOG.md ├── eslint-config-react │ ├── README.md │ ├── package.json │ ├── index.js │ └── CHANGELOG.md ├── eslint-config-typescript │ ├── README.md │ ├── package.json │ ├── index.js │ └── CHANGELOG.md └── tsconfig │ ├── package.json │ ├── tsconfig.json │ ├── docs │ ├── README.md │ ├── guides │ │ ├── cra.md │ │ └── next.md │ └── examples.md │ ├── README.md │ └── CHANGELOG.md ├── .prettierrc.js ├── .husky ├── commit-msg └── pre-commit ├── catalog-info.yaml ├── .eslintrc.json ├── .gitmodules ├── postinstall.sh ├── lerna.json ├── .github ├── workflows │ ├── test.yml │ ├── rebase.yml │ ├── publish.yml │ ├── publish-develop.yml │ └── publish-release.yml └── dependabot.yaml ├── package.json ├── .gitignore ├── release.sh └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .gitignore -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | web-scripts 2 | Copyright 2019 Spotify AB 3 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/.eslintignore: -------------------------------------------------------------------------------- 1 | __fixtures__ -------------------------------------------------------------------------------- /packages/web-scripts/.eslintignore: -------------------------------------------------------------------------------- 1 | __fixtures__ 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./packages/prettier-config'); 2 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/index.js: -------------------------------------------------------------------------------- 1 | export const sum = (a, b) => a + b; 2 | -------------------------------------------------------------------------------- /packages/web-scripts/bin/web-scripts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('../cjs'); 3 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/__fixtures__/demo-lib/src/index.ts: -------------------------------------------------------------------------------- 1 | export const a = () => ''; 2 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/index.ts: -------------------------------------------------------------------------------- 1 | export const sum = (a: number, b: number) => a + b; 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn web-scripts commitmsg --edit="$1" 5 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/bin/create-web-scripts-library: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('../cjs/cli'); 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn web-scripts precommit --no-tests --no-typecheck 5 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/FormatTask/__fixtures__/poorly-formatted-file.ts: -------------------------------------------------------------------------------- 1 | // prettier-ignore 2 | export const FOO = "bar" 3 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/__fixtures__/demo-lib/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@spotify/tsconfig", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/Component.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export const Component = () =>
hello, world.
; 3 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/Component.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export const Component = () =>
hello, world.
; 3 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@spotify/web-scripts/config/tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/index.test.js: -------------------------------------------------------------------------------- 1 | import { sum } from './'; 2 | test('sum', () => { 3 | expect(sum(1, 1)).toEqual(2); 4 | }); 5 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/index.test.ts: -------------------------------------------------------------------------------- 1 | import { sum } from './'; 2 | test('sum', () => { 3 | expect(sum(1, 1)).toEqual(2); 4 | }); 5 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: web-scripts 5 | spec: 6 | type: library 7 | owner: web-infra 8 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/.eslintignore: -------------------------------------------------------------------------------- 1 | # coverage 2 | coverage/ 3 | 4 | # web-scripts generated files 5 | cjs/ 6 | esm/ 7 | types/ 8 | 9 | # ignore the template 10 | template/ -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@spotify", "@spotify/eslint-config-oss"], 3 | "ignorePatterns": [ 4 | "__fixtures__", 5 | "packages/create-web-scripts-library/template" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages/create-web-scripts-library/template"] 2 | path = packages/create-web-scripts-library/template 3 | url = https://github.com/spotify/web-scripts-library-template.git 4 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/AuditTasks/__fixtures__/0/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audit-test", 3 | "description": "This test has no dependencies, so the audit dependency should return a status code of 0" 4 | } 5 | -------------------------------------------------------------------------------- /packages/web-scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@spotify/tsconfig", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "isolatedModules": false, 6 | "noEmit": true, 7 | "jsx": "preserve" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/AuditTasks/__fixtures__/12/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audit-test", 3 | "description": "Throws a high and moderate status. See => https://www.npmjs.com/advisories/10", 4 | "devDependencies": { 5 | "geddy": "13.0.7" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@spotify/tsconfig", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "isolatedModules": false, 6 | "noEmit": true, 7 | "declaration": false, 8 | "jsx": "preserve" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/Component.test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Component } from './Component'; 4 | 5 | describe('testing JSX in tests', () => { 6 | it('does not throw', () => { 7 | expect(() => ).not.toThrow(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/web-scripts/__fixtures__/Component.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { Component } from './Component'; 4 | 5 | describe('testing JSX in tests', () => { 6 | it('does not throw', () => { 7 | expect(() => ).not.toThrow(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/eslint-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@spotify/web-scripts/config/tsconfig.json", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "types": ["node", "jest"], 6 | "isolatedModules": false, 7 | "noEmit": true, 8 | "jsx": "preserve" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/web-scripts/config/README.md: -------------------------------------------------------------------------------- 1 | This folder contains the configuration files for consumers of this CLI. Right now, they are simply symlinks to what the CLI itself uses. In the future they could drift. Even if they do, this folder ensures that consumers will not have to change their paths. 2 | -------------------------------------------------------------------------------- /packages/web-scripts/config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@spotify/tsconfig", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "declaration": true, 6 | "isolatedModules": false, 7 | "jsx": "react", 8 | "lib": ["es6", "dom"], 9 | "module": "commonjs", 10 | "sourceMap": true, 11 | "target": "es6" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /postinstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | web-scripts audit --help &> /dev/null 3 | 4 | if ! [ $? -eq 0 ]; then 5 | echo "Bootstrapping web-scripts..." 6 | yarn lerna run bootstrap 7 | fi 8 | 9 | git submodule update --init --recursive 10 | # gotta remove threshold low until semantic-release gets their lives in order 11 | web-scripts audit # --threshold low 12 | -------------------------------------------------------------------------------- /packages/eslint-plugin/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": [ 5 | "src/rules/best-practices/no-discouraged-words.{md,ts}", 6 | "src/rules/best-practices/no-discouraged-words.test.ts" 7 | ], 8 | "rules": { 9 | "@spotify/best-practices/no-discouraged-words": "off" 10 | } 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/AuditTasks/__fixtures__/30/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audit-test", 3 | "description": "Throws a high and moderate status. See => https://www.npmjs.com/advisories/10 + 48 + 1 ", 4 | "devDependencies": { 5 | "bassmaster": "1.5.1", 6 | "geddy": "13.0.7", 7 | "uglify-js": "2.5.0", 8 | "chokidar": "2.1.8" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/__fixtures__/demo-lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "some-dummy-project", 3 | "jest": { 4 | "collectCoverageFrom": "src/**/*.ts" 5 | }, 6 | "dependencies": { 7 | "react": "*" 8 | }, 9 | "devDependencies": { 10 | "@testing-library/react": "*" 11 | }, 12 | "peerDependencies": { 13 | "styled-components": "*" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/*"], 3 | "npmClient": "yarn", 4 | "useWorkspaces": true, 5 | "version": "15.0.0", 6 | "command": { 7 | "publish": { 8 | "ignoreChanges": [ 9 | "*.md", 10 | "__test__/**", 11 | "__fixtures__/**", 12 | "**/*.test.{j|t}s", 13 | "@(!(package)).json" 14 | ] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # @spotify/eslint-config 2 | 3 | Spotify's TypeScript full ESLint config. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | npm install --save-dev eslint @spotify/eslint-config 9 | ``` 10 | 11 | ## Usage 12 | 13 | After installing, update your project's ESLint config: 14 | 15 | ```js 16 | { 17 | "extends" : ["@spotify"] 18 | } 19 | ``` 20 | 21 | --- 22 | 23 | Read the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) 24 | for more information. 25 | -------------------------------------------------------------------------------- /packages/prettier-config/README.md: -------------------------------------------------------------------------------- 1 | # prettier-config 2 | 3 | Spotify's base Prettier config. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | yarn add --dev @spotify/prettier-config 9 | ``` 10 | 11 | ## Usage 12 | 13 | After installing, update your project's `prettier.config.js` file to import the rule sets you want: 14 | 15 | ```js 16 | module.exports = { 17 | ...require('@spotify/prettier-config'), 18 | // your overrides here 19 | }; 20 | ``` 21 | 22 | --- 23 | 24 | Read the [Prettier config docs](https://prettier.io) for more information. 25 | -------------------------------------------------------------------------------- /packages/eslint-config-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/eslint-config-base", 3 | "version": "15.0.0", 4 | "license": "Apache-2.0", 5 | "description": "Spotify's base ESLint config", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/spotify/web-scripts.git" 10 | }, 11 | "scripts": {}, 12 | "peerDependencies": { 13 | "eslint": ">=7.x" 14 | }, 15 | "publishConfig": { 16 | "access": "public" 17 | }, 18 | "engines": { 19 | "node": ">=18" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/prettier-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/prettier-config", 3 | "version": "15.0.0", 4 | "license": "Apache-2.0", 5 | "description": "Spotify's base Prettier config", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/spotify/web-scripts.git" 9 | }, 10 | "main": "index.js", 11 | "scripts": {}, 12 | "devDependencies": { 13 | "prettier": "^2.8.8" 14 | }, 15 | "peerDependencies": { 16 | "prettier": "2.x" 17 | }, 18 | "publishConfig": { 19 | "access": "public" 20 | }, 21 | "engines": { 22 | "node": ">=18" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/eslint-config-react/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-react 2 | 3 | Spotify's ESLint config for react. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | yarn add --dev @spotify/eslint-config-react eslint eslint-plugin-react eslint-plugin-jsx-a11y 9 | ``` 10 | 11 | ## Usage 12 | 13 | After installing, update your project's `.eslintrc.json` file to import the rule sets you want: 14 | 15 | ```js 16 | { 17 | "extends" : [ 18 | "@spotify/eslint-config-react" 19 | ] 20 | } 21 | ``` 22 | 23 | --- 24 | 25 | Read the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) 26 | for more information. 27 | -------------------------------------------------------------------------------- /packages/eslint-config-typescript/README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-typescript 2 | 3 | Spotify's TypeScript ESLint config extras. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | npm install --save-dev @spotify/eslint-config-typescript 9 | ``` 10 | 11 | ## Usage 12 | 13 | After installing, update your project's `.eslintrc.json` file to import the rule sets you want: 14 | 15 | ```js 16 | { 17 | "extends" : [ 18 | "@spotify/eslint-config-base", 19 | "@spotify/eslint-config-typescript" 20 | ] 21 | } 22 | ``` 23 | 24 | --- 25 | 26 | Read the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) 27 | for more information. 28 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/tsconfig", 3 | "version": "15.0.0", 4 | "license": "Apache-2.0", 5 | "description": "Common tsconfigs to be used as your base configurations", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/spotify/web-scripts.git" 9 | }, 10 | "main": "tsconfig.json", 11 | "files": [ 12 | "tsconfig.json" 13 | ], 14 | "scripts": { 15 | "test": "true" 16 | }, 17 | "devDependencies": { 18 | "typescript": "^5.0.4" 19 | }, 20 | "peerDependencies": { 21 | "typescript": ">=5" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | }, 26 | "engines": { 27 | "node": ">=18" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/web-scripts/config/eslintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | extends: ['@spotify'], 18 | }; 19 | -------------------------------------------------------------------------------- /packages/web-scripts/config/prettier.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = require('@spotify/prettier-config'); 17 | -------------------------------------------------------------------------------- /packages/eslint-config-base/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | extends: ['./es5.js', './es6.js'], 18 | }; 19 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | export { getConsumingRoot } from './get-consuming-root'; 17 | export { hasConfig } from './has-config'; 18 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/README.md: -------------------------------------------------------------------------------- 1 | # `create-web-scripts-library` 2 | 3 | Scaffold a [@spotify/web-scripts](https://github.com/spotify/web-scripts) library quickly. Code was directly inspired by [create-next-app](https://github.com/zeit/create-next-app). 4 | 5 | ## Usage 6 | 7 | ### With `yarn create` 8 | 9 | ```sh 10 | yarn create @spotify/web-scripts-library my-cool-library 11 | ``` 12 | 13 | ### With `npx` 14 | 15 | ```sh 16 | npx @spotify/create-web-scripts-library my-cool-library 17 | ``` 18 | 19 | ### Programatically 20 | 21 | ```javascript 22 | const path = require('path'); 23 | const createWebScriptsLibrary = require('@spotify/create-web-scripts-library'); 24 | 25 | async function start() { 26 | await createWebScriptsLibrary(path.resolve('my-cool-library')); 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /packages/eslint-config-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/eslint-config-typescript", 3 | "version": "15.0.0", 4 | "license": "Apache-2.0", 5 | "description": "Spotify's ESLint config for TypeScript", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/spotify/web-scripts.git" 9 | }, 10 | "main": "index.js", 11 | "scripts": {}, 12 | "devDependencies": { 13 | "@typescript-eslint/eslint-plugin": "^5.59.6", 14 | "@typescript-eslint/parser": "^5.59.6", 15 | "eslint": "^8.40.0" 16 | }, 17 | "peerDependencies": { 18 | "@typescript-eslint/eslint-plugin": ">=5", 19 | "@typescript-eslint/parser": ">=5", 20 | "eslint": ">=8.x" 21 | }, 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "engines": { 26 | "node": ">=18" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '*' 10 | 11 | jobs: 12 | test: 13 | name: Test on node ${{ matrix.node-version }} 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [18] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | with: 23 | fetch-depth: 0 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v2 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | - name: yarn install 29 | run: yarn install --frozen-lockfile 30 | - name: yarn build 31 | run: yarn build 32 | - name: lint 33 | run: yarn lint 34 | - name: test 35 | run: yarn test 36 | -------------------------------------------------------------------------------- /packages/eslint-config-base/README.md: -------------------------------------------------------------------------------- 1 | # @spotify/eslint-config-base 2 | 3 | Spotify's base ESLint config. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | yarn add --dev @spotify/eslint-config-base eslint 9 | ``` 10 | 11 | ## Usage 12 | 13 | After installing, update your project's `.eslintrc.json` file to import the rule sets you want: 14 | 15 | ```js 16 | { 17 | "extends" : [ 18 | "@spotify/eslint-config-base" 19 | ] 20 | } 21 | ``` 22 | 23 | ### ES5 only 24 | 25 | ```js 26 | { 27 | "extends" : [ 28 | "@spotify/eslint-config-base/es5" 29 | ] 30 | } 31 | ``` 32 | 33 | ### ES6+ only 34 | 35 | ```js 36 | { 37 | "extends" : [ 38 | "@spotify/eslint-config-base/es6" 39 | ] 40 | } 41 | ``` 42 | 43 | --- 44 | 45 | Read the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) 46 | for more information. 47 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | on: 2 | issue_comment: 3 | types: [created] 4 | name: Automatic Rebase 5 | jobs: 6 | rebase: 7 | name: Rebase 8 | if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@master 12 | with: 13 | fetch-depth: 0 14 | - name: Automatic Rebase 15 | uses: cirrus-actions/rebase@1.2 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 18 | # https://github.community/t5/GitHub-Actions/Workflow-is-failing-if-no-job-can-be-ran-due-to-condition/m-p/38186#M3250 19 | always_job: 20 | name: Always run job 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Always run 24 | run: echo "This job is used to prevent the workflow to fail when all other jobs are skipped." 25 | -------------------------------------------------------------------------------- /packages/eslint-plugin/src/rules/best-practices/no-discouraged-words.md: -------------------------------------------------------------------------------- 1 | # Prevents usage of discouraged words. (best-practices/no-discouraged-words) 2 | 3 | Use in order to prevent discouraged words in variable names and comments. 4 | 5 | ```js 6 | // .eslintrc.json 7 | { 8 | "plugins": ["@spotify/eslint-plugin"], 9 | "rules": { 10 | "@spotify/best-practices/no-discouraged-words": "error", 11 | } 12 | } 13 | ``` 14 | 15 | ## Discouraged words 16 | 17 | ```js 18 | const discouragedWords = ['blacklist', 'whitelist']; 19 | ``` 20 | 21 | To make a contribution to the list, see [this file](./no-discouraged-words.ts). PRs are most welcome! 22 | 23 | ## Rule details 24 | 25 | This rule will raise the following error whenever you refer to one of the discouraged words above: 26 | 27 | > Usage of the word "{word}" is strongly discouraged. Please use a different word. 28 | -------------------------------------------------------------------------------- /packages/eslint-plugin/src/util/helpers.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export const createDocsUrl = (pathname: string): string => { 18 | return `https://github.com/spotify/web-scripts/blob/master/packages/eslint-plugin/src/rules/${pathname}`; 19 | }; 20 | -------------------------------------------------------------------------------- /packages/eslint-config-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/eslint-config-react", 3 | "version": "15.0.0", 4 | "license": "Apache-2.0", 5 | "description": "Spotify's ESLint config for React projects", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/spotify/web-scripts.git" 9 | }, 10 | "main": "index.js", 11 | "scripts": {}, 12 | "devDependencies": { 13 | "eslint": "^8.40.0", 14 | "eslint-plugin-jsx-a11y": "^6.4.1", 15 | "eslint-plugin-react": "^7.32.2", 16 | "eslint-plugin-react-hooks": "^4.2.0" 17 | }, 18 | "peerDependencies": { 19 | "eslint": ">=8.x", 20 | "eslint-plugin-jsx-a11y": "6.x", 21 | "eslint-plugin-react": ">=7.7.0 <8", 22 | "eslint-plugin-react-hooks": "^4.0.0" 23 | }, 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "engines": { 28 | "node": ">=18" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/src/get-consuming-root.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { resolve } from 'path'; 17 | 18 | // The ROOT folder of the consuming package, 19 | // aka where the user is using this package from. 20 | export const getConsumingRoot = () => resolve(process.cwd()); 21 | -------------------------------------------------------------------------------- /packages/tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "experimentalDecorators": false, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "importHelpers": false, 8 | "incremental": true, 9 | "isolatedModules": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "noEmit": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitAny": true, 15 | "noImplicitReturns": true, 16 | "noImplicitThis": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "pretty": true, 20 | "removeComments": true, 21 | "resolveJsonModule": true, 22 | "strict": true, 23 | "strictBindCallApply": true, 24 | "strictFunctionTypes": true, 25 | "strictNullChecks": true, 26 | "strictPropertyInitialization": true, 27 | "stripInternal": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/web-scripts-monorepo", 3 | "private": true, 4 | "license": "Apache-2.0", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/spotify/web-scripts.git" 8 | }, 9 | "scripts": { 10 | "postinstall": "./postinstall.sh", 11 | "test": "lerna run test --stream", 12 | "build": "lerna run build --stream", 13 | "lint": "web-scripts lint --no-typecheck", 14 | "format": "web-scripts format", 15 | "commit": "web-scripts commit", 16 | "bootstrap": "lerna bootstrap --use-workspaces", 17 | "release": "./release.sh", 18 | "prepare": "husky install" 19 | }, 20 | "workspaces": [ 21 | "packages/*" 22 | ], 23 | "devDependencies": { 24 | "@spotify/eslint-config-oss": "^1.0.0", 25 | "@spotify/eslint-plugin": "^14.1.6", 26 | "husky": "^8.0.1", 27 | "lerna": "^6.6.2", 28 | "typescript": "^5.0.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: / 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: npm 8 | directory: /packages/web-scripts/src/Tasks/AuditTasks/__fixtures__/12 9 | schedule: 10 | interval: daily 11 | ignore: 12 | # these dependencies are intentionally included in 13 | # the test fixtures to see if the audit task works as designed 14 | - dependency-name: geddy 15 | - package-ecosystem: npm 16 | directory: /packages/web-scripts/src/Tasks/AuditTasks/__fixtures__/30 17 | schedule: 18 | interval: daily 19 | ignore: 20 | # these dependencies are intentionally included in 21 | # the test fixtures to see if the audit task works as designed 22 | - dependency-name: bassmaster 23 | - dependency-name: chokidar 24 | - dependency-name: geddy 25 | - dependency-name: uglify-js 26 | -------------------------------------------------------------------------------- /packages/tsconfig/docs/README.md: -------------------------------------------------------------------------------- 1 | # tsconfig 2 | 3 | A collection of different base `tsconfig.json` to be extended from in your project. 4 | 5 | This project aims to reduce per-project configuration as much as possible. With good defaults, we can focus on building, not configuration! 6 | 7 | ## Installation 8 | 9 | Add TypeScript to your project: 10 | 11 | ```sh 12 | yarn add typescript 13 | ``` 14 | 15 | Using npm or yarn: 16 | 17 | ```sh 18 | yarn add --dev @spotify/tsconfig 19 | ``` 20 | 21 | ## Examples 22 | 23 | See the [examples documentation](./examples.md) for detailed guidance on how to set up the Spotify TypeScript config for your any library or app. 24 | 25 | ## Getting Started with TypeScript 26 | 27 | Step-by-step guides for setting up TypeScript and the Spotify TypeScript config for Golden Path use cases are available in this repo as well. 28 | 29 | - [Create React App](./guides/cra.md) 30 | - [Next.js](./guides/next.md) 31 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/src/has-key-in-obj.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | export const hasKeyInObj = ( 17 | key: string, 18 | obj: { [s: string]: any } = {}, 19 | ): boolean => { 20 | const [k, ...restOfK] = key.split('.'); 21 | if (restOfK.length === 0) { 22 | return Object.keys(obj).some(ok => ok === k); 23 | } 24 | const nextObj = obj[k]; 25 | if (!(nextObj instanceof Object)) { 26 | return false; 27 | } 28 | return hasKeyInObj(restOfK.join('.'), nextObj); 29 | }; 30 | -------------------------------------------------------------------------------- /packages/tsconfig/README.md: -------------------------------------------------------------------------------- 1 | # tsconfig 2 | 3 | Check out our [docs on GitHub]. 4 | 5 | A collection of different base `tsconfig.json` to be extended from in your project. 6 | 7 | This project aims to reduce per-project configuration as much as possible. With good defaults, we can focus on building, not configuration! 8 | 9 | ## Installation 10 | 11 | Using npm or yarn: 12 | 13 | ```sh 14 | yarn add --dev @spotify/tsconfig 15 | ``` 16 | 17 | For more information, check out our [docs on GitHub]. 18 | 19 | ## Contributing 20 | 21 | Try to optimize for the fewest specified options between the config specializations. For example, only `app` has `noEmit: true`, since the [default value][compiler options], `false`, is good for the `lib` config. Specifying it only in the `app` config means fewer overall entries! 22 | 23 | We want to keep maintenance low by only specifying what is necessary. If the option's [default value][compiler options] is good for every config, remove it from every config! 24 | 25 | [compiler options]: https://www.typescriptlang.org/docs/handbook/compiler-options.html 26 | [docs on github]: ./docs 27 | -------------------------------------------------------------------------------- /packages/eslint-plugin/src/util/testHelpers.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { RuleTester } from 'eslint'; 18 | 19 | export const createRuleTester = (): RuleTester => { 20 | return new RuleTester({ 21 | parser: require.resolve('@typescript-eslint/parser'), 22 | parserOptions: { 23 | ecmaVersion: 2018, 24 | ecmaFeatures: { 25 | experimentalObjectRestSpread: true, 26 | jsx: true, 27 | }, 28 | sourceType: 'module', 29 | }, 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /packages/web-scripts/config/jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | const path = require('path'); 17 | 18 | module.exports = { 19 | rootDir: path.join(process.cwd(), 'src'), 20 | coverageDirectory: path.join(process.cwd(), 'coverage'), 21 | collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', '!**/*.d.ts'], 22 | transform: { 23 | '^.+\\.[tj]sx?$': [ 24 | 'ts-jest', 25 | { 26 | tsconfig: { 27 | allowJs: true, 28 | }, 29 | }, 30 | ], 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | publish: 10 | name: Publish 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | # pulls all commits (needed for lerna / semantic release to correctly version) 17 | fetch-depth: '0' 18 | # pulls all tags (needed for lerna / semantic release to correctly version) 19 | - name: fetch tags 20 | run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* 21 | - uses: actions/setup-node@v2 22 | with: 23 | node-version: 18 24 | - name: yarn install 25 | run: yarn install --frozen-lockfile 26 | - name: yarn build 27 | run: yarn build 28 | - name: lint 29 | run: yarn lint 30 | - name: test 31 | run: yarn test 32 | - name: release 33 | run: yarn release 34 | env: 35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 37 | GH_USERNAME: ${{ secrets.GH_USERNAME }} 38 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/src/get-install-cmd.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | // from https://github.com/zeit/create-next-app/blob/master/lib/utils/get-install-cmd.js 17 | 18 | import execa from 'execa'; 19 | 20 | let cmd: string; 21 | 22 | export default function getInstallCmd() { 23 | if (cmd) { 24 | return cmd; 25 | } 26 | 27 | try { 28 | execa.commandSync('yarnpkg --version'); 29 | cmd = 'yarn'; 30 | } catch (e) { 31 | cmd = 'npm'; 32 | } 33 | 34 | return cmd; 35 | } 36 | -------------------------------------------------------------------------------- /packages/tsconfig/docs/guides/cra.md: -------------------------------------------------------------------------------- 1 | # Create React App 2 | 3 | **This assumes you are using `react-scripts` v2.1 or higher!** 4 | 5 | ## Install TypeScript 6 | 7 | Install TypeScript and configure it for use with Create React App by following their [brief tutorial](https://facebook.github.io/create-react-app/docs/adding-typescript). 8 | 9 | _Feel free to commit just that part as a first step._ 10 | 11 | ## Install and use the Spotify TypeScript config 12 | 13 | Next, install the Spotify TypeScript config as a dev dependency: 14 | 15 | ```sh 16 | yarn add -D @spotify/tsconfig 17 | ``` 18 | 19 | Create React App will have already created a `tsconfig.json` for you. In this file, add an `extends` configuration: 20 | 21 | ```json 22 | { 23 | "extends": "@spotify/tsconfig", 24 | "include": ["src"] 25 | } 26 | ``` 27 | 28 | Start your server up. At this point, Create React App will probably update your tsconfig.json with some defaults they recommend. At the time of writing, these don't conflict with anything the Spotify config attempts to cover, so let Create React App do it. 29 | 30 | _Go ahead and create another commit here once your server runs successfully._ 31 | -------------------------------------------------------------------------------- /packages/eslint-plugin/README.md: -------------------------------------------------------------------------------- 1 | # @spotify/eslint-plugin 2 | 3 | This contains all Spotify-specific eslint rules. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | npm install --save-dev eslint @spotify/eslint-plugin 9 | ``` 10 | 11 | ## Rules 12 | 13 | | Category | Name | Description | 14 | | -------------- | --------------------------------------- | ------------------------------------------------------------------------------------ | 15 | | Best Practices | [`best-practices/no-discouraged-words`] | Prevents usage of specific words. [See more][`best-practices/no-discouraged-words`]. | 16 | 17 | [`best-practices/no-discouraged-words`]: https://github.com/spotify/web-scripts/blob/master/packages/eslint-spotify/src/rules/best-practices/no-discouraged-words.md 18 | 19 | ## Usage 20 | 21 | After installing, update your project's `.eslintrc.json` config: 22 | 23 | ```js 24 | { 25 | "plugins": ["@spotify/eslint-plugin"], 26 | } 27 | ``` 28 | 29 | --- 30 | 31 | Read the [ESlint config docs](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information. 32 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Paths.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { stat as statFS } from 'fs'; 17 | import { promisify } from 'util'; 18 | const stat = promisify(statFS); 19 | import * as Paths from './Paths'; 20 | 21 | test('Paths are exported and exist', async () => { 22 | expect(await stat(Paths.CONSUMING_ROOT)).toBeTruthy(); 23 | expect(await stat(Paths.THIS_ROOT)).toBeTruthy(); 24 | expect(await stat(Paths.ESLINT_CONFIG)).toBeTruthy(); 25 | expect(await stat(Paths.PRETTIER_CONFIG)).toBeTruthy(); 26 | expect(await stat(Paths.TSCONFIG)).toBeTruthy(); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/tsconfig/docs/guides/next.md: -------------------------------------------------------------------------------- 1 | # Next.js 2 | 3 | **This assumes you are using `next` v9 or higher!** 4 | 5 | ## Install TypeScript in your Next app 6 | 7 | Install TypeScript and configure it for use with Next by following their [brief tutorial](https://github.com/zeit/next.js#typescript). 8 | 9 | _Feel free to commit just that part as a first step._ 10 | 11 | ## Install and use the Spotify TypeScript config 12 | 13 | Next, install the Spotify TypeScript config as a dev dependency: 14 | 15 | ```sh 16 | yarn add -D @spotify/tsconfig 17 | ``` 18 | 19 | You will have already created a `tsconfig.json` in the tutorial, and it should contain some defaults from Next. In this file, add an `extends` configuration: 20 | 21 | ```json 22 | { 23 | "extends": "@spotify/tsconfig" 24 | } 25 | ``` 26 | 27 | Start your server up. Be sure to test that TypeScript is all working by changing the file extension of something in `pages` from `.js` to `.tsx`. 28 | 29 | You can test that type failures break your build by doing some invalid TypeScript: 30 | 31 | ```ts 32 | let a = 1; 33 | console.log(a); 34 | a = 'foo'; 35 | ``` 36 | 37 | _Go ahead and create another commit here once your server runs successfully._ 38 | -------------------------------------------------------------------------------- /packages/eslint-plugin/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import path from 'path'; 18 | import { Rule } from 'eslint'; 19 | 20 | type RulesInput = string[]; 21 | type RulesOutput = { [key: string]: Rule.RuleModule }; 22 | 23 | const exportRules = (rulesInput: RulesInput): RulesOutput => { 24 | return rulesInput.reduce( 25 | (rulesOutput, rule) => ({ 26 | ...rulesOutput, 27 | [rule]: require(`./${path.join('./rules/', rule)}`).default, 28 | }), 29 | {} as RulesOutput, 30 | ); 31 | }; 32 | 33 | module.exports = { 34 | rules: exportRules(['best-practices/no-discouraged-words']), 35 | }; 36 | -------------------------------------------------------------------------------- /.github/workflows/publish-develop.yml: -------------------------------------------------------------------------------- 1 | name: Publish Develop Branch 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | 8 | jobs: 9 | publish: 10 | name: Publish Develop Branch 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | # pulls all commits (needed for lerna / semantic release to correctly version) 17 | fetch-depth: '0' 18 | # pulls all tags (needed for lerna / semantic release to correctly version) 19 | - name: fetch tags 20 | run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* 21 | - uses: actions/setup-node@v2 22 | with: 23 | node-version: 18 24 | - name: yarn install 25 | run: yarn install --frozen-lockfile 26 | - name: yarn build 27 | run: yarn build 28 | - name: lint 29 | run: yarn lint 30 | - name: test 31 | run: yarn test 32 | - name: copy token 33 | run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} >> ~/.npmrc 34 | env: 35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | - name: publish 37 | run: npx lerna publish --yes --canary --preid dev --dist-tag dev --conventional-commits --registry=https://registry.npmjs.org 38 | -------------------------------------------------------------------------------- /.github/workflows/publish-release.yml: -------------------------------------------------------------------------------- 1 | name: Publish Release Branch 2 | 3 | on: 4 | push: 5 | branches: 6 | - release 7 | 8 | jobs: 9 | publish: 10 | name: Publish Release Branch 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | # pulls all commits (needed for lerna / semantic release to correctly version) 17 | fetch-depth: '0' 18 | # pulls all tags (needed for lerna / semantic release to correctly version) 19 | - name: fetch tags 20 | run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* 21 | - uses: actions/setup-node@v2 22 | with: 23 | node-version: 18 24 | - name: yarn install 25 | run: yarn install --frozen-lockfile 26 | - name: yarn build 27 | run: yarn build 28 | - name: lint 29 | run: yarn lint 30 | - name: test 31 | run: yarn test 32 | - name: copy token 33 | run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} >> ~/.npmrc 34 | env: 35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | - name: publish 37 | run: npx lerna publish --yes --canary --preid rc --dist-tag prerelease --conventional-commits --registry=https://registry.npmjs.org 38 | -------------------------------------------------------------------------------- /packages/prettier-config/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | // defaults have been commented out 17 | // https://prettier.io/docs/en/options.html 18 | 19 | module.exports = { 20 | // printWidth: 80, 21 | // tabWidth: 2, 22 | // useTabs: false, 23 | // semi: true, 24 | singleQuote: true, 25 | // jsxSingleQuote: false, 26 | trailingComma: 'all', 27 | // bracketSpacing: true, 28 | // jsxBracketSameLine: false, 29 | arrowParens: 'avoid', 30 | // rangeStart: 0, 31 | // rangeEnd: Infinity, 32 | // requirePragma: false, 33 | // insertPragma: false, 34 | // proseWrap: 'preserve', 35 | // htmlWhitespaceSensitivity: 'css', 36 | // endOfLine: 'auto', 37 | }; 38 | -------------------------------------------------------------------------------- /packages/web-scripts/config/commitlint.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | extends: ['@commitlint/config-conventional'], 18 | rules: { 19 | 'subject-case': [ 20 | 1, 21 | 'never', 22 | ['sentence-case', 'start-case', 'pascal-case', 'upper-case'], 23 | ], 24 | 'type-enum': [ 25 | 1, 26 | 'always', 27 | [ 28 | 'feat', 29 | 'fix', 30 | 'improvement', 31 | 'docs', 32 | 'style', 33 | 'refactor', 34 | 'perf', 35 | 'test', 36 | 'build', 37 | 'ci', 38 | 'chore', 39 | 'revert', 40 | ], 41 | ], 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/web-scripts-utils", 3 | "version": "15.0.0", 4 | "description": "Private package which contains re-used utils within web-scripts projects", 5 | "license": "Apache-2.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/spotify/web-scripts.git" 9 | }, 10 | "main": "cjs/index.js", 11 | "module": "esm/index.js", 12 | "types": "types", 13 | "files": [ 14 | "cjs", 15 | "esm", 16 | "types" 17 | ], 18 | "scripts": { 19 | "clean": "rm -rf cjs esm types", 20 | "build": "web-scripts build", 21 | "test": "web-scripts test", 22 | "lint": "web-scripts lint --stylecheck", 23 | "format": "web-scripts format", 24 | "bootstrap": "yarn run clean && tsc --allowJs --outDir cjs --noEmit false --module CommonJS && tsc --declaration --isolatedModules false --outDir types --emitDeclarationOnly --noEmit false", 25 | "prepublishOnly": "yarn run bootstrap && yarn run build" 26 | }, 27 | "dependencies": { 28 | "@types/glob": "8.1.0", 29 | "glob": "8.1.0", 30 | "read-pkg-up": "^7.0.1" 31 | }, 32 | "devDependencies": { 33 | "@spotify/tsconfig": "^15.0.0", 34 | "@types/jest": "^29.5.1" 35 | }, 36 | "publishConfig": { 37 | "access": "public" 38 | }, 39 | "engines": { 40 | "node": ">=18" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/web-scripts/src/@types/index.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | declare module 'object.fromentries' { 17 | export default function fromEntries(entries: Array<[string, T]>): { 18 | [s: string]: T; 19 | }; 20 | } 21 | 22 | // / 23 | 24 | declare module 'cross-spawn-promise' { 25 | import { SpawnOptions } from 'child_process'; 26 | 27 | interface CrossSpawnOptions extends SpawnOptions { 28 | encoding: string; 29 | } 30 | 31 | interface CrossSpawnError { 32 | exitStatus: number; 33 | message: string; 34 | stack: string; 35 | stderr: Uint8Array; 36 | stdout: Uint8Array | null; 37 | } 38 | 39 | export default function crossSpawnPromise( 40 | cmd: string, 41 | args?: any[], 42 | options?: Partial, 43 | ): Promise; 44 | } 45 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/eslint-config", 3 | "version": "15.0.0", 4 | "description": "Combined ESLint config for Spotify", 5 | "author": "Paul Marbach ", 6 | "homepage": "https://github.com/spotify/web-scripts#readme", 7 | "license": "Apache-2.0", 8 | "main": "index.js", 9 | "files": [ 10 | "index.js" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/spotify/web-scripts.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/spotify/web-scripts/issues" 18 | }, 19 | "scripts": {}, 20 | "dependencies": { 21 | "@spotify/eslint-config-base": "^15.0.0", 22 | "@spotify/eslint-config-react": "^15.0.0", 23 | "@spotify/eslint-config-typescript": "^15.0.0", 24 | "@spotify/eslint-plugin": "^15.0.0", 25 | "@spotify/web-scripts-utils": "^15.0.0", 26 | "@typescript-eslint/eslint-plugin": "^5.59.6", 27 | "@typescript-eslint/parser": "^5.59.6", 28 | "eslint-config-prettier": "^8.8.0", 29 | "eslint-plugin-jest": "^27.1.6", 30 | "eslint-plugin-jsx-a11y": "^6.4.1", 31 | "eslint-plugin-react": "^7.32.2", 32 | "eslint-plugin-react-hooks": "^4.2.0" 33 | }, 34 | "devDependencies": { 35 | "eslint": "^8.40.0" 36 | }, 37 | "peerDependencies": { 38 | "eslint": ">=8.x" 39 | }, 40 | "publishConfig": { 41 | "access": "public" 42 | }, 43 | "engines": { 44 | "node": ">=18" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Paths.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { join } from 'path'; 17 | import { getConsumingRoot } from '@spotify/web-scripts-utils'; 18 | 19 | // The ROOT folder of the consuming package, aka where the user is using this 20 | // package from. 21 | export const CONSUMING_ROOT = getConsumingRoot(); 22 | 23 | // This tool's ROOT folder. 24 | export const THIS_ROOT = join(__dirname, '..'); 25 | 26 | export const CONFIG_FOLDER = join(THIS_ROOT, 'config'); 27 | export const ESLINT_CONFIG = join(CONFIG_FOLDER, 'eslintrc.js'); 28 | export const PRETTIER_CONFIG = join(CONFIG_FOLDER, 'prettier.config.js'); 29 | export const TSCONFIG = join(CONFIG_FOLDER, 'tsconfig.json'); 30 | export const JEST_CONFIG = join(CONFIG_FOLDER, 'jest.config.js'); 31 | export const COMMITLINT_CONIFG = join(CONFIG_FOLDER, 'commitlint.config.js'); 32 | export const LINT_STAGED_CONFIG = join(CONFIG_FOLDER, 'lint-staged.config.js'); 33 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/create-web-scripts-library", 3 | "version": "15.0.0", 4 | "description": "Project scaffolding script for @spotify/web-scripts libraries", 5 | "author": "Paul Marbach ", 6 | "homepage": "https://github.com/spotify/web-scripts#readme", 7 | "license": "Apache-2.0", 8 | "bin": { 9 | "create-web-scripts-library": "bin/create-web-scripts-library" 10 | }, 11 | "main": "cjs/index.js", 12 | "module": "esm/index.js", 13 | "types": "types", 14 | "files": [ 15 | "cjs", 16 | "esm", 17 | "bin", 18 | "types", 19 | "template", 20 | "package.json" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/spotify/web-scripts.git" 25 | }, 26 | "scripts": { 27 | "test": "web-scripts test", 28 | "build": "web-scripts build", 29 | "lint": "web-scripts lint --stylecheck", 30 | "format": "web-scripts format", 31 | "prepublishOnly": "yarn run build" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/spotify/web-scripts/issues" 35 | }, 36 | "dependencies": { 37 | "chalk": "^4.0.0", 38 | "commander": "^10.0.1", 39 | "execa": "^5.0.0", 40 | "fs-extra": "^11.1.1", 41 | "read-pkg-up": "^7.0.1" 42 | }, 43 | "devDependencies": { 44 | "@spotify/web-scripts": "^15.0.0", 45 | "@types/fs-extra": "^11.0.1", 46 | "tempy": "^1.0.1" 47 | }, 48 | "publishConfig": { 49 | "access": "public" 50 | }, 51 | "engines": { 52 | "node": ">=18" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/eslint-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/eslint-plugin", 3 | "version": "15.0.0", 4 | "description": "Set of rules for Spotify's custom ESLint rules", 5 | "author": "Bilawal Hameed ", 6 | "homepage": "https://github.com/spotify/web-scripts/blob/master/packages/eslint-plugin#readme", 7 | "keywords": [ 8 | "eslint", 9 | "eslint-plugin", 10 | "react", 11 | "typescript" 12 | ], 13 | "license": "Apache-2.0", 14 | "main": "cjs/index.js", 15 | "module": "esm/index.js", 16 | "types": "types", 17 | "files": [ 18 | "cjs", 19 | "esm", 20 | "types" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/spotify/web-scripts.git", 25 | "directory": "packages/eslint-plugin" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/spotify/web-scripts/issues" 29 | }, 30 | "scripts": { 31 | "build": "web-scripts build", 32 | "test": "web-scripts test", 33 | "lint": "web-scripts lint --stylecheck", 34 | "format": "web-scripts format" 35 | }, 36 | "devDependencies": { 37 | "@spotify/web-scripts": "^15.0.0", 38 | "@types/eslint": "^8.37.0", 39 | "@types/jest": "^29.5.1", 40 | "@typescript-eslint/parser": "^5.59.6", 41 | "@typescript-eslint/types": "^5.59.6", 42 | "eslint": "^8.40.0", 43 | "typescript": "^5.0.4" 44 | }, 45 | "peerDependencies": { 46 | "@typescript-eslint/parser": "^5.13.0", 47 | "eslint": ">=8.x" 48 | }, 49 | "publishConfig": { 50 | "access": "public" 51 | }, 52 | "engines": { 53 | "node": ">=18" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/src/cli.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { program } from 'commander'; 17 | import chalk from 'chalk'; 18 | 19 | import createWebScriptsLibrary from '.'; 20 | 21 | // MUST require and not import this to avoid wrecking the 22 | // file structure in the build output. 23 | const pkg = require('../package.json'); 24 | 25 | let projectName: string; 26 | 27 | program 28 | .version(pkg.version) 29 | .arguments('') 30 | .usage(`${chalk.green('')} [options]`) 31 | .action((name: string) => { 32 | projectName = name; 33 | }) 34 | .allowUnknownOption() 35 | .parse(process.argv); 36 | 37 | async function run() { 38 | try { 39 | await createWebScriptsLibrary(projectName); 40 | } catch (err) { 41 | /* eslint-disable no-console */ 42 | console.log(chalk.redBright('Failed to create your project!')); 43 | console.log((err as Error).message); 44 | /* eslint-enable no-console */ 45 | process.exit(1); 46 | return; 47 | } 48 | } 49 | 50 | run(); 51 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/src/has-key-in-obj.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { hasKeyInObj } from './has-key-in-obj'; 17 | 18 | describe('hasKeyInObj', () => { 19 | it('works when the key is defined', () => { 20 | expect(hasKeyInObj('a', { a: 1, b: 2 })).toBe(true); 21 | }); 22 | 23 | it('works when the key is not defined', () => { 24 | expect(hasKeyInObj('c', { a: 1, b: 2 })).toBe(false); 25 | }); 26 | 27 | it('works when the key is nested and defined', () => { 28 | expect(hasKeyInObj('c.foo', { a: 1, b: 2, c: { foo: 'bar' } })).toBe(true); 29 | }); 30 | 31 | it('works when the key is nested and undefined', () => { 32 | expect(hasKeyInObj('c.baz', { a: 1, b: 2, c: { foo: 'bar' } })).toBe(false); 33 | }); 34 | 35 | it('works when the key is nested and undefined early', () => { 36 | expect(hasKeyInObj('d.baz', { a: 1, b: 2, c: { foo: 'bar' } })).toBe(false); 37 | }); 38 | 39 | it('does not fail when the object is undefined', () => { 40 | expect(() => hasKeyInObj('foo', undefined)).not.toThrow(); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/src/messages.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { program } from 'commander'; 17 | import chalk from 'chalk'; 18 | 19 | export const missingProjectName = () => ` 20 | Please specify the project directory: 21 | ${chalk.cyan(program.name())} ${chalk.green('')} 22 | 23 | For example: 24 | ${chalk.cyan(program.name())} ${chalk.green('my-library-name')} 25 | Run ${chalk.cyan(`${program.name()} --help`)} to see all options. 26 | `; 27 | 28 | export const alreadyExists = (projectName: string) => ` 29 | It looks like there's already a directory called "${chalk.cyan( 30 | projectName, 31 | )}". Please try a different name or delete that folder.`; 32 | 33 | export const start = (projectName: string) => ` 34 | Your project is now set up in "${chalk.cyan(projectName)}"! Try running 35 | 36 | ${chalk.green('yarn lint')} 37 | ${chalk.green('yarn test')} 38 | ${chalk.green('yarn build')} 39 | 40 | to see the web-scripts in action. When you're ready to publish your package, use ${chalk.green( 41 | 'yarn commit', 42 | )} and ${chalk.green('yarn release')} to use commitizen and semantic-release.`; 43 | -------------------------------------------------------------------------------- /.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 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Optional REPL history 57 | .node_repl_history 58 | 59 | # Output of 'npm pack' 60 | *.tgz 61 | 62 | # Yarn Integrity file 63 | .yarn-integrity 64 | 65 | # dotenv environment variables file 66 | .env 67 | .env.test 68 | 69 | # parcel-bundler cache (https://parceljs.org/) 70 | .cache 71 | 72 | # next.js build output 73 | .next 74 | 75 | # nuxt.js build output 76 | .nuxt 77 | 78 | # vuepress build output 79 | .vuepress/dist 80 | 81 | # Serverless directories 82 | .serverless/ 83 | 84 | # FuseBox cache 85 | .fusebox/ 86 | 87 | # DynamoDB Local files 88 | .dynamodb/ 89 | 90 | # web-scripts generated files 91 | cjs/ 92 | esm/ 93 | types/ 94 | -------------------------------------------------------------------------------- /packages/web-scripts/config/lint-staged.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | const { getEslintConfig } = require('../cjs/Tasks/LintTask'); 17 | const { getPrettierConfig } = require('../cjs/Tasks/FormatTask'); 18 | const { getJestConfig } = require('../cjs/Tasks/TestTask'); 19 | 20 | const tests = process.env.WEB_SCRIPTS_RUN_TESTS === 'true'; 21 | const jestConfig = process.env.WEB_SCRIPTS_JEST_CONFIG || getJestConfig(); 22 | const prettierConfig = 23 | process.env.WEB_SCRIPTS_PRETTIER_CONFIG || getPrettierConfig(); 24 | const eslintConfig = process.env.WEB_SCRIPTS_ESLINT_CONFIG || getEslintConfig(); 25 | 26 | const testRelatedChanges = `jest ${ 27 | jestConfig ? `--config ${jestConfig} ` : '' 28 | }--bail --findRelatedTests --passWithNoTests`; 29 | 30 | const lintRelatedChanges = `eslint --fix ${ 31 | eslintConfig ? `--config ${eslintConfig}` : '' 32 | }`.trim(); 33 | 34 | const formatRelatedChanges = `prettier --write ${ 35 | prettierConfig ? `--config ${prettierConfig}` : '' 36 | }`.trim(); 37 | 38 | module.exports = { 39 | '*.{js,jsx,ts,tsx,json,md,yaml}': [formatRelatedChanges], 40 | '*.{js,jsx,ts,tsx}': [ 41 | lintRelatedChanges, 42 | ...(tests ? [testRelatedChanges] : []), 43 | ], 44 | }; 45 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/TestTask.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { default as spawn } from 'cross-spawn'; 17 | import { default as Debug } from 'debug'; 18 | import { SpawnSyncReturns } from 'child_process'; 19 | import { hasConfig } from '@spotify/web-scripts-utils'; 20 | 21 | import { TestTaskDesc } from '../SharedTypes'; 22 | import { JEST_CONFIG } from '../Paths'; 23 | 24 | const dbg = Debug('web-scripts:test'); // eslint-disable-line new-cap 25 | 26 | export function getJestConfig(): string | null { 27 | if ( 28 | !hasConfig([ 29 | { type: 'file', pattern: 'jest.config.js' }, 30 | { type: 'package.json', property: 'jest' }, 31 | ]) 32 | ) { 33 | return JEST_CONFIG; 34 | } 35 | 36 | return null; 37 | } 38 | 39 | export function testTask(task: TestTaskDesc): SpawnSyncReturns { 40 | // `coverageDirectory` is necessary because the root is `src` 41 | const cmd = 'npx'; 42 | const config = task.config || getJestConfig(); 43 | 44 | const args = [ 45 | '--no-install', 46 | 'jest', 47 | ...(config ? ['--config', config] : []), 48 | ...task.restOptions, 49 | ]; 50 | dbg('npx args %o', args); 51 | return spawn.sync(cmd, args, { stdio: 'inherit' }); 52 | } 53 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | # This release script determines if a publish should happen using a dry run of semantic release to determine if the 2 | # commits contain publishable changes (feat, bug, breaking change). If so, lerna will be used to perform the actual 3 | # publish, however, lerna also has its own logic for determining whether to publish. Specifically, it will run git diff 4 | # in each package, excluding markdown files, tests, etc. So any attempt to force a version bump with an empty commit or 5 | # readme tweak will fail. To get around this, we pass the `force-publish` option to lerna, skipping the git diff for 6 | # changed packages. This allows the semantic release dry run check to be the deciding factor for publishing. 7 | 8 | # this message is logged by semantic-release when one of the commits found by web-scripts should trigger a release 9 | expected_release_message="The release type for the commit is" 10 | 11 | echo "spotify/web-scripts: Running semantic-release in --dry-run to see if we should trigger a lerna release." 12 | yarn web-scripts release --dry-run | grep "${expected_release_message}" 13 | 14 | if [ $? -eq 0 ] 15 | then 16 | echo "spotify/web-scripts: A release will be triggered." 17 | echo "spotify/web-scripts: Configuring git for Github Actions Lerna publish..." 18 | git config --global user.email "no-reply@spotify.com" 19 | git config --global user.name "GitHub Action" 20 | git remote set-url origin "https://${GH_USERNAME}:${GH_TOKEN}@github.com/spotify/web-scripts.git" 21 | git checkout master 22 | echo "spotify/web-scripts: Configuring npm for publishing..." 23 | echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 24 | echo "spotify/web-scripts: Attempting publish..." 25 | npx lerna publish --yes --force-publish --ignore-scripts --conventional-commits --create-release=github --registry=https://registry.npmjs.org 26 | exit $? 27 | else 28 | echo "spotify/web-scripts: No release will be triggered." >&2 29 | exit 0 30 | fi 31 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/FormatTask/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { default as Debug } from 'debug'; 17 | import { default as spawn } from 'cross-spawn'; 18 | import { SpawnSyncReturns } from 'child_process'; 19 | import { hasConfig } from '@spotify/web-scripts-utils'; 20 | 21 | import { FormatTaskDesc } from '../../SharedTypes'; 22 | import { PRETTIER_CONFIG, CONSUMING_ROOT } from '../../Paths'; 23 | 24 | const dbg = Debug('web-scripts:format'); // eslint-disable-line new-cap 25 | 26 | export function getPrettierConfig(): string | null { 27 | if ( 28 | !hasConfig([ 29 | { type: 'file', pattern: '.prettierrc' }, 30 | { type: 'file', pattern: 'prettier.config.js' }, 31 | { type: 'package.json', property: 'prettierrc' }, 32 | ]) 33 | ) { 34 | return PRETTIER_CONFIG; 35 | } 36 | 37 | return null; 38 | } 39 | 40 | export function formatTask(task: FormatTaskDesc): SpawnSyncReturns { 41 | const cmd = 'npx'; 42 | const config = task.config || getPrettierConfig(); 43 | const path = task.path || `${CONSUMING_ROOT}/**/src`; 44 | 45 | const args = [ 46 | '--no-install', 47 | 'prettier', 48 | ...(config ? ['--config', config] : []), 49 | '--write', 50 | `${path}/**/*.{ts,tsx,js,jsx}`, 51 | ]; 52 | dbg('npx args %o', args); 53 | return spawn.sync(cmd, args, { stdio: 'inherit' }); 54 | } 55 | -------------------------------------------------------------------------------- /packages/web-scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@spotify/web-scripts", 3 | "version": "15.0.0", 4 | "license": "Apache-2.0", 5 | "description": "Build, lint, test, format, and release your JS/TS library.", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/spotify/web-scripts.git" 9 | }, 10 | "main": "cjs/index.js", 11 | "module": "esm/index.js", 12 | "types": "types", 13 | "bin": { 14 | "web-scripts": "./bin/web-scripts" 15 | }, 16 | "files": [ 17 | "bin", 18 | "cjs", 19 | "config", 20 | "esm", 21 | "types" 22 | ], 23 | "scripts": { 24 | "clean": "rm -rf cjs esm types", 25 | "build": "node ./bin/web-scripts build", 26 | "test": "node ./bin/web-scripts test", 27 | "lint": "node ./bin/web-scripts lint", 28 | "format": "node ./bin/web-scripts format", 29 | "bootstrap": "yarn run clean && tsc --allowJs --outDir cjs --noEmit false --module CommonJS", 30 | "prepublishOnly": "yarn run bootstrap && yarn run build" 31 | }, 32 | "dependencies": { 33 | "@commitlint/cli": "^17.6.3", 34 | "@commitlint/config-conventional": "^17.6.3", 35 | "@spotify/eslint-config": "^15.0.0", 36 | "@spotify/prettier-config": "^15.0.0", 37 | "@spotify/tsconfig": "^15.0.0", 38 | "@spotify/web-scripts-utils": "^15.0.0", 39 | "@types/cross-spawn": "^6.0.0", 40 | "@types/debug": "^4.1.2", 41 | "@types/jest": "^29.5.1", 42 | "@types/react": "^18.2.6", 43 | "commander": "^10.0.1", 44 | "commitizen": "^4.2.6", 45 | "cross-spawn-promise": "^0.10.1", 46 | "cz-conventional-changelog": "^3.3.0", 47 | "debug": "^4.1.1", 48 | "eslint": "^8.40.0", 49 | "jest": "^29.5.0", 50 | "jest-junit": "^16.0.0", 51 | "lint-staged": "^13.2.2", 52 | "prettier": "^2.8.8", 53 | "semantic-release": "^21.0.2", 54 | "ts-jest": "^29.1.0", 55 | "typescript": "^5.0.4" 56 | }, 57 | "devDependencies": { 58 | "@types/rimraf": "^3.0.0", 59 | "object.fromentries": "^2.0.0", 60 | "rimraf": "^3.0.0", 61 | "tempy": "^1.0.1" 62 | }, 63 | "publishConfig": { 64 | "access": "public" 65 | }, 66 | "engines": { 67 | "node": ">=18" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/eslint-config/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | const { hasConfig } = require('@spotify/web-scripts-utils'); 17 | 18 | const hasReact = hasConfig([ 19 | { type: 'dependency', dependency: 'react' }, 20 | { type: 'dependency', dependency: 'react', dependencyType: 'peer' }, 21 | ]); 22 | const hasTypescript = hasConfig([ 23 | { type: 'dependency', dependency: 'typescript' }, 24 | { type: 'dependency', dependency: 'typescript', dependencyType: 'dev' }, 25 | { type: 'file', pattern: 'tsconfig.json' }, 26 | ]); 27 | 28 | // We explicitly set the Jest version because auto-detection doesn't work in the monorepo. 29 | // Ref: https://github.com/jest-community/eslint-plugin-jest/pull/564/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5 30 | const settings = { 31 | jest: { 32 | version: 24, 33 | }, 34 | }; 35 | 36 | if (hasReact) { 37 | settings.react = { 38 | version: 'detect', 39 | }; 40 | } 41 | 42 | module.exports = { 43 | extends: [ 44 | '@spotify/eslint-config-base', 45 | hasReact ? '@spotify/eslint-config-react' : null, 46 | hasTypescript ? '@spotify/eslint-config-typescript' : null, 47 | 'prettier', 48 | 'plugin:jest/recommended', 49 | ].filter(s => !!s), 50 | parser: '@typescript-eslint/parser', 51 | env: { 52 | jest: true, 53 | }, 54 | parserOptions: { 55 | ecmaVersion: 2018, 56 | sourceType: 'module', 57 | }, 58 | settings, 59 | plugins: ['@spotify/eslint-plugin'], 60 | rules: { 61 | // no discouraged words 62 | '@spotify/best-practices/no-discouraged-words': 'error', 63 | }, 64 | }; 65 | -------------------------------------------------------------------------------- /packages/web-scripts/src/SharedTypes.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | type ThresholdLimits = 17 | | 'info' 18 | | 'low' 19 | | 'moderate' 20 | | 'high' 21 | | 'critical' 22 | | 'none'; 23 | 24 | export type TaskName = 25 | | 'init' 26 | | 'build' 27 | | 'test' 28 | | 'lint' 29 | | 'format' 30 | | 'commit' 31 | | 'commitmsg' 32 | | 'precommit' 33 | | 'release' 34 | | 'audit'; 35 | 36 | export type TaskDesc = { 37 | name: TaskName; 38 | restOptions: string[]; 39 | }; 40 | 41 | export type BuildTaskDesc = { 42 | name: 'build'; 43 | cjs: boolean; 44 | esm: boolean; 45 | types: boolean; 46 | } & TaskDesc; 47 | 48 | export type TestTaskDesc = { 49 | name: 'test'; 50 | config?: string; 51 | } & TaskDesc; 52 | 53 | export type LintTaskDesc = { 54 | name: 'lint'; 55 | config?: string; 56 | stylecheck: boolean; 57 | typecheck: boolean; 58 | } & TaskDesc; 59 | 60 | export type FormatTaskDesc = { 61 | name: 'format'; 62 | config?: string; 63 | path?: string; 64 | } & TaskDesc; 65 | 66 | export type CommitTaskDesc = { 67 | name: 'commit'; 68 | path: string; 69 | } & TaskDesc; 70 | 71 | export type CommitMsgTaskDesc = { 72 | name: 'commitmsg'; 73 | config: string; 74 | edit?: string; 75 | } & TaskDesc; 76 | 77 | export type ReleaseTaskDesc = { 78 | name: 'release'; 79 | } & TaskDesc; 80 | 81 | export type AuditTaskDesc = { 82 | name: 'audit'; 83 | threshold: ThresholdLimits; 84 | } & TaskDesc; 85 | 86 | export type PrecommitTaskDesc = { 87 | name: 'precommit'; 88 | tests: boolean; 89 | typecheck: boolean; 90 | eslintConfig: string; 91 | jestConfig: string; 92 | prettierConfig: string; 93 | } & TaskDesc; 94 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/FormatTask/index.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { join } from 'path'; 17 | 18 | import { promisify } from 'util'; 19 | import tempy from 'tempy'; 20 | import { 21 | mkdir as mkdirFS, 22 | readFile as readFileFS, 23 | writeFile as writeFileFS, 24 | } from 'fs'; 25 | 26 | import { formatTask } from '.'; 27 | 28 | const writeFile = promisify(writeFileFS); 29 | const readFile = promisify(readFileFS); 30 | const mkdir = promisify(mkdirFS); 31 | 32 | // @ts-ignore 33 | jest.spyOn(process, 'exit').mockImplementation(c => c); 34 | 35 | describe('web-scripts format', () => { 36 | let pkgRoot: string; 37 | let testFile: string; 38 | 39 | beforeEach(async () => { 40 | jest.clearAllMocks(); 41 | pkgRoot = tempy.directory(); 42 | 43 | const fixtureFile = join( 44 | __dirname, 45 | '__fixtures__', 46 | 'poorly-formatted-file.ts', 47 | ); 48 | testFile = join(pkgRoot, 'src', 'poorly-formatted-file.ts'); 49 | 50 | await mkdir(join(pkgRoot, 'src')); 51 | const content = (await readFile(fixtureFile)).toString(); 52 | await writeFile(testFile, content.replace(/\/\/ prettier-ignore[\n]+/, '')); 53 | }); 54 | 55 | afterAll(() => jest.restoreAllMocks()); 56 | 57 | it('formats files', async () => { 58 | const before = await readFile( 59 | join(pkgRoot, 'src', 'poorly-formatted-file.ts'), 60 | ); 61 | expect(before.toString().trim()).toBe('export const FOO = "bar"'); 62 | 63 | formatTask({ name: 'format', path: pkgRoot, restOptions: [] }); 64 | 65 | const after = await readFile( 66 | join(pkgRoot, 'src', 'poorly-formatted-file.ts'), 67 | ); 68 | expect(after.toString().trim()).toBe("export const FOO = 'bar';"); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/src/has-config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import glob from 'glob'; 17 | import readPkgUp from 'read-pkg-up'; 18 | 19 | import { getConsumingRoot } from './get-consuming-root'; 20 | import { hasKeyInObj } from './has-key-in-obj'; 21 | 22 | const getDependencyTypePath = ( 23 | dependency: string, 24 | type?: 'dev' | 'peer', 25 | ): string => { 26 | switch (type) { 27 | case 'dev': 28 | return `devDependencies.${dependency}`; 29 | case 'peer': 30 | return `peerDependencies.${dependency}`; 31 | default: 32 | return `dependencies.${dependency}`; 33 | } 34 | }; 35 | 36 | // this function can be used to determine whether a config exists, 37 | // either in package.json or as a file. 38 | export const hasConfig = ( 39 | sources: ( 40 | | { type: 'file'; pattern: string } 41 | | { type: 'package.json'; property: string } 42 | | { 43 | type: 'dependency'; 44 | dependency: string; 45 | dependencyType?: 'peer' | 'dev'; 46 | } 47 | )[], 48 | ): boolean => { 49 | const { path: pkgPath, packageJson } = readPkgUp.sync({ 50 | cwd: getConsumingRoot(), 51 | }) || { packageJson: {}, path: getConsumingRoot() }; 52 | const root = pkgPath.slice(0, pkgPath.length - '/package.json'.length); 53 | return sources.some(source => { 54 | switch (source.type) { 55 | case 'file': 56 | return !!glob.sync(source.pattern, { cwd: root }).length; 57 | case 'package.json': 58 | return hasKeyInObj(source.property, packageJson); 59 | case 'dependency': 60 | return hasKeyInObj( 61 | getDependencyTypePath(source.dependency, source.dependencyType), 62 | packageJson, 63 | ); 64 | default: 65 | return false; 66 | } 67 | }); 68 | }; 69 | -------------------------------------------------------------------------------- /packages/eslint-config-typescript/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | parser: '@typescript-eslint/parser', 18 | parserOptions: { 19 | sourceType: 'module', 20 | }, 21 | plugins: ['@typescript-eslint/eslint-plugin'], 22 | // camelcase, indent, no-array-constructor, and no-unused-vars are all 23 | // busted when using TypeScript at the moment. When you use this plugin, you're 24 | // forced to turn off the base rules from ESLint and turn on the TypeScript-friendly 25 | // variant that comes with @typescript-eslint/eslint-plugin. 26 | rules: { 27 | // camelcase interference fix. 28 | camelcase: 'off', 29 | '@typescript-eslint/naming-convention': 'off', 30 | // indent interference fix. 31 | indent: 'off', 32 | '@typescript-eslint/indent': ['error', 2, { SwitchCase: 1 }], 33 | // no-array-constructor interference fix. 34 | 'no-array-constructor': 'off', 35 | '@typescript-eslint/no-array-constructor': 'error', 36 | // no-unused-vars interference fix. 37 | 'no-unused-vars': 'off', 38 | '@typescript-eslint/no-unused-vars': 'off', 39 | // no-useless-constructor interference fix. 40 | 'no-useless-constructor': 'off', 41 | '@typescript-eslint/no-useless-constructor': 'error', 42 | // semi interference fix. 43 | semi: 'off', 44 | '@typescript-eslint/semi': 'warn', 45 | // no-shadow interference fix. 46 | 'no-shadow': 'off', 47 | '@typescript-eslint/no-shadow': 'error', 48 | // no-redeclare interference fix. 49 | 'no-redeclare': 'off', 50 | '@typescript-eslint/no-redeclare': 'error', 51 | // no-use-before-define interference fix. 52 | // allow functions to be defined after they're used 53 | 'no-use-before-define': 'off', 54 | '@typescript-eslint/no-use-before-define': ['error', 'nofunc'], 55 | }, 56 | }; 57 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import path from 'path'; 17 | import fs from 'fs-extra'; 18 | import execa from 'execa'; 19 | import chalk from 'chalk'; 20 | import readPkgUp from 'read-pkg-up'; 21 | 22 | import * as messages from './messages'; 23 | import getInstallCmd from './get-install-cmd'; 24 | 25 | // console.log is used here to make sure that logs make it to the user 26 | /* eslint-disable no-console */ 27 | export default async function createWebScriptsLibrary(projectName?: string) { 28 | if (!projectName) { 29 | throw new Error(messages.missingProjectName()); 30 | } 31 | 32 | if (fs.existsSync(projectName) && projectName !== '.') { 33 | throw new Error(messages.alreadyExists(projectName)); 34 | } 35 | 36 | const { packageJson: cwslPkg } = 37 | readPkgUp.sync({ 38 | cwd: __dirname, 39 | }) || {}; 40 | 41 | const projectPath = path.resolve(process.cwd(), projectName); 42 | const templatePath = path.resolve(__dirname, '..', 'template'); 43 | 44 | console.log(chalk.gray('Copying template...')); 45 | await fs.copy(templatePath, projectPath); 46 | 47 | console.log(chalk.gray('Writing over necessary files...')); 48 | process.chdir(projectPath); 49 | const newPkgPath = path.join(projectPath, 'package.json'); 50 | const newPkg = require(newPkgPath); 51 | newPkg.name = projectName; 52 | newPkg.devDependencies['@spotify/web-scripts'] = 53 | (cwslPkg?.devDependencies || {})['@spotify/web-scripts'] || 54 | newPkg.devDependencies['@spotify/web-scripts']; 55 | await fs.writeFile(newPkgPath, JSON.stringify(newPkg, null, 2)); 56 | 57 | console.log(chalk.gray('Installing dependencies...')); 58 | process.chdir(projectPath); 59 | await execa(getInstallCmd(), ['install']); 60 | 61 | console.log(messages.start(projectName)); 62 | } 63 | /* eslint-enable no-console */ 64 | -------------------------------------------------------------------------------- /packages/eslint-config-base/es6.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | env: { 18 | es6: true, 19 | }, 20 | parserOptions: { 21 | ecmaVersion: 2018, 22 | sourceType: 'module', 23 | ecmaFeatures: { 24 | jsx: true, 25 | }, 26 | }, 27 | rules: { 28 | // require parens in arrow function arguments 29 | 'arrow-parens': 0, 30 | // require space before/after arrow function's arrow 31 | 'arrow-spacing': 0, 32 | // verify super() callings in constructors 33 | 'constructor-super': 0, 34 | // enforce the spacing around the * in generator functions 35 | 'generator-star-spacing': 0, 36 | // disallow modifying variables of class declarations 37 | 'no-class-assign': 0, 38 | // disallow modifying variables that are declared using const 39 | 'no-const-assign': 2, 40 | // disallow to use this/super before super() calling in constructors. 41 | 'no-this-before-super': 0, 42 | // disallow empty constructors and constructors that only delegate into the parent class. 43 | 'no-useless-constructor': 2, 44 | // require let or const instead of var 45 | 'no-var': 2, 46 | // require method and property shorthand syntax for object literals 47 | 'object-shorthand': 0, 48 | // suggest using of const declaration for variables that are never modified after declared 49 | 'prefer-const': 2, 50 | // suggest using the spread operator instead of .apply() 51 | 'prefer-spread': 0, 52 | // suggest using Reflect methods where applicable 53 | 'prefer-reflect': 0, 54 | // suggest using template strings instead of concatenation or joining 55 | 'prefer-template': 2, 56 | // disallow generator functions that do not have yield 57 | 'require-yield': 0, 58 | // disallow trailing commas in object literals 59 | 'comma-dangle': [2, 'always-multiline'], 60 | }, 61 | }; 62 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/AuditTasks/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { default as spawn } from 'cross-spawn-promise'; 17 | import { default as Debug } from 'debug'; 18 | 19 | import { AuditTaskDesc } from '../../SharedTypes'; 20 | import { CONSUMING_ROOT } from '../../Paths'; 21 | 22 | const dbg = Debug('web-scripts:audit'); // eslint-disable-line new-cap 23 | 24 | enum ThresholdLimits { 25 | info = 1, 26 | low = 2, 27 | moderate = 4, 28 | high = 8, 29 | critical = 16, 30 | none = 32, 31 | } 32 | 33 | export async function auditTask(task: AuditTaskDesc): Promise { 34 | const fns = [yarnRun]; 35 | 36 | return await Promise.all( 37 | fns.map(async fn => { 38 | dbg('Beginning %s task', fn.name); 39 | const stdout = await fn(task); 40 | dbg('Finished %s task', fn.name); 41 | return stdout; 42 | }), 43 | ); 44 | } 45 | 46 | /** 47 | * This task will run yarn audit at the location from which it was called. 48 | * Yarn audit returns a status code which is the sum of the following masks: 49 | * 1 for INFO 50 | * 2 for LOW 51 | * 4 for MODERATE 52 | * 8 for HIGH 53 | * 16 for CRITICAL 54 | * 55 | * The threshold ceiling is therefore 31. The default value of the threshold 56 | * is 32, returning 0 exit status unless a threshold option is set. 57 | * @see https://yarnpkg.com/lang/en/docs/cli/audit/ 58 | */ 59 | async function yarnRun(task: AuditTaskDesc): Promise { 60 | const cmd = 'npx'; 61 | const { threshold } = task; 62 | 63 | const args = [ 64 | '--no-install', 65 | 'yarn', 66 | 'audit', 67 | '--cwd', 68 | CONSUMING_ROOT, 69 | ...task.restOptions, 70 | ]; 71 | dbg('npx args %o', args); 72 | 73 | try { 74 | await spawn(cmd, args, { stdio: 'inherit' }); 75 | } catch (err) { 76 | const thresholdReached = 77 | (err as any).exitStatus >= ThresholdLimits[threshold]; 78 | if (thresholdReached) process.exit((err as any).exitStatus); 79 | } 80 | 81 | return ''; 82 | } 83 | -------------------------------------------------------------------------------- /packages/eslint-plugin/src/rules/best-practices/no-discouraged-words.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Rule } from 'eslint'; 18 | import { TSESTree } from '@typescript-eslint/types'; 19 | import { createDocsUrl } from '../../util/helpers'; 20 | 21 | /** 22 | * List of discouraged words in the form of RegEx (regular expressions). 23 | */ 24 | const discouragedWords = ['blacklist', 'whitelist']; 25 | 26 | const rule: Rule.RuleModule = { 27 | meta: { 28 | docs: { 29 | category: 'Best Practices', 30 | description: 'Prevent use of discouraged words.', 31 | url: createDocsUrl('best-practices/no-discouraged-words.md'), 32 | }, 33 | schema: [], 34 | fixable: 'code', 35 | type: 'suggestion', 36 | }, 37 | create(context: Rule.RuleContext) { 38 | return { 39 | // This checks all the JS comments for use of discouraged word. This line is an example of a comment. 40 | Program(): void { 41 | const comments = context.getSourceCode().getAllComments(); 42 | comments.forEach(comment => { 43 | const commentText = comment.value; 44 | const commentTextViolation = discouragedWords.find(word => 45 | commentText.match(new RegExp(word, 'i')), 46 | ); 47 | 48 | if (!commentTextViolation) { 49 | // There is no violation here. 50 | return; 51 | } 52 | 53 | context.report({ 54 | // @ts-ignore 55 | node: comment, 56 | message: `Usage of the word "${commentTextViolation}" is strongly discouraged. Please use a different word.`, 57 | }); 58 | }); 59 | }, 60 | 61 | // This checks all the JS syntax for use of discouraged words. 62 | Identifier(node: TSESTree.Identifier) { 63 | const variableName = node.name; 64 | const variableNameViolation = discouragedWords.find(word => 65 | variableName.match(new RegExp(word, 'i')), 66 | ); 67 | 68 | if (!variableNameViolation) { 69 | // There is no violation here 70 | return; 71 | } 72 | 73 | // Report it as an error to ESLint 74 | context.report({ 75 | node, 76 | message: `Usage of the word "${variableNameViolation}" is strongly discouraged. Please use a different word.`, 77 | }); 78 | }, 79 | } as Rule.RuleListener; 80 | }, 81 | }; 82 | 83 | export default rule; 84 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/src/has-config.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | jest.mock('./get-consuming-root'); 17 | 18 | import path from 'path'; 19 | import { hasConfig } from './has-config'; 20 | 21 | const { getConsumingRoot } = jest.requireMock('./get-consuming-root'); 22 | 23 | describe('hasConfig', () => { 24 | beforeEach(() => { 25 | getConsumingRoot.mockReturnValue( 26 | path.join(__dirname, '..', '__fixtures__', 'demo-lib'), 27 | ); 28 | }); 29 | it('works for a file', () => { 30 | expect(hasConfig([{ type: 'file', pattern: 'tsconfig.json' }])).toBe(true); 31 | }); 32 | 33 | it('works for a package.json property', () => { 34 | expect(hasConfig([{ type: 'package.json', property: 'name' }])).toBe(true); 35 | }); 36 | 37 | it('works for a nested package.json property', () => { 38 | expect( 39 | hasConfig([ 40 | { type: 'package.json', property: 'jest.collectCoverageFrom' }, 41 | ]), 42 | ).toBe(true); 43 | }); 44 | 45 | it('works for a dependency', () => { 46 | expect(hasConfig([{ type: 'dependency', dependency: 'react' }])).toBe(true); 47 | }); 48 | 49 | it('works for a dev dependency', () => { 50 | expect( 51 | hasConfig([ 52 | { 53 | type: 'dependency', 54 | dependency: '@testing-library/react', 55 | dependencyType: 'dev', 56 | }, 57 | ]), 58 | ).toBe(true); 59 | }); 60 | 61 | it('works for a peer dependency', () => { 62 | expect( 63 | hasConfig([ 64 | { 65 | type: 'dependency', 66 | dependency: 'styled-components', 67 | dependencyType: 'peer', 68 | }, 69 | ]), 70 | ).toBe(true); 71 | }); 72 | 73 | it('works when some fail and some succeed', () => { 74 | expect( 75 | hasConfig([ 76 | { 77 | type: 'dependency', 78 | dependency: 'react', 79 | }, 80 | { 81 | type: 'dependency', 82 | dependency: 'react', 83 | dependencyType: 'peer', 84 | }, 85 | ]), 86 | ).toBe(true); 87 | }); 88 | 89 | it('fails when all fail', () => { 90 | expect( 91 | hasConfig([ 92 | { 93 | type: 'dependency', 94 | dependency: 'angular', 95 | }, 96 | { 97 | type: 'dependency', 98 | dependency: 'angular', 99 | dependencyType: 'peer', 100 | }, 101 | ]), 102 | ).toBe(false); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/LintTask.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { default as spawn } from 'cross-spawn-promise'; 17 | import { default as Debug } from 'debug'; 18 | import { hasConfig } from '@spotify/web-scripts-utils'; 19 | 20 | import { LintTaskDesc } from '../SharedTypes'; 21 | import { CONSUMING_ROOT, ESLINT_CONFIG } from '../Paths'; 22 | import { getPrettierConfig } from './FormatTask'; 23 | 24 | const dbg = Debug('web-scripts:lint'); // eslint-disable-line new-cap 25 | 26 | export function getEslintConfig(): string | null { 27 | if ( 28 | !hasConfig([ 29 | { type: 'file', pattern: '.eslintrc.*' }, 30 | { type: 'package.json', property: 'eslintConfig' }, 31 | ]) 32 | ) { 33 | return ESLINT_CONFIG; 34 | } 35 | 36 | return null; 37 | } 38 | 39 | export async function lintTask(task: LintTaskDesc): Promise { 40 | const fns = [eslintRun]; 41 | if (task.typecheck) fns.push(typeCheck); 42 | if (task.stylecheck) fns.push(styleCheck); 43 | 44 | return await Promise.all( 45 | fns.map(async fn => { 46 | dbg('Beginning %s task', fn.name); 47 | const stdout = await fn(task); 48 | dbg('Finished %s task', fn.name); 49 | return stdout; 50 | }), 51 | ); 52 | } 53 | 54 | export async function eslintRun(task: LintTaskDesc): Promise { 55 | const cmd = 'npx'; 56 | const config = task.config || getEslintConfig(); 57 | 58 | const args = [ 59 | '--no-install', 60 | 'eslint', 61 | '--ext', 62 | 'js,ts,jsx,tsx', 63 | CONSUMING_ROOT, 64 | '--ignore-pattern', 65 | 'types/', 66 | '--ignore-pattern', 67 | 'cjs/', 68 | '--ignore-pattern', 69 | 'esm/', 70 | ...(config ? ['--config', config] : []), 71 | ...task.restOptions, 72 | ]; 73 | dbg('npx args %o', args); 74 | 75 | const stdout = await spawn(cmd, args, { stdio: 'inherit' }); 76 | return (stdout || '').toString(); 77 | } 78 | 79 | export async function typeCheck(): Promise { 80 | const cmd = 'npx'; 81 | const args = ['tsc', '--noEmit']; 82 | const stdout = await spawn(cmd, args, { stdio: 'inherit' }); 83 | return (stdout || '').toString(); 84 | } 85 | 86 | export async function styleCheck(): Promise { 87 | const cmd = 'npx'; 88 | const args = ['--no-install', 'prettier']; 89 | 90 | const config = getPrettierConfig(); 91 | if (config) { 92 | args.push('--config', config); 93 | } 94 | 95 | args.push('--check', `${CONSUMING_ROOT}/**/src/**/*.{ts,tsx,js,jsx}`); 96 | const stdout = await spawn(cmd, args, { stdio: 'inherit' }); 97 | return (stdout || '').toString(); 98 | } 99 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/AuditTasks/index.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { join } from 'path'; 17 | 18 | import { auditTask } from '.'; 19 | 20 | // @ts-ignore 21 | jest.spyOn(process, 'exit').mockImplementation(c => c); 22 | 23 | jest.mock('cross-spawn-promise', () => jest.fn()); 24 | 25 | const spawn: jest.Mock = jest.requireMock('cross-spawn-promise'); 26 | 27 | class AuditError extends Error { 28 | public exitStatus: number; 29 | constructor(message: string, exitStatus: number) { 30 | super(message); 31 | this.exitStatus = exitStatus; 32 | } 33 | } 34 | 35 | /** 36 | * WARNING: 37 | * These tests have some issues with being potentially non-deterministic. 38 | * Due to a network dependency on npmjs.com this test could potentially fail 39 | * should there be any downtime with external services used by with yarn audit. 40 | * 41 | * Should these tests begin to fail suddenly, it might be worth trading test coverage 42 | * confidence for test reliability by mocking the network calls made by yarn audit. 43 | */ 44 | describe('web-scripts audit', () => { 45 | beforeEach(() => jest.clearAllMocks()); 46 | afterAll(() => jest.restoreAllMocks()); 47 | 48 | test.each` 49 | violations | threshold | status 50 | ${0} | ${undefined} | ${0} 51 | ${0} | ${'none'} | ${0} 52 | ${12} | ${undefined} | ${0} 53 | ${12} | ${'none'} | ${0} 54 | ${12} | ${'low'} | ${12} 55 | ${12} | ${'moderate'} | ${12} 56 | ${12} | ${'high'} | ${12} 57 | ${12} | ${'critical'} | ${0} 58 | ${30} | ${undefined} | ${0} 59 | ${30} | ${'none'} | ${0} 60 | ${30} | ${'low'} | ${30} 61 | ${30} | ${'moderate'} | ${30} 62 | ${30} | ${'high'} | ${30} 63 | ${30} | ${'critical'} | ${30} 64 | `( 65 | 'return status code $status when audited dependencies have $violations violations and $threshold threshold', 66 | async ({ violations, threshold, status }) => { 67 | const source = join(__dirname, '__fixtures__', violations.toString()); 68 | 69 | if (violations) { 70 | spawn.mockRejectedValueOnce( 71 | new AuditError('audit failure found', violations), 72 | ); 73 | } else { 74 | spawn.mockResolvedValueOnce(null); 75 | } 76 | 77 | await auditTask({ 78 | name: 'audit', 79 | threshold, 80 | // Overrides implementation logic for CWD 81 | restOptions: ['--cwd', source], 82 | }); 83 | 84 | /* eslint jest/no-conditional-expect: off */ 85 | if (status) expect(process.exit).toHaveBeenCalledWith(status); 86 | else expect(process.exit).not.toHaveBeenCalled(); 87 | }, 88 | ); 89 | }); 90 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/BuildTask.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { BuildTaskDesc } from '../SharedTypes'; 17 | 18 | import { default as Debug } from 'debug'; 19 | import { default as spawn } from 'cross-spawn-promise'; 20 | const dbg = Debug('web-scripts:build'); // eslint-disable-line new-cap 21 | 22 | // Pretty sure I have to use the tsconfig in the root of the calling 23 | // project, since the "include" key resolves the folder relative to the 24 | // tsconfig location, not the process.cwd(). Manually specifying it would 25 | // force this CLI to have to build the config up manually as well. Something 26 | // I don't really want to do. 27 | export async function buildTask(task: BuildTaskDesc): Promise { 28 | const fns = []; 29 | 30 | if (!task.cjs && !task.esm && !task.types) { 31 | // default is all! 32 | fns.push(buildTypes, buildCJS, buildESM); 33 | } else { 34 | if (task.types) fns.push(buildTypes); 35 | if (task.esm) fns.push(buildESM); 36 | if (task.cjs) fns.push(buildCJS); 37 | } 38 | 39 | return Promise.all( 40 | fns.map(async fn => { 41 | dbg('Beginning %s task', fn.name); 42 | const result = await fn(task); 43 | dbg('Finished %s task', fn.name); 44 | return result; 45 | }), 46 | ); 47 | } 48 | 49 | async function buildTypes(task: BuildTaskDesc): Promise { 50 | const cmd = 'npx'; 51 | const args = [ 52 | 'tsc', 53 | '--declaration', 54 | '--declarationMap', 55 | '--isolatedModules', 56 | 'false', 57 | '--outDir', 58 | 'types', 59 | '--emitDeclarationOnly', 60 | '--noEmit', 61 | 'false', 62 | '--module', 63 | 'CommonJS', 64 | ...task.restOptions, 65 | ]; 66 | const stdout = await spawn(cmd, args, { stdio: 'inherit' }); 67 | return (stdout || '').toString(); 68 | } 69 | 70 | async function buildCJS(task: BuildTaskDesc): Promise { 71 | const cmd = 'npx'; 72 | const args = [ 73 | 'tsc', 74 | '--declaration', 75 | 'false', 76 | '--allowJs', 77 | '--outDir', 78 | 'cjs', 79 | '--noEmit', 80 | 'false', 81 | '--module', 82 | 'CommonJS', 83 | ...task.restOptions, 84 | ]; 85 | const stdout = await spawn(cmd, args, { stdio: 'inherit' }); 86 | return (stdout || '').toString(); 87 | } 88 | 89 | async function buildESM(task: BuildTaskDesc): Promise { 90 | const cmd = 'npx'; 91 | const args = [ 92 | 'tsc', 93 | '--declaration', 94 | 'false', 95 | '--allowJs', 96 | '--outDir', 97 | 'esm', 98 | '--noEmit', 99 | 'false', 100 | '--module', 101 | 'ES2015', 102 | ...task.restOptions, 103 | ]; 104 | const stdout = await spawn(cmd, args, { stdio: 'inherit' }); 105 | return (stdout || '').toString(); 106 | } 107 | -------------------------------------------------------------------------------- /packages/create-web-scripts-library/src/integration.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import tempy from 'tempy'; 17 | import path from 'path'; 18 | import execa from 'execa'; 19 | import fs from 'fs-extra'; 20 | 21 | import createWebScriptsLibrary from '.'; 22 | import getInstallCmd from './get-install-cmd'; 23 | 24 | describe('integration test', () => { 25 | let PKG_ROOT: string; 26 | let LIBRARY_NAME: string; 27 | let LIBRARY_ROOT: string; 28 | let INSTALL_CMD: string; 29 | 30 | describe('succesful create', () => { 31 | // using a beforeAll instead of beforeEach for this test, which ensures that the tests run quickly 32 | // this IS a risky testing strategy. Inside this describe block, we need to avoid doing destructive operations. 33 | beforeAll(async () => { 34 | PKG_ROOT = tempy.directory(); 35 | LIBRARY_NAME = 'my-cool-library'; 36 | LIBRARY_ROOT = path.join(PKG_ROOT, LIBRARY_NAME); 37 | process.chdir(PKG_ROOT); 38 | INSTALL_CMD = getInstallCmd(); 39 | 40 | // create a single library and then assert against it 41 | await createWebScriptsLibrary(LIBRARY_NAME); 42 | }, 60000); 43 | 44 | it('replace the package.json name with the correct name', async () => { 45 | // check the package.json name replacement 46 | const pkgPath = path.join(LIBRARY_ROOT, 'package.json'); 47 | expect(fs.existsSync(pkgPath)).toBe(true); 48 | expect(require(pkgPath).name).toBe(LIBRARY_NAME); 49 | }); 50 | 51 | // check that all the commands work 52 | [ 53 | { cmd: 'lint', asyncTimeout: 20000 }, 54 | { cmd: 'test', asyncTimeout: 30000 }, 55 | { cmd: 'build', asyncTimeout: 60000 }, 56 | ].forEach( 57 | ({ 58 | cmd, 59 | asyncTimeout = 10000, 60 | }: { 61 | cmd: string; 62 | asyncTimeout?: number; 63 | }) => { 64 | it( 65 | `scaffolds such that "${cmd}" command runs successfully`, 66 | async () => { 67 | await expect( 68 | execa(INSTALL_CMD, ['run', cmd], { cwd: LIBRARY_ROOT }), 69 | ).resolves.toBeDefined(); 70 | }, 71 | asyncTimeout, 72 | ); 73 | }, 74 | ); 75 | }); 76 | 77 | describe('failure cases', () => { 78 | beforeEach(() => { 79 | PKG_ROOT = tempy.directory(); 80 | LIBRARY_NAME = 'my-cool-library'; 81 | LIBRARY_ROOT = path.join(PKG_ROOT, LIBRARY_NAME); 82 | process.chdir(PKG_ROOT); 83 | INSTALL_CMD = getInstallCmd(); 84 | }); 85 | 86 | it('fails when the library name is missing', async () => { 87 | await expect(createWebScriptsLibrary()).rejects.toEqual( 88 | expect.any(Error), 89 | ); 90 | }); 91 | 92 | it('fails when a directory already exists', async () => { 93 | await fs.mkdir(path.join(PKG_ROOT, LIBRARY_NAME)); 94 | await expect(createWebScriptsLibrary()).rejects.toEqual( 95 | expect.any(Error), 96 | ); 97 | }); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /packages/eslint-config-react/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | module.exports = { 17 | plugins: ['react', 'react-hooks', 'jsx-a11y'], 18 | parserOptions: { 19 | ecmaFeatures: { 20 | jsx: true, 21 | }, 22 | }, 23 | extends: ['plugin:jsx-a11y/recommended'], 24 | rules: { 25 | // Prevent missing displayName in a React component definition 26 | 'react/display-name': 0, 27 | // Enforce boolean attributes notation in JSX 28 | 'react/jsx-boolean-value': 2, 29 | // Enforce or disallow spaces inside of curly braces in JSX attributes 30 | 'react/jsx-curly-spacing': 0, 31 | // Enforce or disallow react string props to be wrapped in curly braces 32 | 'react/jsx-curly-brace-presence': 2, 33 | // Prevent duplicate props in JSX 34 | 'react/jsx-no-duplicate-props': 0, 35 | // Disallow undeclared variables in JSX 36 | 'react/jsx-no-undef': 0, 37 | // Enforce quote style for JSX attributes 38 | 'react/jsx-quotes': 0, 39 | // Enforce propTypes declarations alphabetical sorting 40 | 'react/jsx-sort-prop-types': 0, 41 | // Enforce props alphabetical sorting 42 | 'react/jsx-sort-props': 0, 43 | // Prevent React to be incorrectly marked as unused 44 | 'react/jsx-uses-react': 2, 45 | // Prevent variables used in JSX to be incorrectly marked as unused 46 | 'react/jsx-uses-vars': 2, 47 | // Prevent missing parentheses around multilines JSX 48 | 'react/jsx-wrap-multilines': 2, 49 | // Enforce react rules of hooks 50 | 'react-hooks/rules-of-hooks': 2, 51 | // Enforce the list of dependencies for hooks is correct 52 | 'react-hooks/exhaustive-deps': 2, 53 | // Prevent usage of dangerous JSX properties 54 | 'react/no-danger': 0, 55 | // Prevent usage of setState in componentDidMount 56 | 'react/no-did-mount-set-state': 0, 57 | // Prevent usage of setState in componentDidUpdate 58 | 'react/no-did-update-set-state': 2, 59 | // Prevent multiple component definition per file 60 | 'react/no-multi-comp': [2, { ignoreStateless: true }], 61 | // Prevent usage of unknown DOM property 62 | 'react/no-unknown-property': 2, 63 | // Prevent missing props validation in a React component definition 64 | 'react/prop-types': 0, 65 | // Prevent missing React when using JSX 66 | 'react/react-in-jsx-scope': 2, 67 | // Restrict file extensions that may be required 68 | 'react/require-extension': 0, 69 | // Prevent extra closing tags for components without children 70 | 'react/self-closing-comp': 2, 71 | // Enforce component methods order 72 | 'react/sort-comp': [ 73 | 2, 74 | { 75 | order: [ 76 | 'statics', 77 | 'static-variables', 78 | 'static-methods', 79 | 'instance-variables', 80 | 'constructor', 81 | 'getChildContext', 82 | 'componentDidMount', 83 | 'shouldComponentUpdate', 84 | 'getSnapshotBeforeUpdate', 85 | 'componentDidUpdate', 86 | 'componentWillUnmount', 87 | 'componentDidCatch', 88 | '/^handle.+$/', 89 | '/^on.+$/', 90 | 'everything-else', 91 | '/^render.+$/', 92 | 'render', 93 | ], 94 | }, 95 | ], 96 | }, 97 | }; 98 | -------------------------------------------------------------------------------- /packages/tsconfig/docs/examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | ## Getting started 4 | 5 | This project outputs a single tsconfig.json file for use. This file is configured to disable all output options (`declaration` is `false`, `noEmit` is true) and is set to strictly type check your code (for example, `noImplicitAny` and many other strict type checks). It is likely that you will need to import this file and do a little configuration additionally depending on whether you plan to use this configuration in conjunction with Webpack or Babel, or whether you plan to use `tsc` to output artifacts. 6 | 7 | ### Questions to answer 8 | 9 | 1. Do you have a full TypeScript project (e.g. is your project brand new or is it sufficiently small that you can convert the whole thing at once)? 10 | 2. Do you need to keep using Babel to transpile an existing project, or can you use `tsc` (the TypeScript compiler that is installed when you add `typescript` as a Node dependency) to keep your build simple? 11 | 3. Is your project a library, which means it needs to compile in a way that other TypeScript projects can use the types from it, or is it an app, which means it likely has JSX and that there is no need to export declarations? 12 | 13 | ### Overriding options 14 | 15 | Use the `"extends"` option in your tsconfig.json to extend the appropriate config. 16 | 17 | ## Apps 18 | 19 | This setup assumes that Create React App, Next, Webpack, and/or Babel will transpile your bundled assets (aka `tsc` is not used for emitting transpiled code, only for type-checking). 20 | 21 | Extend your `tsconfig.json`: 22 | 23 | ```json 24 | { 25 | "extends": "@spotify/tsconfig" 26 | } 27 | ``` 28 | 29 | ### Create React App 30 | 31 | Use our [Create React App guide](./guides/cra.md). 32 | 33 | ### Next.js 34 | 35 | Use our [Next.js guide](./guides/next.md). 36 | 37 | ### Babel 38 | 39 | When using Babel, use [@babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript) to load TypeScript files. If you use the Babel CLI directly, make sure to include `--extensions ".js,.ts,.tsx"`. 40 | 41 | ### Webpack 42 | 43 | If using Babel with Webpack, use [@babel/preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript) as described above. Then, in your Webpack config, be sure to update the `test` regular expression which `babel-loader` is using to include your `ts` and `tsx` files. 44 | 45 | If you don't use `babel-loader` or you prefer for it not to handle your TypeScript, you can use `ts-loader` instead. 46 | 47 | ```bash 48 | yarn add -D ts-loader 49 | ``` 50 | 51 | Make sure to add the TypeScript filetypes and `ts-loader` to your Webpack config. 52 | 53 | ```js 54 | module.exports = { 55 | // ... 56 | resolve: { 57 | extensions: ['.ts', '.tsx', '.js'], 58 | }, 59 | module: { 60 | rules: [{ test: /\.(ts|tsx)$/, loader: 'ts-loader' }], 61 | }, 62 | // ... 63 | }; 64 | ``` 65 | 66 | **IMPORTANT** You will need to turn off `noEmit` when using `ts-loader` with `@spotify/tsconfig`: 67 | 68 | ```json 69 | { 70 | "extends": "@spotify/tsconfig", 71 | "compilerOptions": { 72 | "noEmit": false 73 | } 74 | } 75 | ``` 76 | 77 | ## Libraries 78 | 79 | ### @spotify/web-scripts 80 | 81 | With one command, [`web-scripts build`](https://github.com/spotify/web-scripts/tree/master/packages/web-scripts#the-build-script) takes your TypeScript code and outputs types, esm, and cjs files ready for publishing. It's probably want you want! 82 | 83 | If you want or need to manually control how your library is built using our shared configs, read on. 84 | 85 | ### Manual builds 86 | 87 | Assumes the library will be consumed as a node module by an app that will provide, if needed, polyfills for platforms lacking in ES6/2015 support. For example, this config will not transpile `async`/`await`. It will assume the consuming platform either supports those features natively or provides transpilation / polyfills. 88 | 89 | This config also assumes that `tsc` (the TypeScript compiler) is responsible for emitting / transpiling the TS -> JS (and providing type declaration files). 90 | 91 | Essentially, this config takes the base config and extends it to output Common JS modules and the corresponding type definitions. 92 | 93 | ```json 94 | { 95 | "extends": "@spotify/tsconfig", 96 | "include": ["src"], 97 | "compilerOptions": { 98 | "noEmit": false, 99 | "outDir": "dist", 100 | "declaration": true, 101 | "declarationMap": true, 102 | "jsx": "react", 103 | "lib": ["es6", "dom"], 104 | "module": "commonjs", 105 | "sourceMap": true, 106 | "target": "es6" 107 | } 108 | } 109 | ``` 110 | 111 | Run `tsc -p tsconfig.json` to see your output. 112 | -------------------------------------------------------------------------------- /packages/eslint-plugin/src/rules/best-practices/no-discouraged-words.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import rule from './no-discouraged-words'; 18 | import { createRuleTester } from '../../util/testHelpers'; 19 | 20 | const defaultErrorMessageWithWord = (word: string): string => 21 | `Usage of the word "${word}" is strongly discouraged. Please use a different word.`; 22 | 23 | createRuleTester().run('best-practices/no-discouraged-words', rule, { 24 | valid: [ 25 | { 26 | code: 'var foo = () => {};', 27 | }, 28 | { 29 | code: 'var foo: String = () => {};', 30 | }, 31 | { 32 | code: 'var foo: String = () => ({} as ExampleObject);', 33 | }, 34 | { 35 | // We currently don't do "advanced" checking of the discouraged words. That's something we can add over time. 36 | code: 'var black_list = "";', 37 | }, 38 | { 39 | // This plugin only covers variable naming. It's unclear if there are unexpected side effects if we flat out ban the words. 40 | // In the future, if we see there is not, let's check the entire codebase and avoid them. 41 | code: 'var foo = "blacklist";', 42 | }, 43 | { 44 | code: "/* Hello world. I'm using no discouraged words. */", 45 | }, 46 | ], 47 | invalid: [ 48 | { 49 | code: 'var whitelist = "";', 50 | errors: [defaultErrorMessageWithWord('whitelist')], 51 | }, 52 | { 53 | code: 'var blacklist = "";', 54 | errors: [defaultErrorMessageWithWord('blacklist')], 55 | }, 56 | { 57 | code: 'var foo = blacklist => "";', 58 | errors: [defaultErrorMessageWithWord('blacklist')], 59 | }, 60 | { 61 | code: 'var foo = _blacklist => "";', 62 | errors: [defaultErrorMessageWithWord('blacklist')], 63 | }, 64 | { 65 | code: 'var foo = (bar: Blacklist) => "";', 66 | errors: [defaultErrorMessageWithWord('blacklist')], 67 | }, 68 | { 69 | code: 'var foo = bar => "" as Blacklist;', 70 | errors: [defaultErrorMessageWithWord('blacklist')], 71 | }, 72 | { 73 | code: 'var bLacKLisT = "";', 74 | errors: [defaultErrorMessageWithWord('blacklist')], 75 | }, 76 | { 77 | code: 'var _blacklist = "";', 78 | errors: [defaultErrorMessageWithWord('blacklist')], 79 | }, 80 | { 81 | code: 'var wordsWithBlacklistAndAfter = "";', 82 | errors: [defaultErrorMessageWithWord('blacklist')], 83 | }, 84 | { 85 | code: 'var { blacklist } = {};', 86 | // Because this translates to '{ var blacklist: blacklist } = {}' the plugin reports the error twice 87 | errors: [ 88 | defaultErrorMessageWithWord('blacklist'), 89 | defaultErrorMessageWithWord('blacklist'), 90 | ], 91 | }, 92 | { 93 | code: 'var blacklist = {}; console.log(blacklist);', 94 | // Because we're using the word twice in the syntax, it'll report twice. Maybe we can clear this up later. 95 | errors: [ 96 | defaultErrorMessageWithWord('blacklist'), 97 | defaultErrorMessageWithWord('blacklist'), 98 | ], 99 | }, 100 | { 101 | code: 'var { blacklist: name } = {};', 102 | errors: [defaultErrorMessageWithWord('blacklist')], 103 | }, 104 | { 105 | code: 'var { name: blacklist } = {};', 106 | errors: [defaultErrorMessageWithWord('blacklist')], 107 | }, 108 | { 109 | code: 'var foo: Blacklist = "";', 110 | errors: [defaultErrorMessageWithWord('blacklist')], 111 | }, 112 | { 113 | code: 'var foo = "" as Blacklist;', 114 | errors: [defaultErrorMessageWithWord('blacklist')], 115 | }, 116 | { 117 | code: 'var foo = "" as Example.Blacklist;', 118 | errors: [defaultErrorMessageWithWord('blacklist')], 119 | }, 120 | { 121 | code: 'var foo = "" as Blacklist.Example;', 122 | errors: [defaultErrorMessageWithWord('blacklist')], 123 | }, 124 | { 125 | code: 'var foo = ""; // blacklist', 126 | errors: [defaultErrorMessageWithWord('blacklist')], 127 | }, 128 | { 129 | code: 'enum Blacklist {}', 130 | errors: [defaultErrorMessageWithWord('blacklist')], 131 | }, 132 | { 133 | code: 'class Blacklist {}', 134 | errors: [defaultErrorMessageWithWord('blacklist')], 135 | }, 136 | { 137 | code: 'type Blacklist = {}', 138 | errors: [defaultErrorMessageWithWord('blacklist')], 139 | }, 140 | { 141 | code: "/* Hello world. I'm using the discouraged word blacklist. */", 142 | errors: [defaultErrorMessageWithWord('blacklist')], 143 | }, 144 | ], 145 | }); 146 | -------------------------------------------------------------------------------- /packages/web-scripts/src/Tasks/CommitTasks.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { default as Debug } from 'debug'; 17 | import { default as spawn } from 'cross-spawn'; 18 | import { default as promiseSpawn } from 'cross-spawn-promise'; 19 | import { SpawnSyncReturns } from 'child_process'; 20 | // @ts-ignore 21 | import { bootstrap as czBootstrap } from 'commitizen/dist/cli/git-cz'; 22 | import { hasConfig } from '@spotify/web-scripts-utils'; 23 | 24 | import { typeCheck } from './LintTask'; 25 | import { 26 | CommitTaskDesc, 27 | CommitMsgTaskDesc, 28 | ReleaseTaskDesc, 29 | PrecommitTaskDesc, 30 | } from '../SharedTypes'; 31 | import { LINT_STAGED_CONFIG } from '../Paths'; 32 | 33 | export function getLintStagedConfig(): string | null { 34 | if ( 35 | !hasConfig([ 36 | { type: 'file', pattern: 'lint-staged.config.js' }, 37 | { type: 'file', pattern: '.lintstagedrc*' }, 38 | { type: 'package.json', property: 'lint-staged' }, 39 | ]) 40 | ) { 41 | return LINT_STAGED_CONFIG; 42 | } 43 | 44 | return null; 45 | } 46 | 47 | const dbg = Debug('web-scripts:commit'); // eslint-disable-line new-cap 48 | 49 | export async function precommitTask( 50 | task: PrecommitTaskDesc, 51 | ): Promise { 52 | const fns: Array<(task?: PrecommitTaskDesc) => Promise> = []; 53 | if (task.typecheck) { 54 | fns.push(typeCheck); 55 | } 56 | 57 | const results = await Promise.all( 58 | fns.map(async fn => { 59 | dbg('Beginning %s task', fn.name); 60 | const stdout = await fn(task); 61 | dbg('Finished %s task', fn.name); 62 | return stdout; 63 | }), 64 | ); 65 | 66 | // unfortunately, lint-staged cannot be parallelized alongside any other tasks because it takes over the output 67 | // completely, rendering the output unreadable if anything is run with it. 68 | results.push(await lintStaged(task)); 69 | 70 | return results; 71 | } 72 | 73 | export async function lintStaged(task: PrecommitTaskDesc): Promise { 74 | const config = getLintStagedConfig(); 75 | const cmd = 'npx'; 76 | const args = [ 77 | '--no-install', 78 | 'lint-staged', 79 | ...(config ? ['--config', config] : []), 80 | ...task.restOptions, 81 | ]; 82 | dbg('npx args %o', args); 83 | 84 | const env: { [key: string]: string } = { 85 | ...process.env, 86 | WEB_SCRIPTS_RUN_TESTS: task.tests.toString(), 87 | }; 88 | 89 | if (task.eslintConfig) { 90 | env.WEB_SCRIPTS_ESLINT_CONFIG = task.eslintConfig; 91 | } 92 | if (task.jestConfig) { 93 | env.WEB_SCRIPTS_JEST_CONFIG = task.jestConfig; 94 | } 95 | if (task.prettierConfig) { 96 | env.WEB_SCRIPTS_PRETTIER_CONFIG = task.prettierConfig; 97 | } 98 | 99 | const stdout = await promiseSpawn(cmd, args, { 100 | stdio: 'inherit', 101 | env, 102 | }); 103 | 104 | return (stdout || '').toString(); 105 | } 106 | 107 | export function commitTask(task: CommitTaskDesc): void { 108 | dbg('running commitizen commit', task.restOptions); 109 | 110 | // use this to get the resolved path to the root of the commitizen directory 111 | const cliPath = require 112 | .resolve('commitizen/package.json') 113 | .replace('package.json', ''); 114 | 115 | // https://github.com/commitizen/cz-cli/issues/667 116 | Object.assign(process.env, { 117 | CZ_TYPE: process.env.CZ_TYPE || ' ', 118 | CZ_SCOPE: process.env.CZ_SCOPE || ' ', 119 | CZ_SUBJECT: process.env.CZ_SUBJECT || ' ', 120 | CZ_BODY: process.env.CZ_BODY || ' ', 121 | CZ_ISSUES: process.env.CZ_ISSUES || ' ', 122 | CZ_MAX_HEADER_WIDTH: process.env.CZ_MAX_HEADER_WIDTH || 100, 123 | CZ_MAX_LINE_WIDTH: process.env.CZ_MAX_LINE_WIDTH || 100, 124 | }); 125 | 126 | return czBootstrap( 127 | { 128 | cliPath, 129 | config: { 130 | path: task.path, 131 | }, 132 | }, 133 | // this gets the arguments in the right positions to 134 | // satisfy commitizen, which strips the first two 135 | // (assumes that they're `['node', 'git-cz']`) 136 | [null, ...task.restOptions], 137 | ); 138 | } 139 | 140 | export function commitMsgTask( 141 | task: CommitMsgTaskDesc, 142 | ): SpawnSyncReturns { 143 | const cmd = 'npx'; 144 | const args = [ 145 | '--no-install', 146 | 'commitlint', 147 | `--config=${task.config}`, 148 | `--edit=${task.edit || process.env.HUSKY_GIT_PARAMS}`, 149 | ...task.restOptions, 150 | ]; 151 | dbg('npx args %o', args); 152 | return spawn.sync(cmd, args, { stdio: 'inherit' }); 153 | } 154 | 155 | export function releaseTask(task: ReleaseTaskDesc): SpawnSyncReturns { 156 | const cmd = 'npx'; 157 | const args = ['--no-install', 'semantic-release', ...task.restOptions]; 158 | dbg('npx args %o', args); 159 | return spawn.sync(cmd, args, { stdio: 'inherit' }); 160 | } 161 | -------------------------------------------------------------------------------- /packages/eslint-plugin/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **deps:** upgrade dependencies ([ef060c7](https://github.com/spotify/web-scripts/commit/ef060c7da531060cc1d0f0fb60d3df8f355e418e)) 11 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 12 | 13 | ### BREAKING CHANGES 14 | 15 | - **node:** Node bump from v14 to v18 16 | - **deps:** TypeScript bump from v4 to v5, Jest bump from v28 to v29 17 | 18 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 19 | 20 | **Note:** Version bump only for package @spotify/eslint-plugin 21 | 22 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 23 | 24 | **Note:** Version bump only for package @spotify/eslint-plugin 25 | 26 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 27 | 28 | **Note:** Version bump only for package @spotify/eslint-plugin 29 | 30 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 31 | 32 | **Note:** Version bump only for package @spotify/eslint-plugin 33 | 34 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 35 | 36 | **Note:** Version bump only for package @spotify/eslint-plugin 37 | 38 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 39 | 40 | **Note:** Version bump only for package @spotify/eslint-plugin 41 | 42 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 43 | 44 | **Note:** Version bump only for package @spotify/eslint-plugin 45 | 46 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 47 | 48 | **Note:** Version bump only for package @spotify/eslint-plugin 49 | 50 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 51 | 52 | **Note:** Version bump only for package @spotify/eslint-plugin 53 | 54 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 55 | 56 | ### Bug Fixes 57 | 58 | - fix peer dependency versioning for eslint ([46068c2](https://github.com/spotify/web-scripts/commit/46068c240faccb3ee8db2244541a6b1fbc0a6d90)) 59 | 60 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 61 | 62 | ### chore 63 | 64 | - update [@typescript-eslint](https://github.com/typescript-eslint) from v4 to v5, eslint from v7 to v8 ([e284943](https://github.com/spotify/web-scripts/commit/e28494330a6dd9c2561370f56a4eed1ef152f23d)) 65 | - update eslint from v7 to v8 ([725749c](https://github.com/spotify/web-scripts/commit/725749c6cf177de20b4011057198dd590cdbb742)) 66 | 67 | ### BREAKING CHANGES 68 | 69 | - update @typescript-eslint from v4 to v5, eslint from v7 to v8 70 | - update eslint from v7 to v8 71 | 72 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 73 | 74 | ### Build System 75 | 76 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 77 | 78 | ### BREAKING CHANGES 79 | 80 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 81 | 82 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 83 | 84 | **Note:** Version bump only for package @spotify/eslint-plugin 85 | 86 | # [10.1.0](https://github.com/spotify/web-scripts/compare/v10.0.1...v10.1.0) (2021-06-30) 87 | 88 | **Note:** Version bump only for package @spotify/eslint-plugin 89 | 90 | ## [10.0.1](https://github.com/spotify/web-scripts/compare/v10.0.0...v10.0.1) (2021-04-27) 91 | 92 | **Note:** Version bump only for package @spotify/eslint-plugin 93 | 94 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 95 | 96 | ### Build System 97 | 98 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 99 | 100 | ### BREAKING CHANGES 101 | 102 | - drop support for NodeJS v10.x, which reaches EOL on 103 | April 30, 2021. 104 | 105 | ## [9.0.2](https://github.com/spotify/web-scripts/compare/v9.0.1...v9.0.2) (2021-02-26) 106 | 107 | **Note:** Version bump only for package @spotify/eslint-plugin 108 | 109 | ## [9.0.1](https://github.com/spotify/web-scripts/compare/v9.0.0...v9.0.1) (2021-02-21) 110 | 111 | **Note:** Version bump only for package @spotify/eslint-plugin 112 | 113 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 114 | 115 | ### Bug Fixes 116 | 117 | - sync [@typescript-eslint](https://github.com/typescript-eslint) versions across repo ([fb20119](https://github.com/spotify/web-scripts/commit/fb201196a551a3b942410b1e5a3b40c5f43bc721)), closes [#555](https://github.com/spotify/web-scripts/issues/555) 118 | 119 | ## [8.1.1](https://github.com/spotify/web-scripts/compare/v8.1.0...v8.1.1) (2020-09-22) 120 | 121 | ### Bug Fixes 122 | 123 | - update eslint-plugin to allow for @typescript-eslint/parser@4 ([0363558](https://github.com/spotify/web-scripts/commit/0363558716e39ec175e14375070206e97a418d39)) 124 | 125 | # [8.1.0](https://github.com/spotify/web-scripts/compare/v8.0.4...v8.1.0) (2020-09-08) 126 | 127 | ### Features 128 | 129 | - **eslint-spotify:** added eslint-plugin package w/ best-practices/no-discouraged-words ([ddbbadc](https://github.com/spotify/web-scripts/commit/ddbbadcb810bc8f15f94f14fa5e9cc468c476131)) 130 | -------------------------------------------------------------------------------- /packages/web-scripts/README.md: -------------------------------------------------------------------------------- 1 | # web-scripts 2 | 3 | ## Description 4 | 5 | Build, lint, test, format, and release your JS/TS library. This CLI tool bundles all the necessary configuration and dependencies so you can focus on the code. 6 | 7 | ## Usage 8 | 9 | ```sh 10 | yarn add --dev @spotify/web-scripts husky 11 | ``` 12 | 13 | Add the scripts and commit hooks to your package.json: 14 | 15 | ```json 16 | { 17 | "scripts": { 18 | "test": "web-scripts test", 19 | "lint": "web-scripts lint", 20 | "format": "web-scripts format", 21 | "build": "web-scripts build", 22 | "commit": "web-scripts commit", 23 | "release": "web-scripts release" 24 | }, 25 | "husky": { 26 | "hooks": { 27 | "commit-msg": "web-scripts commitmsg", 28 | "pre-commit": "web-scripts precommit" 29 | } 30 | } 31 | } 32 | ``` 33 | 34 | If you plan to use `web-scripts build` to build ESM, CommonJS, and types for your library with ease, update your package.json to define the locations where those will end up. [Read more about our the build script](#the-build-script). 35 | 36 | ```json 37 | { 38 | "main": "cjs/index.js", 39 | "module": "esm/index.js", 40 | "types": "types" 41 | } 42 | ``` 43 | 44 | ### Editor support steps 45 | 46 | Add a root tsconfig.json: 47 | 48 | ```json 49 | { 50 | "extends": "@spotify/web-scripts/config/tsconfig.json", 51 | "include": ["src"] 52 | } 53 | ``` 54 | 55 | Add a root prettier.config.js: 56 | 57 | ```js 58 | module.exports = require('@spotify/web-scripts/config/prettier.config.js'); 59 | ``` 60 | 61 | Add a root .eslintrc.js: 62 | 63 | ```js 64 | module.exports = require('@spotify/web-scripts/config/eslintrc.js'); 65 | ``` 66 | 67 | Add a root jest.config.js: 68 | 69 | ```js 70 | module.exports = require('@spotify/web-scripts/config/jest.config.js'); 71 | ``` 72 | 73 | ### Watchers 74 | 75 | Both `web-scripts build` and `web-scripts test` support a `--watch` flag which runs the underlying CLIs (tsc and jest) as watchers. 76 | 77 | ```sh 78 | # re-compile the cjs, esm, and types on each change to your src with tsc 79 | web-scripts build --watch 80 | 81 | # re-run the tests that are relevant to your file changes with jest 82 | web-scripts test --watch 83 | ``` 84 | 85 | ### The `build` script 86 | 87 | `web-scripts build` runs three parallel calls to the TypeScript compiler. 88 | 89 | - One of them transpiles the files as CommonJS and outputs it to the `cjs` directory. Your repo should have `"cjs/index.js"` set as `main` in your package.json. You can turn this off using `--no-cjs` when running build. 90 | - Another does the exact same thing but only transpiles to [EcmaScript modules](https://github.com/standard-things/esm). This is super helpful if your consuming project is using Babel or TypeScript, and you'll end up avoiding playing games of transpilation telephone along the way. Your repo should have `"esm/index.js"` set as `module` in your package.json if using this. You can turn this off with the `--no-esm` flag when running build. 91 | - Finally, tsc will be run to output type definitions. Your repo should have the `"types"` directory set as `types` in your package.json if using this. You can turn this off with the `--no-types` flag when running build. 92 | 93 | These parallel builds are set up to share resources and work efficiently. 94 | 95 | If you need to use Babel for some reason, that's ok! Simply use babel directly instead of using `web-scripts build`. Teams inside Spotify mix and match which scripts they use to serve their needs. In many cases, `tsc` is all you need and is lighter and simpler to set up. 96 | 97 | ### Setting up CI publishing (Travis CI) 98 | 99 | The following steps should be from your local repository folder. 100 | 101 | (Optional but probably mandatory): Visit https://travis-ci.com/account/repositories and click "Sync Account" otherwise the Travis CLI may not be able to register your ENV vars later. 102 | 103 | 1. Add a basic .travis.yaml. You probably want something like: 104 | 105 | ```yml 106 | language: node_js 107 | node_js: 108 | - '14' 109 | branches: 110 | only: 111 | - master 112 | cache: 113 | yarn: true 114 | directories: 115 | - node_modules 116 | before_install: 117 | - curl -o- -L https://yarnpkg.com/install.sh | bash -s 118 | - export PATH="$HOME/.yarn/bin:$PATH" 119 | script: 120 | - yarn lint 121 | - yarn test 122 | ``` 123 | 124 | 2. Append a "release" stage to the `jobs:` that invokes `web-scripts release`: 125 | 126 | ``` 127 | jobs: 128 | include: 129 | - stage: release 130 | node_js: lts/* 131 | script: skip # do not run tests again 132 | deploy: 133 | provider: script 134 | skip_cleanup: true 135 | script: 136 | - yarn web-scripts release # or `yarn release` if you defined it in your package.json scripts 137 | ``` 138 | 139 | 3. Install the travis CI CLI: `gem install travis` 140 | 4. Create an NPM token: `https://www.npmjs.com/settings/[NPM USERNAME]/tokens` (scope: Read and Publish) 141 | 5. Set the secure ENV var: `travis env set NPM_TOKEN YOUR-NPM-TOKEN` 142 | 6. Create a Github Token: `https://github.com/settings/tokens` (required scope: `public_repo` !) 143 | 7. Set the secure ENV var: `travis env set GH_TOKEN YOUR-GH-TOKEN` 144 | 8. Commit all your changes with `yarn commit`, and push. 145 | 146 | If you use a scoped public package, such as `@yourusername/packagename`, then you'll need explicitly set in your `package.json`: 147 | 148 | ``` 149 | "publishConfig": { 150 | "access": "public" 151 | }, 152 | ``` 153 | 154 | Otherwise you'll receive an error during release like "You must sign up for private packages" or a missing flag `--access=public`. 155 | 156 | ## Contributing 157 | 158 | To start working in the repo: 159 | 160 | ```sh 161 | yarn 162 | yarn bootstrap 163 | ``` 164 | 165 | This library provides shared scripts and configs for creating a library at Spotify. It tries to use as much of those scripts and configs for itself, which is why the `bootstrap` task is required above. Otherwise, you can run within this package itself: 166 | 167 | ```sh 168 | yarn lint 169 | yarn build 170 | yarn test 171 | ``` 172 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @spotify/web-scripts 2 | 3 | [![Actions Status](https://github.com/spotify/web-scripts/workflows/Tests/badge.svg)](https://github.com/spotify/web-scripts/actions) 4 | [![Version](https://img.shields.io/npm/v/@spotify/web-scripts.svg)](https://www.npmjs.com/package/@spotify/web-scripts) 5 | 6 | # ⚠️ DEPRECATION NOTICE 7 | 8 | 2023-12-15: This repository is now officially deprecated. This means that the repository is no longer actively maintained and will not receive any further updates or bug fixes. 9 | 10 | --- 11 | 12 | A monorepo of base configs and CLI wrappers used to speed up development @ Spotify. 13 | 14 | Want to use it? Check out the [CLI documentation](https://github.com/spotify/web-scripts/blob/master/packages/web-scripts) to get started! 15 | 16 | ## About this project 17 | 18 | ### web-scripts CLI 19 | 20 | [@spotify/web-scripts](./packages/web-scripts) is a CLI that combines shared configuration for building, linting, testing, formatting, and releasing libraries for Node and the browser. It is opinionated, but allows configuration to avoid lock-in. You can also pick and choose which scripts you use. It is inspired by other tooling bundles like [react-scripts](https://www.npmjs.com/package/react-scripts) and [kcd-scripts](https://www.npmjs.com/package/kcd-scripts). 21 | 22 | ```bash 23 | yarn add --dev @spotify/web-scripts husky 24 | ``` 25 | 26 | It is intended to be used within a project as a series of npm scripts. 27 | 28 | ```json 29 | { 30 | "devDependencies": { 31 | "@spotify/web-scripts": "^12.0.0", 32 | "husky": "^7.0.0" 33 | }, 34 | "scripts": { 35 | "build": "web-scripts build", 36 | "test": "web-scripts test", 37 | "format": "web-scripts format", 38 | "lint": "web-scripts lint", 39 | "commit": "web-scripts commit", 40 | "release": "web-scripts release", 41 | "prepare": "husky install && web-scripts audit" 42 | } 43 | } 44 | ``` 45 | 46 | Additionally, you'll need to run the following two commands to create the commit and pre-commit hooks: 47 | 48 | ```shell 49 | npx husky set .husky/pre-commit 'yarn web-scripts precommit --no-tests --no-typecheck' 50 | 51 | npx husky set .husky/commit-msg 'yarn web-scripts commitmsg --edit="$1"' && \ 52 | sed 's/edit=""/edit="$1"/g' .husky/commit-msg | tee .husky/commit-msg 53 | ``` 54 | 55 | NOTE: the second command uses sed to hack around [this bug in husky](https://github.com/typicode/husky/issues/1019) that removes `$1`. 56 | 57 | You'll want to add and commit the `.husky` directory. 58 | 59 | View the [full CLI documentation](./packages/web-scripts) for more details on how to get started. 60 | 61 | ### Create a new library 62 | 63 | To quickly get started with a new `@spotify/web-scripts` library, you can build one with our [library scaffolding tool](https://github.com/spotify/web-scripts/tree/master/packages/create-web-scripts-library): 64 | 65 | ```sh 66 | yarn create @spotify/web-scripts-library my-library-name 67 | ``` 68 | 69 | ### Spotify shared configurations 70 | 71 | The other projects in this repo are shared configurations for common tools we use for building, linting, and formatting our code. They can be installed separately and used by anyone should they opt to follow our standards. We have a [specialized point-of-view on what belongs in our configs](#methodology). They are all used by the web-scripts CLI by default. 72 | 73 | - [@spotify/eslint-config](./packages/eslint-config) 74 | - [@spotify/eslint-config-base](./packages/eslint-config-base) 75 | - [@spotify/eslint-config-react](./packages/eslint-config-react) 76 | - [@spotify/eslint-config-typescript](./packages/eslint-config-typescript) 77 | - [@spotify/eslint-plugin](./packages/eslint-plugin) 78 | - [@spotify/prettier-config](./packages/prettier-config) 79 | - [@spotify/tsconfig](./packages/tsconfig) 80 | 81 | ## Methodology 82 | 83 | We have a few guiding principles for this project. 84 | 85 | 1. Style rules should be auto-fixable and if you can, errors should be linted ahead of runtime. 86 | 2. Avoid enforcing code style in static analysis; search for bugs with static analysis, and let auto-formatting deal with code style. 87 | 3. Push "fast" checks as far left as you can. Optimize for code editors/IDEs fixing issues and enforcing things; write Git hooks that catch things as a failsafe; and use static analysis in CI to prevent bad things from getting into master. 88 | 4. `web-scripts` is meant to be configurable. We want to avoid the "eject" problem. You should be able to easily take the base configs and extend them in your project. 89 | 5. Fewer top-level scripts that encapsulate all behavior for that lifecycle are preferable to lots of smaller, composable scripts. For example, we do `yarn lint` which includes Prettier, ESLint, and TypeScript checks. We could have done `yarn lint`, `yarn typecheck`, and `yarn stylecheck`. That would have meant pushing "new" linting to all repos on new versions would be much harder, as we would need to communicate that you need to update your invocation in package.json. 90 | 91 | ## Related projects we use 92 | 93 | - [TypeScript]: a superset of JavaScript which we think helps make code readable and less bug-prone. 94 | - [ESLint]: used for static code analysis with some auto-fixing. 95 | - [Prettier]: use to format code pre-commit and automatically in your editor. 96 | - [Jest]: our preferred JavaScript test framework. 97 | - [husky]: allows us to hook into git events in a convenient way. 98 | - [lint-staged]: allows us to write pre-commit hooks which target specific paths and run a series of commands. 99 | 100 | ## Contributing 101 | 102 | This project adheres to the [Open Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code. 103 | 104 | This project is an opinionated approach to static analysis, code formatting, testing, and publishing. It's 105 | the result of consensus between many web engineers inside Spotify, and the default configs will mostly be 106 | written by Spotify employees. _We may reject PRs to the ESLint config if we don't agree that the rule 107 | makes sense as part of our baseline, for example._ Use it if it aligns with your needs! 108 | 109 | ### Running Tests locally 110 | 111 | If you get an error like `Cannot find module '../cjs'` when running `yarn test`, you need to bootstrap web-scripts. 112 | 113 | ```bash 114 | $ yarn lerna run bootstrap 115 | ``` 116 | 117 | [eslint]: https://eslint.org/ 118 | [typescript]: https://www.typescriptlang.org/ 119 | [prettier]: https://prettier.io/ 120 | [jest]: https://jestjs.io/ 121 | [husky]: https://github.com/typicode/husky 122 | [lint-staged]: https://github.com/okonet/lint-staged 123 | [code-of-conduct]: https://github.com/spotify/code-of-conduct/blob/master/code-of-conduct.md 124 | 125 | ### Releasing 126 | 127 | The repo [releases automatically on merge to master](https://github.com/spotify/web-scripts/blob/master/release.sh) using `semantic-release` and `lerna` in a Github Action, if the commit message has the right [semantic-release format](https://github.com/semantic-release/semantic-release#commit-message-format) 128 | -------------------------------------------------------------------------------- /packages/web-scripts-utils/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **deps:** upgrade dependencies ([ef060c7](https://github.com/spotify/web-scripts/commit/ef060c7da531060cc1d0f0fb60d3df8f355e418e)) 11 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 12 | 13 | ### BREAKING CHANGES 14 | 15 | - **node:** Node bump from v14 to v18 16 | - **deps:** TypeScript bump from v4 to v5, Jest bump from v28 to v29 17 | 18 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 19 | 20 | **Note:** Version bump only for package @spotify/web-scripts-utils 21 | 22 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 23 | 24 | **Note:** Version bump only for package @spotify/web-scripts-utils 25 | 26 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 27 | 28 | **Note:** Version bump only for package @spotify/web-scripts-utils 29 | 30 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 31 | 32 | **Note:** Version bump only for package @spotify/web-scripts-utils 33 | 34 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 35 | 36 | **Note:** Version bump only for package @spotify/web-scripts-utils 37 | 38 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 39 | 40 | **Note:** Version bump only for package @spotify/web-scripts-utils 41 | 42 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 43 | 44 | **Note:** Version bump only for package @spotify/web-scripts-utils 45 | 46 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 47 | 48 | **Note:** Version bump only for package @spotify/web-scripts-utils 49 | 50 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 51 | 52 | **Note:** Version bump only for package @spotify/web-scripts-utils 53 | 54 | # [14.0.0](https://github.com/spotify/web-scripts/compare/v13.0.1...v14.0.0) (2022-07-11) 55 | 56 | ### chore 57 | 58 | - **deps:** upgrade deps; jest from v27 to v28 ([13aff23](https://github.com/spotify/web-scripts/commit/13aff23c90c7b23ca0a8bb27eb58695663d3f644)) 59 | 60 | ### BREAKING CHANGES 61 | 62 | - **deps:** Jest bump from v27 to v28 63 | 64 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 65 | 66 | **Note:** Version bump only for package @spotify/web-scripts-utils 67 | 68 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 69 | 70 | **Note:** Version bump only for package @spotify/web-scripts-utils 71 | 72 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 73 | 74 | ### Build System 75 | 76 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 77 | 78 | ### BREAKING CHANGES 79 | 80 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 81 | 82 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 83 | 84 | **Note:** Version bump only for package @spotify/web-scripts-utils 85 | 86 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 87 | 88 | ### Build System 89 | 90 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 91 | 92 | ### BREAKING CHANGES 93 | 94 | - drop support for NodeJS v10.x, which reaches EOL on 95 | April 30, 2021. 96 | 97 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 98 | 99 | **Note:** Version bump only for package @spotify/web-scripts-utils 100 | 101 | # [8.0.0](https://github.com/spotify/web-scripts/compare/v7.0.2...v8.0.0) (2020-06-23) 102 | 103 | **Note:** Version bump only for package @spotify/web-scripts-utils 104 | 105 | # [7.0.0](https://github.com/spotify/web-scripts/compare/v6.2.0...v7.0.0) (2020-04-28) 106 | 107 | **Note:** Version bump only for package @spotify/web-scripts-utils 108 | 109 | ## [6.1.1](https://github.com/spotify/web-scripts/compare/v6.1.0...v6.1.1) (2020-04-03) 110 | 111 | **Note:** Version bump only for package @spotify/web-scripts-utils 112 | 113 | # [6.0.0](https://github.com/spotify/web-scripts/compare/v5.3.0...v6.0.0) (2020-01-29) 114 | 115 | ### Build System 116 | 117 | - bump node in engines to 10.18.0 ([08ea936](https://github.com/spotify/web-scripts/commit/08ea936faf879be18b97f8a4ba99aba5926ccff8)) 118 | 119 | ### BREAKING CHANGES 120 | 121 | - increasing Node version in engines declaration 122 | 123 | # [5.3.0](https://github.com/spotify/web-scripts/compare/v5.2.1...v5.3.0) (2020-01-29) 124 | 125 | **Note:** Version bump only for package @spotify/web-scripts-utils 126 | 127 | # [5.1.0](https://github.com/spotify/web-scripts/compare/v5.0.2...v5.1.0) (2020-01-22) 128 | 129 | ### Features 130 | 131 | - **web-scripts:** rename postinstall to audit ([169f3c1](https://github.com/spotify/web-scripts/commit/169f3c18641d7a51c5319ba8e155cd5a7bd4b85e)), closes [#131](https://github.com/spotify/web-scripts/issues/131) 132 | 133 | ## [5.0.2](https://github.com/spotify/web-scripts/compare/v5.0.1...v5.0.2) (2020-01-21) 134 | 135 | **Note:** Version bump only for package @spotify/web-scripts-utils 136 | 137 | # [5.0.0](https://github.com/spotify/web-scripts/compare/v4.0.2...v5.0.0) (2020-01-06) 138 | 139 | ### Features 140 | 141 | - **tsconfig:** expose a single tsconfig ([5048d6a](https://github.com/spotify/web-scripts/commit/5048d6aea1e8949c11bfa8ed5bbdff3f177074b7)), closes [#21](https://github.com/spotify/web-scripts/issues/21) 142 | 143 | ### BREAKING CHANGES 144 | 145 | - **tsconfig:** deleted a number of exports from tsconfig 146 | 147 | # [4.0.0](https://github.com/spotify/web-scripts/compare/v3.3.1...v4.0.0) (2020-01-03) 148 | 149 | ### chore 150 | 151 | - bump engine to >=10.13.0 ([9527453](https://github.com/spotify/web-scripts/commit/9527453a03ea0a807e6f6964469bf8482a3e3cca)) 152 | 153 | ### BREAKING CHANGES 154 | 155 | - Minimum Node version has been increased 156 | 157 | # [3.3.0](https://github.com/spotify/web-scripts/compare/v3.2.0...v3.3.0) (2020-01-03) 158 | 159 | ### Features 160 | 161 | - **deps:** yarn upgrade ([1b49fd8](https://github.com/spotify/web-scripts/commit/1b49fd84fcf23eb992dea9ac6cf08bf20b35270e)) 162 | 163 | # [3.1.0](https://github.com/spotify/web-scripts/compare/v3.0.1...v3.1.0) (2020-01-02) 164 | 165 | ### Bug Fixes 166 | 167 | - stylecheck should use implicit config ([9c9a88c](https://github.com/spotify/web-scripts/commit/9c9a88c)) 168 | 169 | # [3.0.0](https://github.com/spotify/web-scripts/compare/v2.1.0...v3.0.0) (2019-10-10) 170 | 171 | **Note:** Version bump only for package @spotify/web-scripts-utils 172 | 173 | # [2.1.0](https://github.com/spotify/web-scripts/compare/v2.0.1...v2.1.0) (2019-10-10) 174 | 175 | ### Features 176 | 177 | - use package attributes to determine lint preset ([f6151ed](https://github.com/spotify/web-scripts/commit/f6151ed)), closes [#56](https://github.com/spotify/web-scripts/issues/56) 178 | -------------------------------------------------------------------------------- /packages/prettier-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **deps:** upgrade dependencies ([ef060c7](https://github.com/spotify/web-scripts/commit/ef060c7da531060cc1d0f0fb60d3df8f355e418e)) 11 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 12 | 13 | ### BREAKING CHANGES 14 | 15 | - **node:** Node bump from v14 to v18 16 | - **deps:** TypeScript bump from v4 to v5, Jest bump from v28 to v29 17 | 18 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 19 | 20 | **Note:** Version bump only for package @spotify/prettier-config 21 | 22 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 23 | 24 | **Note:** Version bump only for package @spotify/prettier-config 25 | 26 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 27 | 28 | **Note:** Version bump only for package @spotify/prettier-config 29 | 30 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 31 | 32 | **Note:** Version bump only for package @spotify/prettier-config 33 | 34 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 35 | 36 | **Note:** Version bump only for package @spotify/prettier-config 37 | 38 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 39 | 40 | **Note:** Version bump only for package @spotify/prettier-config 41 | 42 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 43 | 44 | **Note:** Version bump only for package @spotify/prettier-config 45 | 46 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 47 | 48 | **Note:** Version bump only for package @spotify/prettier-config 49 | 50 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 51 | 52 | **Note:** Version bump only for package @spotify/prettier-config 53 | 54 | # [14.0.0](https://github.com/spotify/web-scripts/compare/v13.0.1...v14.0.0) (2022-07-11) 55 | 56 | **Note:** Version bump only for package @spotify/prettier-config 57 | 58 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 59 | 60 | **Note:** Version bump only for package @spotify/prettier-config 61 | 62 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 63 | 64 | **Note:** Version bump only for package @spotify/prettier-config 65 | 66 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 67 | 68 | ### Build System 69 | 70 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 71 | 72 | ### BREAKING CHANGES 73 | 74 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 75 | 76 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 77 | 78 | **Note:** Version bump only for package @spotify/prettier-config 79 | 80 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 81 | 82 | ### Build System 83 | 84 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 85 | 86 | ### BREAKING CHANGES 87 | 88 | - drop support for NodeJS v10.x, which reaches EOL on 89 | April 30, 2021. 90 | 91 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 92 | 93 | **Note:** Version bump only for package @spotify/prettier-config 94 | 95 | # [8.0.0](https://github.com/spotify/web-scripts/compare/v7.0.2...v8.0.0) (2020-06-23) 96 | 97 | **Note:** Version bump only for package @spotify/prettier-config 98 | 99 | # [7.0.0](https://github.com/spotify/web-scripts/compare/v6.2.0...v7.0.0) (2020-04-28) 100 | 101 | - major release- 7.0.0 (#318) ([29509b4](https://github.com/spotify/web-scripts/commit/29509b4a52325080b7a38f3aeb41ce8ed82f04f5)), closes [#318](https://github.com/spotify/web-scripts/issues/318) [#314](https://github.com/spotify/web-scripts/issues/314) [#312](https://github.com/spotify/web-scripts/issues/312) [#310](https://github.com/spotify/web-scripts/issues/310) 102 | 103 | ### BREAKING CHANGES 104 | 105 | - running web-scripts without arguments exits code 1 now instead of exiting 0 106 | - prettier 2.0 may introduce breaking changes 107 | - prettier 2.0 may introduce breaking changes 108 | 109 | - improvement(web-scripts): make stylecheck and typecheck default for lint 110 | 111 | the lint script will now default typechecking and stylechecking to true by default. You may shut 112 | these off with `--no-typecheck` and `--no-stylecheck`. 113 | 114 | - Users who have projects incompatible with TypeScript checks or with projects that 115 | do not user prettier will now fail yarn lint. 116 | 117 | # [6.2.0](https://github.com/spotify/web-scripts/compare/v6.1.1...v6.2.0) (2020-04-04) 118 | 119 | **Note:** Version bump only for package @spotify/prettier-config 120 | 121 | ## [6.1.1](https://github.com/spotify/web-scripts/compare/v6.1.0...v6.1.1) (2020-04-03) 122 | 123 | **Note:** Version bump only for package @spotify/prettier-config 124 | 125 | # [6.0.0](https://github.com/spotify/web-scripts/compare/v5.3.0...v6.0.0) (2020-01-29) 126 | 127 | ### Build System 128 | 129 | - bump node in engines to 10.18.0 ([08ea936](https://github.com/spotify/web-scripts/commit/08ea936faf879be18b97f8a4ba99aba5926ccff8)) 130 | 131 | ### BREAKING CHANGES 132 | 133 | - increasing Node version in engines declaration 134 | 135 | # [5.0.0](https://github.com/spotify/web-scripts/compare/v4.0.2...v5.0.0) (2020-01-06) 136 | 137 | **Note:** Version bump only for package @spotify/prettier-config 138 | 139 | # [4.0.0](https://github.com/spotify/web-scripts/compare/v3.3.1...v4.0.0) (2020-01-03) 140 | 141 | ### chore 142 | 143 | - bump engine to >=10.13.0 ([9527453](https://github.com/spotify/web-scripts/commit/9527453a03ea0a807e6f6964469bf8482a3e3cca)) 144 | 145 | ### BREAKING CHANGES 146 | 147 | - Minimum Node version has been increased 148 | 149 | # [3.0.0](https://github.com/spotify/web-scripts/compare/v2.1.0...v3.0.0) (2019-10-10) 150 | 151 | **Note:** Version bump only for package @spotify/prettier-config 152 | 153 | # [2.0.0](https://github.com/spotify/web-scripts/compare/v1.4.0...v2.0.0) (2019-09-23) 154 | 155 | **Note:** Version bump only for package @spotify/prettier-config 156 | 157 | ## [1.1.4](https://github.com/spotify/web-scripts/compare/v1.1.3...v1.1.4) (2019-07-17) 158 | 159 | ### Bug Fixes 160 | 161 | - Add repostiory field to package.json files ([fccd2db](https://github.com/spotify/web-scripts/commit/fccd2db)) 162 | 163 | # [1.1.0](https://github.com/spotify/web-scripts/compare/v1.0.2...v1.1.0) (2019-07-01) 164 | 165 | ### Bug Fixes 166 | 167 | - Updates engines field to node >=10 ([b3b4f58](https://github.com/spotify/web-scripts/commit/b3b4f58)) 168 | 169 | ## [1.0.2](https://github.com/spotify/web-scripts/compare/v1.0.1...v1.0.2) (2019-06-26) 170 | 171 | ### Bug Fixes 172 | 173 | - update dependencies for peerDependency warnings ([eceff7c](https://github.com/spotify/web-scripts/commit/eceff7c)) 174 | 175 | ## [1.0.1](https://github.com/spotify/web-scripts/compare/v1.0.0...v1.0.1) (2019-06-24) 176 | 177 | **Note:** Version bump only for package @spotify/prettier-config 178 | -------------------------------------------------------------------------------- /packages/web-scripts/src/integration.test.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { exec as execCP } from 'child_process'; 17 | import { join } from 'path'; 18 | import { promisify } from 'util'; 19 | import { 20 | writeFile as writeFileFS, 21 | mkdir as mkdirFS, 22 | copyFile as copyFileFS, 23 | existsSync, 24 | } from 'fs'; 25 | import fromEntries from 'object.fromentries'; 26 | import * as tempy from 'tempy'; 27 | import { default as Debug } from 'debug'; 28 | import rimraf from 'rimraf'; 29 | 30 | import { THIS_ROOT, TSCONFIG } from './Paths'; 31 | 32 | const dbg = Debug('web-scripts:integration-test'); // eslint-disable-line new-cap 33 | const root = join(__dirname, '..'); 34 | const CLI = join(root, 'bin/web-scripts'); 35 | const MONOREPO_ROOT = join(root, '../..'); 36 | const ESLINT_ROOT = join(MONOREPO_ROOT, 'packages/eslint-config'); 37 | 38 | const execPromise = promisify(execCP); 39 | const writeFile = promisify(writeFileFS); 40 | const mkdir = promisify(mkdirFS); 41 | const copyFile = promisify(copyFileFS); 42 | 43 | // log output after the command finishes 44 | const exec = async (cmd: string, options?: object) => { 45 | function _log(resp: { stdout?: string | Buffer; stderr?: string | Buffer }) { 46 | if (resp.stdout) resp.stdout.toString().split('\n').forEach(dbg); 47 | if (resp.stderr) resp.stderr.toString().split('\n').forEach(dbg); 48 | } 49 | try { 50 | const resp = await execPromise(cmd, options); 51 | _log(resp); 52 | return resp; 53 | } catch (err) { 54 | _log(err as any); 55 | throw err; 56 | } 57 | }; 58 | 59 | const SETUP_REPO_TIMEOUT = 30000; 60 | const TEST_SCRIPTS_TIMEOUT = 60000; 61 | 62 | // eslint-disable-next-line jest/no-disabled-tests 63 | describe.skip('integration tests', () => { 64 | let PKG_ROOT: string; 65 | 66 | beforeEach(() => { 67 | PKG_ROOT = tempy.directory(); 68 | }); 69 | 70 | describe('help', () => { 71 | const USAGE_MATCH = 'Usage: web-scripts [options] [command]'; 72 | 73 | test('The CLI fails and offers help when invoked with no arguments', async () => { 74 | await expect(exec(`${CLI}`)).rejects.toMatchObject({ 75 | stdout: expect.stringContaining(USAGE_MATCH), 76 | }); 77 | }); 78 | 79 | test('The CLI offers help when invoked with --help flag', async () => { 80 | const result = await exec(`${CLI} --help`); 81 | expect(result.stdout).toMatch(USAGE_MATCH); 82 | }); 83 | }); 84 | 85 | describe('TypeScript', () => { 86 | beforeEach(async () => { 87 | await setupRepo( 88 | 'index.ts', 89 | 'index.test.ts', 90 | 'Component.tsx', 91 | 'Component.test.tsx', 92 | ); 93 | }, SETUP_REPO_TIMEOUT); 94 | 95 | // eslint-disable-next-line jest/expect-expect 96 | test( 97 | 'Full integration test', 98 | async () => await testScripts(), 99 | TEST_SCRIPTS_TIMEOUT, 100 | ); 101 | }); 102 | 103 | describe('JavaScript', () => { 104 | beforeEach(async () => { 105 | await setupRepo( 106 | 'index.js', 107 | 'index.test.js', 108 | 'Component.jsx', 109 | 'Component.test.jsx', 110 | ); 111 | }, SETUP_REPO_TIMEOUT); 112 | 113 | // eslint-disable-next-line jest/expect-expect 114 | test( 115 | 'Full integration test', 116 | async () => await testScripts(['--no-types'], ['--no-typecheck']), 117 | TEST_SCRIPTS_TIMEOUT, 118 | ); 119 | }); 120 | 121 | async function setupRepo(...fileNames: string[]) { 122 | // we need to locally install some dependencies, but we want to avoid installing 123 | // all of them to prevent needlessly re-installing everything which significantly 124 | // slows this test down and often results in errors in CI. If one of these 125 | // dependencies is removed from package.json, this test will fail when the 126 | // commands are run at the end. 127 | const localDependencies: string[] = [ 128 | 'eslint', 129 | 'ts-jest', 130 | 'typescript', 131 | '@types/jest', 132 | '@types/react', 133 | ]; 134 | 135 | // as of ESLint 6, ESLint plugins need to be locally installed too. 136 | const eslintDependencies: string[] = [ 137 | '@typescript-eslint/eslint-plugin', 138 | 'eslint-plugin-jest', 139 | 'eslint-plugin-jsx-a11y', 140 | 'eslint-plugin-react', 141 | 'eslint-plugin-react-hooks', 142 | ]; 143 | 144 | const pkg = { 145 | name: 'test-pkg', 146 | scripts: { 147 | test: `${CLI} test`, 148 | build: `${CLI} build`, 149 | lint: `${CLI} lint`, 150 | commit: `${CLI} commit`, 151 | release: `${CLI} release`, 152 | }, 153 | dependencies: fromEntries([ 154 | ...Object.entries( 155 | require(`${THIS_ROOT}/package.json`).dependencies, 156 | ).filter(([k]) => localDependencies.includes(k)), 157 | ...Object.entries( 158 | require(`${ESLINT_ROOT}/package.json`).dependencies, 159 | ).filter(([k]) => eslintDependencies.includes(k)), 160 | // react isn't a local dependency so it needs to be directly specified 161 | ['react', '^17'], 162 | ]), 163 | }; 164 | 165 | // extend the tsconfig from the web-scripts/config folder, using an absolute 166 | // path because we didn't link or install into the temp project 167 | const tsConfig = { 168 | extends: TSCONFIG, 169 | include: ['src'], 170 | }; 171 | 172 | await writeFile( 173 | join(PKG_ROOT, 'package.json'), 174 | JSON.stringify(pkg, null, ' '), 175 | ); 176 | 177 | await writeFile( 178 | join(PKG_ROOT, 'tsconfig.json'), 179 | JSON.stringify(tsConfig, null, 2), 180 | ); 181 | 182 | await mkdir(join(PKG_ROOT, 'src')); 183 | fileNames.map(fileName => 184 | copyFile( 185 | join(THIS_ROOT, '__fixtures__', fileName), 186 | join(PKG_ROOT, 'src', fileName), 187 | ), 188 | ); 189 | await copyFile( 190 | join(MONOREPO_ROOT, '.gitignore'), 191 | join(PKG_ROOT, '.gitignore'), 192 | ); 193 | 194 | // install the dependencies we specified above in pkg 195 | // this is what is making the tests fail 196 | // for some reason in docker it can't set the registry to the internal one 197 | await exec('yarn', { cwd: PKG_ROOT }); 198 | // Required for the `commit` and `commitmsg` tasks. 199 | await exec('git init', { cwd: PKG_ROOT }); 200 | } 201 | 202 | async function testScripts( 203 | buildArgs: string[] = [], 204 | lintArgs: string[] = ['--ignore-path=.gitignore', '--format=checkstyle'], 205 | ) { 206 | try { 207 | rimraf.sync(join(PKG_ROOT, 'cjs')); 208 | expect(existsSync(join(PKG_ROOT, 'cjs/index.js'))).toBe(false); 209 | await exec(['yarn build', ...buildArgs].join(' '), { cwd: PKG_ROOT }); 210 | expect(existsSync(join(PKG_ROOT, 'cjs/index.js'))).toBe(true); 211 | 212 | await exec('yarn test', { cwd: PKG_ROOT }); 213 | await exec('yarn test index.test', { cwd: PKG_ROOT }); 214 | await exec(['yarn lint', ...lintArgs].join(' '), { cwd: PKG_ROOT }); 215 | } catch (e) { 216 | // We are not capturing and printing stdout above, where TSC prints its errors. This makes sure it's printed. 217 | console.log((e as any).stdout); // eslint-disable-line no-console 218 | throw e; 219 | } 220 | } 221 | }); 222 | -------------------------------------------------------------------------------- /packages/tsconfig/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **deps:** upgrade dependencies ([ef060c7](https://github.com/spotify/web-scripts/commit/ef060c7da531060cc1d0f0fb60d3df8f355e418e)) 11 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 12 | 13 | ### BREAKING CHANGES 14 | 15 | - **node:** Node bump from v14 to v18 16 | - **deps:** TypeScript bump from v4 to v5, Jest bump from v28 to v29 17 | 18 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 19 | 20 | **Note:** Version bump only for package @spotify/tsconfig 21 | 22 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 23 | 24 | **Note:** Version bump only for package @spotify/tsconfig 25 | 26 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 27 | 28 | **Note:** Version bump only for package @spotify/tsconfig 29 | 30 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 31 | 32 | **Note:** Version bump only for package @spotify/tsconfig 33 | 34 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 35 | 36 | **Note:** Version bump only for package @spotify/tsconfig 37 | 38 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 39 | 40 | **Note:** Version bump only for package @spotify/tsconfig 41 | 42 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 43 | 44 | **Note:** Version bump only for package @spotify/tsconfig 45 | 46 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 47 | 48 | **Note:** Version bump only for package @spotify/tsconfig 49 | 50 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 51 | 52 | **Note:** Version bump only for package @spotify/tsconfig 53 | 54 | # [14.0.0](https://github.com/spotify/web-scripts/compare/v13.0.1...v14.0.0) (2022-07-11) 55 | 56 | **Note:** Version bump only for package @spotify/tsconfig 57 | 58 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 59 | 60 | **Note:** Version bump only for package @spotify/tsconfig 61 | 62 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 63 | 64 | **Note:** Version bump only for package @spotify/tsconfig 65 | 66 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 67 | 68 | ### Build System 69 | 70 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 71 | 72 | ### BREAKING CHANGES 73 | 74 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 75 | 76 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 77 | 78 | **Note:** Version bump only for package @spotify/tsconfig 79 | 80 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 81 | 82 | ### Build System 83 | 84 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 85 | 86 | ### BREAKING CHANGES 87 | 88 | - drop support for NodeJS v10.x, which reaches EOL on 89 | April 30, 2021. 90 | 91 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 92 | 93 | ### Features 94 | 95 | - use TypeScript 4 ([bbf1164](https://github.com/spotify/web-scripts/commit/bbf1164c75c40457d6457274f83deb59d0de7c09)), closes [#487](https://github.com/spotify/web-scripts/issues/487) [#252](https://github.com/spotify/web-scripts/issues/252) 96 | 97 | ### BREAKING CHANGES 98 | 99 | - must upgrade to TypeScript 4 as a consumer; new tsconfig takes advantage of 100 | incremental + noEmit 101 | 102 | # [8.0.0](https://github.com/spotify/web-scripts/compare/v7.0.2...v8.0.0) (2020-06-23) 103 | 104 | **Note:** Version bump only for package @spotify/tsconfig 105 | 106 | # [7.0.0](https://github.com/spotify/web-scripts/compare/v6.2.0...v7.0.0) (2020-04-28) 107 | 108 | - major release- 7.0.0 (#318) ([29509b4](https://github.com/spotify/web-scripts/commit/29509b4a52325080b7a38f3aeb41ce8ed82f04f5)), closes [#318](https://github.com/spotify/web-scripts/issues/318) [#314](https://github.com/spotify/web-scripts/issues/314) [#312](https://github.com/spotify/web-scripts/issues/312) [#310](https://github.com/spotify/web-scripts/issues/310) 109 | 110 | ### BREAKING CHANGES 111 | 112 | - running web-scripts without arguments exits code 1 now instead of exiting 0 113 | - prettier 2.0 may introduce breaking changes 114 | - prettier 2.0 may introduce breaking changes 115 | 116 | - improvement(web-scripts): make stylecheck and typecheck default for lint 117 | 118 | the lint script will now default typechecking and stylechecking to true by default. You may shut 119 | these off with `--no-typecheck` and `--no-stylecheck`. 120 | 121 | - Users who have projects incompatible with TypeScript checks or with projects that 122 | do not user prettier will now fail yarn lint. 123 | 124 | # [6.2.0](https://github.com/spotify/web-scripts/compare/v6.1.1...v6.2.0) (2020-04-04) 125 | 126 | **Note:** Version bump only for package @spotify/tsconfig 127 | 128 | ## [6.1.1](https://github.com/spotify/web-scripts/compare/v6.1.0...v6.1.1) (2020-04-03) 129 | 130 | **Note:** Version bump only for package @spotify/tsconfig 131 | 132 | # [6.0.0](https://github.com/spotify/web-scripts/compare/v5.3.0...v6.0.0) (2020-01-29) 133 | 134 | ### Build System 135 | 136 | - bump node in engines to 10.18.0 ([08ea936](https://github.com/spotify/web-scripts/commit/08ea936faf879be18b97f8a4ba99aba5926ccff8)) 137 | 138 | ### BREAKING CHANGES 139 | 140 | - increasing Node version in engines declaration 141 | 142 | # [5.0.0](https://github.com/spotify/web-scripts/compare/v4.0.2...v5.0.0) (2020-01-06) 143 | 144 | ### Features 145 | 146 | - **tsconfig:** expose a single tsconfig ([5048d6a](https://github.com/spotify/web-scripts/commit/5048d6aea1e8949c11bfa8ed5bbdff3f177074b7)), closes [#21](https://github.com/spotify/web-scripts/issues/21) 147 | 148 | ### BREAKING CHANGES 149 | 150 | - **tsconfig:** deleted a number of exports from tsconfig 151 | 152 | # [4.0.0](https://github.com/spotify/web-scripts/compare/v3.3.1...v4.0.0) (2020-01-03) 153 | 154 | ### chore 155 | 156 | - bump engine to >=10.13.0 ([9527453](https://github.com/spotify/web-scripts/commit/9527453a03ea0a807e6f6964469bf8482a3e3cca)) 157 | 158 | ### BREAKING CHANGES 159 | 160 | - Minimum Node version has been increased 161 | 162 | # [3.3.0](https://github.com/spotify/web-scripts/compare/v3.2.0...v3.3.0) (2020-01-03) 163 | 164 | ### Features 165 | 166 | - **deps:** yarn upgrade ([1b49fd8](https://github.com/spotify/web-scripts/commit/1b49fd84fcf23eb992dea9ac6cf08bf20b35270e)) 167 | 168 | # [3.0.0](https://github.com/spotify/web-scripts/compare/v2.1.0...v3.0.0) (2019-10-10) 169 | 170 | **Note:** Version bump only for package @spotify/tsconfig 171 | 172 | # [2.0.0](https://github.com/spotify/web-scripts/compare/v1.4.0...v2.0.0) (2019-09-23) 173 | 174 | **Note:** Version bump only for package @spotify/tsconfig 175 | 176 | ## [1.1.4](https://github.com/spotify/web-scripts/compare/v1.1.3...v1.1.4) (2019-07-17) 177 | 178 | ### Bug Fixes 179 | 180 | - Add repostiory field to package.json files ([fccd2db](https://github.com/spotify/web-scripts/commit/fccd2db)) 181 | 182 | # [1.1.0](https://github.com/spotify/web-scripts/compare/v1.0.2...v1.1.0) (2019-07-01) 183 | 184 | ### Bug Fixes 185 | 186 | - Updates engines field to node >=10 ([b3b4f58](https://github.com/spotify/web-scripts/commit/b3b4f58)) 187 | 188 | ## [1.0.2](https://github.com/spotify/web-scripts/compare/v1.0.1...v1.0.2) (2019-06-26) 189 | 190 | ### Bug Fixes 191 | 192 | - update dependencies for peerDependency warnings ([eceff7c](https://github.com/spotify/web-scripts/commit/eceff7c)) 193 | 194 | ## [1.0.1](https://github.com/spotify/web-scripts/compare/v1.0.0...v1.0.1) (2019-06-24) 195 | 196 | **Note:** Version bump only for package @spotify/tsconfig 197 | -------------------------------------------------------------------------------- /packages/eslint-config-base/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 11 | 12 | ### BREAKING CHANGES 13 | 14 | - **node:** Node bump from v14 to v18 15 | 16 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 17 | 18 | **Note:** Version bump only for package @spotify/eslint-config-base 19 | 20 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 21 | 22 | **Note:** Version bump only for package @spotify/eslint-config-base 23 | 24 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 25 | 26 | **Note:** Version bump only for package @spotify/eslint-config-base 27 | 28 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 29 | 30 | **Note:** Version bump only for package @spotify/eslint-config-base 31 | 32 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 33 | 34 | **Note:** Version bump only for package @spotify/eslint-config-base 35 | 36 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 37 | 38 | **Note:** Version bump only for package @spotify/eslint-config-base 39 | 40 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 41 | 42 | **Note:** Version bump only for package @spotify/eslint-config-base 43 | 44 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 45 | 46 | **Note:** Version bump only for package @spotify/eslint-config-base 47 | 48 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 49 | 50 | **Note:** Version bump only for package @spotify/eslint-config-base 51 | 52 | # [14.0.0](https://github.com/spotify/web-scripts/compare/v13.0.1...v14.0.0) (2022-07-11) 53 | 54 | **Note:** Version bump only for package @spotify/eslint-config-base 55 | 56 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 57 | 58 | **Note:** Version bump only for package @spotify/eslint-config-base 59 | 60 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 61 | 62 | **Note:** Version bump only for package @spotify/eslint-config-base 63 | 64 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 65 | 66 | ### Build System 67 | 68 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 69 | 70 | ### BREAKING CHANGES 71 | 72 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 73 | 74 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 75 | 76 | **Note:** Version bump only for package @spotify/eslint-config-base 77 | 78 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 79 | 80 | ### Build System 81 | 82 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 83 | 84 | ### BREAKING CHANGES 85 | 86 | - drop support for NodeJS v10.x, which reaches EOL on 87 | April 30, 2021. 88 | 89 | ## [9.0.2](https://github.com/spotify/web-scripts/compare/v9.0.1...v9.0.2) (2021-02-26) 90 | 91 | ### Bug Fixes 92 | 93 | - disable no-undef ([52926ad](https://github.com/spotify/web-scripts/commit/52926ad7b8d94170b0b2584afc14cdb666d47427)) 94 | 95 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 96 | 97 | **Note:** Version bump only for package @spotify/eslint-config-base 98 | 99 | # [8.0.0](https://github.com/spotify/web-scripts/compare/v7.0.2...v8.0.0) (2020-06-23) 100 | 101 | ### Features 102 | 103 | - **eslint:** v7 ([55ebb7f](https://github.com/spotify/web-scripts/commit/55ebb7f402546e9c8d7c7372cafbd6f49f17790c)) 104 | 105 | ### BREAKING CHANGES 106 | 107 | - **eslint:** see release notes for eslint v7 108 | 109 | # [7.0.0](https://github.com/spotify/web-scripts/compare/v6.2.0...v7.0.0) (2020-04-28) 110 | 111 | - major release- 7.0.0 (#318) ([29509b4](https://github.com/spotify/web-scripts/commit/29509b4a52325080b7a38f3aeb41ce8ed82f04f5)), closes [#318](https://github.com/spotify/web-scripts/issues/318) [#314](https://github.com/spotify/web-scripts/issues/314) [#312](https://github.com/spotify/web-scripts/issues/312) [#310](https://github.com/spotify/web-scripts/issues/310) 112 | 113 | ### BREAKING CHANGES 114 | 115 | - running web-scripts without arguments exits code 1 now instead of exiting 0 116 | - prettier 2.0 may introduce breaking changes 117 | - prettier 2.0 may introduce breaking changes 118 | 119 | - improvement(web-scripts): make stylecheck and typecheck default for lint 120 | 121 | the lint script will now default typechecking and stylechecking to true by default. You may shut 122 | these off with `--no-typecheck` and `--no-stylecheck`. 123 | 124 | - Users who have projects incompatible with TypeScript checks or with projects that 125 | do not user prettier will now fail yarn lint. 126 | 127 | # [6.2.0](https://github.com/spotify/web-scripts/compare/v6.1.1...v6.2.0) (2020-04-04) 128 | 129 | **Note:** Version bump only for package @spotify/eslint-config-base 130 | 131 | ## [6.1.1](https://github.com/spotify/web-scripts/compare/v6.1.0...v6.1.1) (2020-04-03) 132 | 133 | **Note:** Version bump only for package @spotify/eslint-config-base 134 | 135 | # [6.1.0](https://github.com/spotify/web-scripts/compare/v6.0.2...v6.1.0) (2020-03-12) 136 | 137 | ### Features 138 | 139 | - **eslint-config-base:** add rule for diabling unsafe finally blocks ([#230](https://github.com/spotify/web-scripts/issues/230)) ([5869bf9](https://github.com/spotify/web-scripts/commit/5869bf994038e918d3ae59c899d4bc2fbe465c6e)) 140 | 141 | # [6.0.0](https://github.com/spotify/web-scripts/compare/v5.3.0...v6.0.0) (2020-01-29) 142 | 143 | ### Build System 144 | 145 | - bump node in engines to 10.18.0 ([08ea936](https://github.com/spotify/web-scripts/commit/08ea936faf879be18b97f8a4ba99aba5926ccff8)) 146 | 147 | ### BREAKING CHANGES 148 | 149 | - increasing Node version in engines declaration 150 | 151 | ## [5.0.2](https://github.com/spotify/web-scripts/compare/v5.0.1...v5.0.2) (2020-01-21) 152 | 153 | ### Bug Fixes 154 | 155 | - **eslint-config-base:** allow triple slashes ([8ee981d](https://github.com/spotify/web-scripts/commit/8ee981dc6a2628fad0e62fb0d25938fd9dd0b4aa)), closes [#117](https://github.com/spotify/web-scripts/issues/117) 156 | 157 | # [5.0.0](https://github.com/spotify/web-scripts/compare/v4.0.2...v5.0.0) (2020-01-06) 158 | 159 | **Note:** Version bump only for package @spotify/eslint-config-base 160 | 161 | # [4.0.0](https://github.com/spotify/web-scripts/compare/v3.3.1...v4.0.0) (2020-01-03) 162 | 163 | ### chore 164 | 165 | - bump engine to >=10.13.0 ([9527453](https://github.com/spotify/web-scripts/commit/9527453a03ea0a807e6f6964469bf8482a3e3cca)) 166 | 167 | ### BREAKING CHANGES 168 | 169 | - Minimum Node version has been increased 170 | 171 | # [3.0.0](https://github.com/spotify/web-scripts/compare/v2.1.0...v3.0.0) (2019-10-10) 172 | 173 | **Note:** Version bump only for package @spotify/eslint-config-base 174 | 175 | # [2.0.0](https://github.com/spotify/web-scripts/compare/v1.4.0...v2.0.0) (2019-09-23) 176 | 177 | ### Features 178 | 179 | - **eslint-config-base:** Add rule for disallowing useless constructors ([beab7ec](https://github.com/spotify/web-scripts/commit/beab7ec)) 180 | 181 | ### BREAKING CHANGES 182 | 183 | - **eslint-config-base:** Adding a lint rule which doesn't have a fix, which means that upgrading could break 184 | builds due to the new rule. 185 | 186 | ## [1.1.4](https://github.com/spotify/web-scripts/compare/v1.1.3...v1.1.4) (2019-07-17) 187 | 188 | ### Bug Fixes 189 | 190 | - Add repostiory field to package.json files ([fccd2db](https://github.com/spotify/web-scripts/commit/fccd2db)) 191 | 192 | # [1.1.0](https://github.com/spotify/web-scripts/compare/v1.0.2...v1.1.0) (2019-07-01) 193 | 194 | ### Bug Fixes 195 | 196 | - support ESLint 6 in our configs ([59341e3](https://github.com/spotify/web-scripts/commit/59341e3)) 197 | - Updates engines field to node >=10 ([b3b4f58](https://github.com/spotify/web-scripts/commit/b3b4f58)) 198 | 199 | ## [1.0.2](https://github.com/spotify/web-scripts/compare/v1.0.1...v1.0.2) (2019-06-26) 200 | 201 | ### Bug Fixes 202 | 203 | - update dependencies for peerDependency warnings ([eceff7c](https://github.com/spotify/web-scripts/commit/eceff7c)) 204 | 205 | ## [1.0.1](https://github.com/spotify/web-scripts/compare/v1.0.0...v1.0.1) (2019-06-24) 206 | 207 | **Note:** Version bump only for package @spotify/eslint-config-base 208 | -------------------------------------------------------------------------------- /packages/web-scripts/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Spotify AB 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import { program, Command } from 'commander'; 17 | import { SpawnSyncReturns } from 'child_process'; 18 | 19 | import { 20 | AuditTaskDesc, 21 | BuildTaskDesc, 22 | CommitTaskDesc, 23 | CommitMsgTaskDesc, 24 | FormatTaskDesc, 25 | LintTaskDesc, 26 | PrecommitTaskDesc, 27 | ReleaseTaskDesc, 28 | TestTaskDesc, 29 | } from './SharedTypes'; 30 | import { COMMITLINT_CONIFG } from './Paths'; 31 | import { auditTask } from './Tasks/AuditTasks'; 32 | import { testTask } from './Tasks/TestTask'; 33 | import { buildTask } from './Tasks/BuildTask'; 34 | import { lintTask } from './Tasks/LintTask'; 35 | import { formatTask } from './Tasks/FormatTask'; 36 | import { 37 | commitTask, 38 | commitMsgTask, 39 | releaseTask, 40 | precommitTask, 41 | } from './Tasks/CommitTasks'; 42 | 43 | program 44 | .command('init') 45 | .description('initialize your package to use web-scripts') 46 | .action(() => { 47 | throw new Error('unimplemented'); 48 | }); 49 | 50 | program 51 | .command('build') 52 | .allowUnknownOption() 53 | .description('Build your project into esm, cjs, and types folders') 54 | .option('--no-esm', 'do not build esm target') 55 | .option('--no-cjs', 'do not build cjs target') 56 | .option('--no-types', 'do not build types target') 57 | .action((...args) => { 58 | const cmd = getCommand(args); 59 | const { esm, types, cjs } = getOpts(cmd); 60 | const t: BuildTaskDesc = { 61 | name: 'build', 62 | esm, 63 | types, 64 | cjs, 65 | restOptions: cmd.args, 66 | }; 67 | 68 | handlePromiseResult(buildTask(t)); 69 | }); 70 | 71 | program 72 | .command('test') 73 | .allowUnknownOption() 74 | .description('Run tests via jest') 75 | .option('--config [path]', 'path to jest config') 76 | .action((...args) => { 77 | const cmd = getCommand(args); 78 | const { config } = getOpts(cmd); 79 | const t: TestTaskDesc = { 80 | name: 'test', 81 | config, 82 | restOptions: cmd.args, 83 | }; 84 | 85 | const result = testTask(t); 86 | handleSpawnResult(result); 87 | }); 88 | 89 | program 90 | .command('lint') 91 | .allowUnknownOption() 92 | .description('Run ESLint and TypeScript to statically analyze your code') 93 | .option('--config [path]', 'path to ESLint config') 94 | .option('--typecheck', 'run a TypeScript type check', true) 95 | .option('--no-typecheck', 'do not run a TypeScript type check') 96 | .option('--stylecheck', "run Prettier's style check", true) 97 | .option('--no-stylecheck', "do not run Prettier's style check") 98 | .action((...args) => { 99 | const cmd = getCommand(args); 100 | const { stylecheck, typecheck, config } = getOpts(cmd); 101 | const t: LintTaskDesc = { 102 | name: 'lint', 103 | config, 104 | stylecheck, 105 | typecheck, 106 | restOptions: cmd.args, 107 | }; 108 | 109 | handlePromiseResult(lintTask(t)); 110 | }); 111 | 112 | program 113 | .command('format') 114 | .allowUnknownOption() 115 | .description('Run Prettier to format your code') 116 | .option('--config [path]', 'path to Prettier config') 117 | .option( 118 | '--path [path]', 119 | 'path to project folder to format. targets the `src` directory within this path only.', 120 | ) 121 | .action((...args) => { 122 | const cmd = getCommand(args); 123 | const { config, path } = getOpts(cmd); 124 | const t: FormatTaskDesc = { 125 | name: 'format', 126 | config, 127 | path, 128 | restOptions: cmd.args, 129 | }; 130 | 131 | handleSpawnResult(formatTask(t)); 132 | }); 133 | 134 | program 135 | .command('precommit') 136 | .allowUnknownOption() 137 | .description('Locally validate the repo before committing') 138 | .option('--jest-config [path]', 'path to jest config') 139 | .option('--prettier-config [path]', 'path to prettier config') 140 | .option('--eslint-config [path]', 'path to eslint config') 141 | .option('--no-tests', 'Do not run Jest tests') 142 | .option('--no-typecheck', 'Do not type check using TypeScript') 143 | .action((...args) => { 144 | const cmd = getCommand(args); 145 | const { tests, typecheck, jestConfig, eslintConfig, prettierConfig } = 146 | getOpts(cmd); 147 | const t: PrecommitTaskDesc = { 148 | name: 'precommit', 149 | tests, 150 | typecheck, 151 | jestConfig, 152 | eslintConfig, 153 | prettierConfig, 154 | restOptions: cmd.args, 155 | }; 156 | 157 | handlePromiseResult(precommitTask(t)); 158 | }); 159 | 160 | function thresholdLimiter(value: string, defaultValue: string) { 161 | switch (value) { 162 | case 'info': 163 | case 'low': 164 | case 'moderate': 165 | case 'high': 166 | case 'critical': 167 | return value; 168 | default: 169 | return defaultValue; 170 | } 171 | } 172 | 173 | program 174 | .command('audit') 175 | .alias('postinstall') 176 | .allowUnknownOption() 177 | .description( 178 | `Run yarn audit and exit non-zero if the security vulnerability threshold is breached`, 179 | ) 180 | .option( 181 | '--threshold [info|low|moderate|high|critical]', 182 | 'The amount of permissible vulnerabilities', 183 | thresholdLimiter, 184 | 'none', 185 | ) 186 | .action((...args) => { 187 | const cmd = getCommand(args); 188 | const { threshold } = getOpts(cmd); 189 | const t: AuditTaskDesc = { 190 | name: 'audit', 191 | threshold, 192 | restOptions: cmd.args, 193 | }; 194 | 195 | handlePromiseResult(auditTask(t)); 196 | }); 197 | 198 | program 199 | .command('commit') 200 | .allowUnknownOption() 201 | .description('Create Commitizen commit from staged files') 202 | .option( 203 | '--path [path]', 204 | 'path for commitizen adapter to use', 205 | 'cz-conventional-changelog', 206 | ) 207 | .action((...args) => { 208 | const cmd = getCommand(args); 209 | const { path } = getOpts(cmd); 210 | const t: CommitTaskDesc = { 211 | name: 'commit', 212 | path, 213 | restOptions: cmd.args, 214 | }; 215 | 216 | try { 217 | commitTask(t); 218 | } catch (err) { 219 | handleError(err as Error & { exitStatus?: number }); 220 | } 221 | }); 222 | 223 | program 224 | .command('commitmsg') 225 | .allowUnknownOption() 226 | .description('Run commitizen commit message validation hook') 227 | .option( 228 | '--config [path]', 229 | 'path to the commitlint config.', 230 | COMMITLINT_CONIFG, 231 | ) 232 | .option( 233 | '--edit [path]', 234 | 'read last commit message from the specified file (only necessary when using Husky v6).', 235 | ) 236 | .action((...args) => { 237 | const cmd = getCommand(args); 238 | const { config, edit } = getOpts(cmd); 239 | const t: CommitMsgTaskDesc = { 240 | name: 'commitmsg', 241 | config, 242 | edit, 243 | restOptions: cmd.args, 244 | }; 245 | 246 | handleSpawnResult(commitMsgTask(t)); 247 | }); 248 | 249 | program 250 | .command('release') 251 | .allowUnknownOption() 252 | .description('Run semantic-release') 253 | .action((...args) => { 254 | const cmd = getCommand(args); 255 | const t: ReleaseTaskDesc = { 256 | name: 'release', 257 | restOptions: cmd.args, 258 | }; 259 | 260 | handleSpawnResult(releaseTask(t)); 261 | }); 262 | 263 | function handlePromiseResult(result: Promise) { 264 | result.catch(handleError); 265 | } 266 | 267 | function handleError(error: Error & { exitStatus?: number }) { 268 | /* eslint-disable no-console */ 269 | // only log if the error is useful (e.g. not the default message from non-zero status is in cross-spawn) 270 | if (error.message && error.message.indexOf('Error: Exited with status') < 0) { 271 | console.error(error); 272 | } 273 | /* eslint-enable no-console */ 274 | process.exit(error.exitStatus || 1); 275 | } 276 | 277 | function handleSpawnResult(result: SpawnSyncReturns) { 278 | if (result.error) { 279 | throw result.error; 280 | } 281 | 282 | if (result.status !== 0) { 283 | process.exit(result.status === null ? 0 : result.status); 284 | } 285 | } 286 | 287 | function getCommand(args: any[]): Command { 288 | return args[1] as Command; 289 | } 290 | 291 | function getOpts(cmd: Command): { [key: string]: any } { 292 | return cmd.opts(); 293 | } 294 | 295 | program.parse(process.argv); 296 | 297 | if (!process.argv.slice(2).length) { 298 | program.help(); 299 | } 300 | -------------------------------------------------------------------------------- /packages/eslint-config-react/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **deps:** upgrade dependencies ([ef060c7](https://github.com/spotify/web-scripts/commit/ef060c7da531060cc1d0f0fb60d3df8f355e418e)) 11 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 12 | 13 | ### BREAKING CHANGES 14 | 15 | - **node:** Node bump from v14 to v18 16 | - **deps:** TypeScript bump from v4 to v5, Jest bump from v28 to v29 17 | 18 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 19 | 20 | **Note:** Version bump only for package @spotify/eslint-config-react 21 | 22 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 23 | 24 | **Note:** Version bump only for package @spotify/eslint-config-react 25 | 26 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 27 | 28 | **Note:** Version bump only for package @spotify/eslint-config-react 29 | 30 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 31 | 32 | **Note:** Version bump only for package @spotify/eslint-config-react 33 | 34 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 35 | 36 | **Note:** Version bump only for package @spotify/eslint-config-react 37 | 38 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 39 | 40 | **Note:** Version bump only for package @spotify/eslint-config-react 41 | 42 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 43 | 44 | **Note:** Version bump only for package @spotify/eslint-config-react 45 | 46 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 47 | 48 | **Note:** Version bump only for package @spotify/eslint-config-react 49 | 50 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 51 | 52 | **Note:** Version bump only for package @spotify/eslint-config-react 53 | 54 | # [14.0.0](https://github.com/spotify/web-scripts/compare/v13.0.1...v14.0.0) (2022-07-11) 55 | 56 | **Note:** Version bump only for package @spotify/eslint-config-react 57 | 58 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 59 | 60 | **Note:** Version bump only for package @spotify/eslint-config-react 61 | 62 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 63 | 64 | ### chore 65 | 66 | - update [@typescript-eslint](https://github.com/typescript-eslint) from v4 to v5, eslint from v7 to v8 ([e284943](https://github.com/spotify/web-scripts/commit/e28494330a6dd9c2561370f56a4eed1ef152f23d)) 67 | 68 | ### BREAKING CHANGES 69 | 70 | - update @typescript-eslint from v4 to v5, eslint from v7 to v8 71 | 72 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 73 | 74 | ### Build System 75 | 76 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 77 | 78 | ### BREAKING CHANGES 79 | 80 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 81 | 82 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 83 | 84 | **Note:** Version bump only for package @spotify/eslint-config-react 85 | 86 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 87 | 88 | ### Build System 89 | 90 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 91 | 92 | ### Features 93 | 94 | - **eslint-config-react:** disable react/prop-types rule ([d445345](https://github.com/spotify/web-scripts/commit/d4453456e8d70accd5beede7c5adfd3a814afe35)) 95 | 96 | ### BREAKING CHANGES 97 | 98 | - drop support for NodeJS v10.x, which reaches EOL on 99 | April 30, 2021. 100 | 101 | ## [9.0.2](https://github.com/spotify/web-scripts/compare/v9.0.1...v9.0.2) (2021-02-26) 102 | 103 | ### Bug Fixes 104 | 105 | - disable no-undef ([52926ad](https://github.com/spotify/web-scripts/commit/52926ad7b8d94170b0b2584afc14cdb666d47427)) 106 | 107 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 108 | 109 | **Note:** Version bump only for package @spotify/eslint-config-react 110 | 111 | ## [8.0.2](https://github.com/spotify/web-scripts/compare/v8.0.1...v8.0.2) (2020-07-15) 112 | 113 | ### Bug Fixes 114 | 115 | - **eslint-config-react:** fix peer dependency on eslint-plugin-react-hooks ([8591423](https://github.com/spotify/web-scripts/commit/859142322212ed3ef5ac2140b831e4244487d91c)) 116 | 117 | # [8.0.0](https://github.com/spotify/web-scripts/compare/v7.0.2...v8.0.0) (2020-06-23) 118 | 119 | ### Features 120 | 121 | - **eslint:** v7 ([55ebb7f](https://github.com/spotify/web-scripts/commit/55ebb7f402546e9c8d7c7372cafbd6f49f17790c)) 122 | 123 | ### BREAKING CHANGES 124 | 125 | - **eslint:** see release notes for eslint v7 126 | 127 | ## [7.0.1](https://github.com/spotify/web-scripts/compare/v7.0.0...v7.0.1) (2020-05-15) 128 | 129 | **Note:** Version bump only for package @spotify/eslint-config-react 130 | 131 | # [7.0.0](https://github.com/spotify/web-scripts/compare/v6.2.0...v7.0.0) (2020-04-28) 132 | 133 | - major release- 7.0.0 (#318) ([29509b4](https://github.com/spotify/web-scripts/commit/29509b4a52325080b7a38f3aeb41ce8ed82f04f5)), closes [#318](https://github.com/spotify/web-scripts/issues/318) [#314](https://github.com/spotify/web-scripts/issues/314) [#312](https://github.com/spotify/web-scripts/issues/312) [#310](https://github.com/spotify/web-scripts/issues/310) 134 | 135 | ### BREAKING CHANGES 136 | 137 | - running web-scripts without arguments exits code 1 now instead of exiting 0 138 | - prettier 2.0 may introduce breaking changes 139 | - prettier 2.0 may introduce breaking changes 140 | 141 | - improvement(web-scripts): make stylecheck and typecheck default for lint 142 | 143 | the lint script will now default typechecking and stylechecking to true by default. You may shut 144 | these off with `--no-typecheck` and `--no-stylecheck`. 145 | 146 | - Users who have projects incompatible with TypeScript checks or with projects that 147 | do not user prettier will now fail yarn lint. 148 | 149 | # [6.2.0](https://github.com/spotify/web-scripts/compare/v6.1.1...v6.2.0) (2020-04-04) 150 | 151 | **Note:** Version bump only for package @spotify/eslint-config-react 152 | 153 | ## [6.1.1](https://github.com/spotify/web-scripts/compare/v6.1.0...v6.1.1) (2020-04-03) 154 | 155 | **Note:** Version bump only for package @spotify/eslint-config-react 156 | 157 | # [6.0.0](https://github.com/spotify/web-scripts/compare/v5.3.0...v6.0.0) (2020-01-29) 158 | 159 | ### Build System 160 | 161 | - bump node in engines to 10.18.0 ([08ea936](https://github.com/spotify/web-scripts/commit/08ea936faf879be18b97f8a4ba99aba5926ccff8)) 162 | 163 | ### BREAKING CHANGES 164 | 165 | - increasing Node version in engines declaration 166 | 167 | # [5.2.0](https://github.com/spotify/web-scripts/compare/v5.1.0...v5.2.0) (2020-01-22) 168 | 169 | ### Features 170 | 171 | - **index.js:** Add react/jsx-curly-brace-presence rule ([fbef1ae](https://github.com/spotify/web-scripts/commit/fbef1ae18d4176819c357862a031e34c16d12bbb)) 172 | 173 | # [5.0.0](https://github.com/spotify/web-scripts/compare/v4.0.2...v5.0.0) (2020-01-06) 174 | 175 | **Note:** Version bump only for package @spotify/eslint-config-react 176 | 177 | # [4.0.0](https://github.com/spotify/web-scripts/compare/v3.3.1...v4.0.0) (2020-01-03) 178 | 179 | ### chore 180 | 181 | - bump engine to >=10.13.0 ([9527453](https://github.com/spotify/web-scripts/commit/9527453a03ea0a807e6f6964469bf8482a3e3cca)) 182 | 183 | ### Features 184 | 185 | - **web-scripts:** Upgrade to ESLint ^6.8.0 ([d0c37e9](https://github.com/spotify/web-scripts/commit/d0c37e9b63e4260eeaffda632a8d0840a793fec4)) 186 | 187 | ### BREAKING CHANGES 188 | 189 | - Minimum Node version has been increased 190 | - **web-scripts:** Users of web-scripts that rely on ESLint 5 will see unexpected linting errors. 191 | 192 | ## [3.0.1](https://github.com/spotify/web-scripts/compare/v3.0.0...v3.0.1) (2019-10-24) 193 | 194 | ### Bug Fixes 195 | 196 | - **eslint-config-react:** Add `static-variables` to `react/sort-comp` ([f0526c0](https://github.com/spotify/web-scripts/commit/f0526c0)) 197 | 198 | # [3.0.0](https://github.com/spotify/web-scripts/compare/v2.1.0...v3.0.0) (2019-10-10) 199 | 200 | **Note:** Version bump only for package @spotify/eslint-config-react 201 | 202 | # [2.0.0](https://github.com/spotify/web-scripts/compare/v1.4.0...v2.0.0) (2019-09-23) 203 | 204 | **Note:** Version bump only for package @spotify/eslint-config-react 205 | 206 | ## [1.1.4](https://github.com/spotify/web-scripts/compare/v1.1.3...v1.1.4) (2019-07-17) 207 | 208 | ### Bug Fixes 209 | 210 | - Add repostiory field to package.json files ([fccd2db](https://github.com/spotify/web-scripts/commit/fccd2db)) 211 | 212 | # [1.1.0](https://github.com/spotify/web-scripts/compare/v1.0.2...v1.1.0) (2019-07-01) 213 | 214 | ### Bug Fixes 215 | 216 | - support ESLint 6 in our configs ([59341e3](https://github.com/spotify/web-scripts/commit/59341e3)) 217 | - Updates engines field to node >=10 ([b3b4f58](https://github.com/spotify/web-scripts/commit/b3b4f58)) 218 | 219 | ## [1.0.2](https://github.com/spotify/web-scripts/compare/v1.0.1...v1.0.2) (2019-06-26) 220 | 221 | ### Bug Fixes 222 | 223 | - update dependencies for peerDependency warnings ([eceff7c](https://github.com/spotify/web-scripts/commit/eceff7c)) 224 | 225 | ## [1.0.1](https://github.com/spotify/web-scripts/compare/v1.0.0...v1.0.1) (2019-06-24) 226 | 227 | **Note:** Version bump only for package @spotify/eslint-config-react 228 | -------------------------------------------------------------------------------- /packages/eslint-config-typescript/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [15.0.0](https://github.com/spotify/web-scripts/compare/v14.1.6...v15.0.0) (2023-05-18) 7 | 8 | ### chore 9 | 10 | - **deps:** upgrade dependencies ([ef060c7](https://github.com/spotify/web-scripts/commit/ef060c7da531060cc1d0f0fb60d3df8f355e418e)) 11 | - **node:** upgrade required Node version to 18 ([9528841](https://github.com/spotify/web-scripts/commit/952884179ba7378440599b8acb109a98500535ee)) 12 | 13 | ### BREAKING CHANGES 14 | 15 | - **node:** Node bump from v14 to v18 16 | - **deps:** TypeScript bump from v4 to v5, Jest bump from v28 to v29 17 | 18 | ## [14.1.6](https://github.com/spotify/web-scripts/compare/v14.1.5...v14.1.6) (2023-02-14) 19 | 20 | **Note:** Version bump only for package @spotify/eslint-config-typescript 21 | 22 | ## [14.1.5](https://github.com/spotify/web-scripts/compare/v14.1.4...v14.1.5) (2023-01-30) 23 | 24 | **Note:** Version bump only for package @spotify/eslint-config-typescript 25 | 26 | ## [14.1.4](https://github.com/spotify/web-scripts/compare/v14.1.3...v14.1.4) (2023-01-19) 27 | 28 | **Note:** Version bump only for package @spotify/eslint-config-typescript 29 | 30 | ## [14.1.3](https://github.com/spotify/web-scripts/compare/v14.1.2...v14.1.3) (2022-12-07) 31 | 32 | **Note:** Version bump only for package @spotify/eslint-config-typescript 33 | 34 | ## [14.1.2](https://github.com/spotify/web-scripts/compare/v14.1.1...v14.1.2) (2022-12-02) 35 | 36 | **Note:** Version bump only for package @spotify/eslint-config-typescript 37 | 38 | ## [14.1.1](https://github.com/spotify/web-scripts/compare/v14.1.0...v14.1.1) (2022-11-25) 39 | 40 | **Note:** Version bump only for package @spotify/eslint-config-typescript 41 | 42 | # [14.1.0](https://github.com/spotify/web-scripts/compare/v14.0.2...v14.1.0) (2022-08-08) 43 | 44 | **Note:** Version bump only for package @spotify/eslint-config-typescript 45 | 46 | ## [14.0.2](https://github.com/spotify/web-scripts/compare/v14.0.1...v14.0.2) (2022-07-15) 47 | 48 | **Note:** Version bump only for package @spotify/eslint-config-typescript 49 | 50 | ## [14.0.1](https://github.com/spotify/web-scripts/compare/v14.0.0...v14.0.1) (2022-07-12) 51 | 52 | **Note:** Version bump only for package @spotify/eslint-config-typescript 53 | 54 | # [14.0.0](https://github.com/spotify/web-scripts/compare/v13.0.1...v14.0.0) (2022-07-11) 55 | 56 | **Note:** Version bump only for package @spotify/eslint-config-typescript 57 | 58 | ## [13.0.1](https://github.com/spotify/web-scripts/compare/v13.0.0...v13.0.1) (2022-04-19) 59 | 60 | **Note:** Version bump only for package @spotify/eslint-config-typescript 61 | 62 | # [13.0.0](https://github.com/spotify/web-scripts/compare/v12.0.0...v13.0.0) (2022-03-21) 63 | 64 | ### Bug Fixes 65 | 66 | - **eslint:** specify parserOptions.project ([5ea256c](https://github.com/spotify/web-scripts/commit/5ea256cc7a05927d94dc5bf1974fdb4e3ee94bc1)) 67 | - remove parserOptions.project ([c901579](https://github.com/spotify/web-scripts/commit/c901579eef6ed3723e94aca079d6f5171525ac41)) 68 | 69 | ### chore 70 | 71 | - update [@typescript-eslint](https://github.com/typescript-eslint) from v4 to v5, eslint from v7 to v8 ([e284943](https://github.com/spotify/web-scripts/commit/e28494330a6dd9c2561370f56a4eed1ef152f23d)) 72 | 73 | ### BREAKING CHANGES 74 | 75 | - update @typescript-eslint from v4 to v5, eslint from v7 to v8 76 | 77 | # [12.0.0](https://github.com/spotify/web-scripts/compare/v11.0.0...v12.0.0) (2021-09-22) 78 | 79 | ### Build System 80 | 81 | - **node:** drop support for Node v12. Support only NodeJS >= 14.17.x ([be04398](https://github.com/spotify/web-scripts/commit/be043986089b79feab63f2a06527f48239ac5144)) 82 | 83 | ### BREAKING CHANGES 84 | 85 | - **node:** Dropped support for Node v12. Minimum supported NodeJS version is now >= 14.17.x. 86 | 87 | # [11.0.0](https://github.com/spotify/web-scripts/compare/v10.1.0...v11.0.0) (2021-07-16) 88 | 89 | **Note:** Version bump only for package @spotify/eslint-config-typescript 90 | 91 | # [10.0.0](https://github.com/spotify/web-scripts/compare/v9.0.2...v10.0.0) (2021-04-14) 92 | 93 | ### Build System 94 | 95 | - drop support for nodejs v10.x ([3fe3059](https://github.com/spotify/web-scripts/commit/3fe3059225c33cc550027dd77dbf1a48fde810a3)) 96 | 97 | ### Features 98 | 99 | - **eslint-config-typescript:** turn off @typescript-eslint/no-unused-vars ([4845031](https://github.com/spotify/web-scripts/commit/48450315d99205f6ced4ca97b1de8f4899376680)) 100 | 101 | ### BREAKING CHANGES 102 | 103 | - drop support for NodeJS v10.x, which reaches EOL on 104 | April 30, 2021. 105 | 106 | # [9.0.0](https://github.com/spotify/web-scripts/compare/v8.1.1...v9.0.0) (2020-10-26) 107 | 108 | ### Bug Fixes 109 | 110 | - incorporate overrides for new typescript-eslint rules ([81b7111](https://github.com/spotify/web-scripts/commit/81b711141b08613a78a2020513f1b21df0c91116)) 111 | - relax no-use-before-define rule ([ee719aa](https://github.com/spotify/web-scripts/commit/ee719aa153b0debd8901006aef3b71a791ef093b)) 112 | - sync [@typescript-eslint](https://github.com/typescript-eslint) versions across repo ([fb20119](https://github.com/spotify/web-scripts/commit/fb201196a551a3b942410b1e5a3b40c5f43bc721)), closes [#555](https://github.com/spotify/web-scripts/issues/555) 113 | 114 | ## [8.1.1](https://github.com/spotify/web-scripts/compare/v8.1.0...v8.1.1) (2020-09-22) 115 | 116 | **Note:** Version bump only for package @spotify/eslint-config-typescript 117 | 118 | ## [8.0.1](https://github.com/spotify/web-scripts/compare/v8.0.0...v8.0.1) (2020-07-02) 119 | 120 | ### Bug Fixes 121 | 122 | - **eslint-config-typescript:** turn off naming-convention ([ed5eec3](https://github.com/spotify/web-scripts/commit/ed5eec3b879a5a9c08916cf8fd334ae99ec7cbaa)) 123 | 124 | # [8.0.0](https://github.com/spotify/web-scripts/compare/v7.0.2...v8.0.0) (2020-06-23) 125 | 126 | ### Features 127 | 128 | - **eslint:** v7 ([55ebb7f](https://github.com/spotify/web-scripts/commit/55ebb7f402546e9c8d7c7372cafbd6f49f17790c)) 129 | - **typescript-eslint:** upgrade to latest to support type export syntax ([688324b](https://github.com/spotify/web-scripts/commit/688324b2702dbf393f058bed6fa55f26bce99bac)) 130 | - **typescript-eslint/eslint-plugin:** v3.4.0 ([195400a](https://github.com/spotify/web-scripts/commit/195400a6082a35db59544d39b156d09d470661c7)) 131 | 132 | ### BREAKING CHANGES 133 | 134 | - **eslint:** see release notes for eslint v7 135 | - **typescript-eslint:** The camelcase rule was deprecated in typescript-eslint. I've tried to replace it 136 | with an equivalent naming-convention rule config. I question if we should have this at all. 137 | 138 | # [7.0.0](https://github.com/spotify/web-scripts/compare/v6.2.0...v7.0.0) (2020-04-28) 139 | 140 | - major release- 7.0.0 (#318) ([29509b4](https://github.com/spotify/web-scripts/commit/29509b4a52325080b7a38f3aeb41ce8ed82f04f5)), closes [#318](https://github.com/spotify/web-scripts/issues/318) [#314](https://github.com/spotify/web-scripts/issues/314) [#312](https://github.com/spotify/web-scripts/issues/312) [#310](https://github.com/spotify/web-scripts/issues/310) 141 | 142 | ### BREAKING CHANGES 143 | 144 | - running web-scripts without arguments exits code 1 now instead of exiting 0 145 | - prettier 2.0 may introduce breaking changes 146 | - prettier 2.0 may introduce breaking changes 147 | 148 | - improvement(web-scripts): make stylecheck and typecheck default for lint 149 | 150 | the lint script will now default typechecking and stylechecking to true by default. You may shut 151 | these off with `--no-typecheck` and `--no-stylecheck`. 152 | 153 | - Users who have projects incompatible with TypeScript checks or with projects that 154 | do not user prettier will now fail yarn lint. 155 | 156 | # [6.2.0](https://github.com/spotify/web-scripts/compare/v6.1.1...v6.2.0) (2020-04-04) 157 | 158 | **Note:** Version bump only for package @spotify/eslint-config-typescript 159 | 160 | ## [6.1.1](https://github.com/spotify/web-scripts/compare/v6.1.0...v6.1.1) (2020-04-03) 161 | 162 | **Note:** Version bump only for package @spotify/eslint-config-typescript 163 | 164 | # [6.0.0](https://github.com/spotify/web-scripts/compare/v5.3.0...v6.0.0) (2020-01-29) 165 | 166 | ### Build System 167 | 168 | - bump node in engines to 10.18.0 ([08ea936](https://github.com/spotify/web-scripts/commit/08ea936faf879be18b97f8a4ba99aba5926ccff8)) 169 | 170 | ### BREAKING CHANGES 171 | 172 | - increasing Node version in engines declaration 173 | 174 | # [5.0.0](https://github.com/spotify/web-scripts/compare/v4.0.2...v5.0.0) (2020-01-06) 175 | 176 | **Note:** Version bump only for package @spotify/eslint-config-typescript 177 | 178 | # [4.0.0](https://github.com/spotify/web-scripts/compare/v3.3.1...v4.0.0) (2020-01-03) 179 | 180 | ### Features 181 | 182 | - eslint 6 updates ([d5444b6](https://github.com/spotify/web-scripts/commit/d5444b6f1607cbd87778bbe7e7d2bb0dc8df3a55)) 183 | - **web-scripts:** Upgrade to ESLint ^6.8.0 ([d0c37e9](https://github.com/spotify/web-scripts/commit/d0c37e9b63e4260eeaffda632a8d0840a793fec4)) 184 | 185 | ### BREAKING CHANGES 186 | 187 | - **web-scripts:** Users of web-scripts that rely on ESLint 5 will see unexpected linting errors. 188 | 189 | # [3.0.0](https://github.com/spotify/web-scripts/compare/v2.1.0...v3.0.0) (2019-10-10) 190 | 191 | ### Bug Fixes 192 | 193 | - **eslint-config:** Update typescript-eslint packages to ^2.2.0 ([bda6c5f](https://github.com/spotify/web-scripts/commit/bda6c5f)) 194 | 195 | ### BREAKING CHANGES 196 | 197 | - **eslint-config:** Major version bump 198 | 199 | ## [2.0.1](https://github.com/spotify/web-scripts/compare/v2.0.0...v2.0.1) (2019-09-27) 200 | 201 | ### Bug Fixes 202 | 203 | - **eslint-config-typescript:** add no-useless-constructor override ([72c6651](https://github.com/spotify/web-scripts/commit/72c6651)) 204 | 205 | # [2.0.0](https://github.com/spotify/web-scripts/compare/v1.4.0...v2.0.0) (2019-09-23) 206 | 207 | **Note:** Version bump only for package @spotify/eslint-config-typescript 208 | 209 | ## [1.1.4](https://github.com/spotify/web-scripts/compare/v1.1.3...v1.1.4) (2019-07-17) 210 | 211 | ### Bug Fixes 212 | 213 | - Add repostiory field to package.json files ([fccd2db](https://github.com/spotify/web-scripts/commit/fccd2db)) 214 | 215 | # [1.1.0](https://github.com/spotify/web-scripts/compare/v1.0.2...v1.1.0) (2019-07-01) 216 | 217 | ### Bug Fixes 218 | 219 | - support ESLint 6 in our configs ([59341e3](https://github.com/spotify/web-scripts/commit/59341e3)) 220 | - Updates engines field to node >=10 ([b3b4f58](https://github.com/spotify/web-scripts/commit/b3b4f58)) 221 | 222 | ## [1.0.2](https://github.com/spotify/web-scripts/compare/v1.0.1...v1.0.2) (2019-06-26) 223 | 224 | ### Bug Fixes 225 | 226 | - update dependencies for peerDependency warnings ([eceff7c](https://github.com/spotify/web-scripts/commit/eceff7c)) 227 | 228 | ## [1.0.1](https://github.com/spotify/web-scripts/compare/v1.0.0...v1.0.1) (2019-06-24) 229 | 230 | **Note:** Version bump only for package @spotify/eslint-config-typescript 231 | --------------------------------------------------------------------------------