This is the Sofie code standard preset library used in the Sofie TV Automation System for defining a code standard preset through ESLint and Prettier.
A script for checking compatible licenses is included.
This preset requires yarn v4. The setup script enforces this, and the generated lint scripts use yarn directly.
First, install the package:
yarn add --dev @sofie-automation/code-standard-presetThen either use the setup script or follow the manual steps below.
Run the setup CLI, which will install all required devDependencies and configure the project automatically:
yarn sofie-code-standard-preset-setupThis will:
- Delete
.prettierrc.jsonif present (it takes precedence overpackage.jsonand would shadow the preset config), then set theprettierfield inpackage.jsonto use the preset's config - Add
lint,lint:eslint,lint:prettier,lint:fix,license-validateandpreparescripts topackage.json - Set
lint-stagedconfig inpackage.json - Create
eslint.config.mjsif missing - Copy
.editorconfigfrom the preset (always overwrites — the preset's copy is always canonical, since there was no standard version to update from in older releases) - Create
.husky/pre-commitif missing - Install required devDependencies:
@eslint/js,eslint,husky,lint-staged,prettier,typescript
If any of the above items are already configured to a different value, they will be skipped with a warning. Pass --force to overwrite existing values:
yarn sofie-code-standard-preset-setup --forceFor monorepos, also pass --fix-subpackages to remove redundant prettier config keys and files from sub-packages, remove legacy ESLint config files (.eslintrc.*) from sub-packages, and report any flat eslint.config.mjs files in sub-packages for manual review.
Then continue with Next steps below.
If you prefer to configure manually, or if the setup script does not work for your project, follow these steps.
Install the required devDependencies:
yarn add --dev @eslint/js eslint@^9 husky@^9 lint-staged@^17 prettier@^3 typescript@~6.0Add the following to your package.json:
{
...,
"scripts": {
...,
"prepare": "husky",
"lint:eslint": "eslint .",
"lint:prettier": "prettier --check .",
"lint": "yarn lint:eslint && yarn lint:prettier",
"lint:fix": "yarn lint:eslint --fix && yarn lint:prettier --write",
"license-validate": "sofie-licensecheck"
},
"prettier": "@sofie-automation/code-standard-preset/prettier.config.mjs",
"lint-staged": {
"*.{css,json,md,scss}": [
"prettier --check"
],
"*.{ts,tsx,js,jsx,mjs,cjs}": [
"eslint"
]
},
...
}If you have an existing .prettierrc.json, remove it — Prettier finds .prettierrc.json before the package.json prettier key, so it must be removed to avoid it shadowing the preset config.
Create the husky hook file .husky/pre-commit:
lint-stagedCreate eslint.config.mjs:
import { generateEslintConfig } from '@sofie-automation/code-standard-preset/eslint/main.mjs'
export default await generateEslintConfig({})Copy the .editorconfig file from this package into the root of your project.
Whether you used the setup script or configured manually, commit your changes, run yarn lint:fix to apply any formatting or import-order changes, and commit again:
git add -A && git commit -m "chore: add sofie code standard preset"
yarn lint:fix
git add -A && git commit -m "chore: apply lint fixes"The following steps are project-specific and cannot be automated.
The generateEslintConfig function accepts options to adjust the config for your project:
{
/** Any extra paths to be ignored by eslint */
ignores?: string[]
/** If you need eslint to use a non-default tsconfig, provide the path. When not set it uses the default search behaviour */
tsconfigName?: string | string[]
/** If the project is browser based instead of node based, you can disable the node runtime rules */
disableNodeRules?: boolean
}If you need to add additional rules, you can extend the generated config:
import pluginYaml from 'eslint-plugin-yml'
import { generateEslintConfig } from '@sofie-automation/code-standard-preset/eslint/main.mjs'
const extendedRules = await generateEslintConfig({
ignores: ['client', 'server'],
})
extendedRules.push(...pluginYaml.configs['flat/recommended'], {
files: ['**/*.yaml'],
rules: {
'yml/quotes': ['error', { prefer: 'single' }],
'yml/spaced-comment': ['error'],
'spaced-comment': ['off'],
},
})
export default extendedRulesCreate the following TypeScript config files if they don't exist:
tsconfig.json
{
"extends": "./tsconfig.build.json",
"exclude": ["node_modules/**"],
"compilerOptions": {
"types": ["jest", "node"]
}
}tsconfig.build.json
{
"extends": "@sofie-automation/code-standard-preset/ts/tsconfig.lib",
"include": ["src/**/*.ts"],
"exclude": ["node_modules/**", "src/**/*spec.ts", "src/**/__tests__/*", "src/**/__mocks__/*"],
"compilerOptions": {
"outDir": "./dist",
"baseUrl": "./",
"paths": {
"*": ["./node_modules/*"],
"{{PACKAGE-NAME}}": ["./src/index.ts"]
},
"types": ["node"]
}
}Note: If you are using this in a 'binary' package, then you should use tsconfig.bin instead of tsconfig.lib. This adjusts the build and output slightly.
Note: replace {{PACKAGE-NAME}} with the correct package name, e.g. hyperdeck-connection
Adjust build script references to make sure they use tsconfig.build.json, e.g. tsc -p tsconfig.build.json.
Vitest is the recommended test runner for new projects. Install it with:
yarn add --dev vitestThen pass testRunner: 'vitest' to generateEslintConfig in your eslint.config.mjs:
export default await generateEslintConfig({ testRunner: 'vitest' })This enables the @vitest/eslint-plugin rules on your test files.
Jest is still fully supported. If using jest, adjust jest configuration files to use tsconfig.json. For example, update the start of jest.config.js:
module.exports = {
transform: {
'^.+\\.(ts|tsx)$': [
'ts-jest',
{
tsconfig: 'tsconfig.json',
},
],
},
// ...Ensure the following devDependencies are present if using jest:
@types/node,@types/jestjest,ts-jest
Remove any old linting or tsconfig files and references to them, for example a config folder containing tsconfig... files. These are no longer required.
Optionally add a .gitattributes file to ensure consistent line endings:
* text=auto eol=lf
Node 22 is now the minimum supported version (up from Node 20). Update your package.json engines field:
"engines": { "node": ">= 22.12" }TypeScript ~6.0 is now required. Update your package.json devDependency:
yarn add --dev typescript@~6.0husky@^9 and lint-staged@^17 are now required. If you need to update them:
yarn add --dev husky@^9 lint-staged@^17Import sorting via @ianvs/prettier-plugin-sort-imports is now bundled with this package. You must switch your prettier config reference from .prettierrc.json to prettier.config.mjs:
In package.json, change:
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",to:
"prettier": "@sofie-automation/code-standard-preset/prettier.config.mjs",This is necessary because Prettier resolves plugin names in JSON configs relative to the consumer project, whereas an .mjs config resolves imports from its own location inside the package.
After switching, run yarn lint:fix to apply any import order changes across your codebase.
The lint script names have been standardised. In package.json, replace any old-style scripts:
"lint:raw": "eslint",
"lint": "run lint:raw .",
"lint-fix": "run lint --fix",with:
"lint:eslint": "eslint .",
"lint:prettier": "prettier --check .",
"lint": "yarn lint:eslint && yarn lint:prettier",
"lint:fix": "yarn lint:eslint --fix && yarn lint:prettier --write",Also update lint-staged to use check-only commands (pre-commit hooks should fail loudly rather than silently auto-fix) and to cover .mjs/.cjs files:
"lint-staged": {
"*.{css,json,md,scss}": ["prettier --check"],
"*.{ts,tsx,js,jsx,mjs,cjs}": ["eslint"]
}You can automate all of the above with the setup CLI:
yarn sofie-code-standard-preset-setup --forceIf not already, the project should be updated to yarn v4 instead of yarn v1. yarn v1 was EOL a few years ago, and v4 is working for us quite nicely.
- Make sure that you are ready to do a semver major bump, with a new minimum nodejs version of v20.
- Update your package.json engines to require node 20
- Install the updated
@sofie-automation/code-standard-presetpackage - Install tools that used to be included by the preset package:
yarn add --dev eslint husky lint-staged prettier, any you do not need can be omitted. - Check the package.json scripts;
- Change
husky installtohusky - Change the
lint:rawto simplyeslint - Check if any
yarn Xcan be made simplyXorrun X
- Change
- In
.husky/pre-commit, replace the contents to be simplylint-staged - Ensure the project has an updated typescript
- This may require updating other tools, be sure to check jest/compiling later
- Remove the existing
.eslintrc.jsonand replace with the neweslint.config.mjsexample above. If you have modified your file from the default, you will need to translate that across. - In your code, any references to eslint rules
node/*have been renamed ton/* - Due to the rules requiring conforming to ESM import syntax, you may need to update many file imports. You can use
npx fix-esm-import-path srcas an easy way of updating all the imports in the project - Make sure that everything is working. You will likely have a bunch of linter failures due to updated formatting and linting rules, which will need resolving.
This release introduces a simple replacement for standard-version
Steps:
- Remove the
standard-versionconfig block in your package.json - Remove the devDependency on
standard-version - Update any scripts using
standard-versionto usesofie-version, if there are any parameters, they will likely all need removing. - Update the prerelease workflow to change
yarn release --prerelease $PRERELEASE_TAG-$COMMIT_DATE-$GIT_HASH --skip.changelog --skip.tag --skip.commitintoyarn release --prerelease $PRERELEASE_TAG - Remove the unused
COMMIT_DATE,GIT_HASHandCOMMIT_TIMESTAMPdefinitions above - Change the variable
PRERELEASE_TAG=nightly-$(echo "${{ steps.prerelease-tag.outputs.tag }}" | sed -r 's/[^a-z0-9]+/-/gi')toPRERELEASE_TAG=nightly-${{ steps.prerelease-tag.outputs.tag }} - Make sure there aren't any other usages of
standard-versionor the release script, if there are they will need updating. - Below any
yarn publish ....lines, addecho "**Published:** $NEW_VERSION" >> $GITHUB_STEP_SUMMARYto log the publish in the github action workflow
While you are here, try to update any uses: lines in the actions workflows, common ones that need updating:
actions/checkout@v3actions/setup-node@v3
This updates husky, and the config that goes with it.
Steps:
- Create the
.husky/pre-commitfile - Remove the old husky config from
package.json - Update the scripts and lint-staged config in
package.json
The NRK logo is a registered trademark of Norsk rikskringkasting AS. The license does not grant any right to use, in any way, any trademarks, service marks or logos of Norsk rikskringkasting AS.