release: v1.1.0 for tsconfig + prettier

This commit is contained in:
Jyotirmoy Bandyopadhayaya 2023-06-25 13:03:03 +05:30
parent 51631b65b8
commit e3f228ad5f
Signed by: bravo68web
GPG Key ID: F5671FD7BCB9917A
40 changed files with 820 additions and 748 deletions

View File

@ -1,16 +1,16 @@
{ {
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"access": "public", "access": "public",
"baseBranch": "main", "baseBranch": "main",
"changelog": [ "changelog": [
"@changesets/changelog-github", "@changesets/changelog-github",
{ {
"repo": "bravo68web/nodejs-config" "repo": "bravo68web/nodejs-config"
} }
], ],
"commit": false, "commit": false,
"fixed": [["@bravo68web/eslint-config", "@bravo68web/tsconfig", "@bravo68web/prettier-config"]], "fixed": [["@bravo68web/eslint-config", "@bravo68web/tsconfig", "@bravo68web/prettier-config"]],
"ignore": [], "ignore": [],
"linked": [], "linked": [],
"updateInternalDependencies": "patch" "updateInternalDependencies": "patch"
} }

View File

@ -1,4 +1,4 @@
{ {
"extends": ["@bravo68web/eslint-config/code-style"], "extends": ["@bravo68web/eslint-config/code-style"],
"ignorePatterns": ["node_modules", "dist"] "ignorePatterns": ["node_modules", "dist"]
} }

View File

@ -2,31 +2,31 @@ name: Setup Node Environment
description: Prepare and install everything for nodejs repo description: Prepare and install everything for nodejs repo
runs: runs:
using: composite using: composite
steps: steps:
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
cache: pnpm cache: pnpm
node-version: 18 node-version: 18
registry-url: https://registry.npmjs.org/ registry-url: https://registry.npmjs.org/
- name: Install dependencies - name: Install dependencies
shell: bash shell: bash
run: pnpm i run: pnpm i
- name: Restore Turborepo Cache - name: Restore Turborepo Cache
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: | path: |
apps/**/.turbo apps/**/.turbo
node_modules/.cache/turbo node_modules/.cache/turbo
key: turbo-${{ runner.os }}-${{ github.job }}-${{ github.sha }} key: turbo-${{ runner.os }}-${{ github.job }}-${{ github.sha }}
restore-keys: | restore-keys: |
turbo-${{ runner.os }}-${{ github.job }} turbo-${{ runner.os }}-${{ github.job }}
- name: Build packages - name: Build packages
shell: bash shell: bash
run: pnpm build run: pnpm build

View File

@ -1,25 +1,25 @@
name: Linting name: Linting
on: on:
push: push:
branches: [main, dev] branches: [main, dev]
pull_request: pull_request:
branches: [main, dev] branches: [main, dev]
workflow_dispatch: workflow_dispatch:
jobs: jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Environment - name: Setup Environment
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Testing - name: Testing
run: pnpm test run: pnpm test
- name: Run Checking - name: Run Checking
run: pnpm lint run: pnpm lint

View File

@ -1,39 +1,39 @@
name: Publish to NPM name: Publish to NPM
on: on:
push: push:
branches: branches:
- main - main
concurrency: ${{ github.workflow }}-${{ github.ref }} concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
jobs: jobs:
release: release:
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: write contents: write
pull-requests: write pull-requests: write
id-token: write id-token: write
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Environment - name: Setup Environment
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Create Release Pull Request or Publish to NPM - name: Create Release Pull Request or Publish to NPM
id: changesets id: changesets
uses: changesets/action@v1 uses: changesets/action@v1
with: with:
version: pnpm ci:version version: pnpm ci:version
publish: pnpm ci:publish publish: pnpm ci:publish
commit: 'chore(release): publish packages' commit: "chore(release): publish packages"
title: 'chore(release): publish packages' title: "chore(release): publish packages"
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@ -1,27 +1,27 @@
name: Sync Renovate changeset name: Sync Renovate changeset
on: on:
pull_request_target: pull_request_target:
paths: paths:
- '.github/workflows/sync_renovate-changesets.yml' - ".github/workflows/sync_renovate-changesets.yml"
- 'pnpm-lock.yaml' - "pnpm-lock.yaml"
jobs: jobs:
generate-changeset: generate-changeset:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.actor == 'renovate[bot]' && github.repository == 'bravo68web/nodejs-config' if: github.actor == 'renovate[bot]' && github.repository == 'bravo68web/nodejs-config'
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 2 fetch-depth: 2
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
- name: Setup Environment - name: Setup Environment
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Configure Git - name: Configure Git
run: | run: |
git config --global user.email '41448663+BRAVO68WEB@users.noreply.github.com' git config --global user.email '41448663+BRAVO68WEB@users.noreply.github.com'
git config --global user.name 'Github changeset workflow' git config --global user.name 'Github changeset workflow'
- name: Generate changeset - name: Generate changeset
run: pnpm sync-renovate-changesets run: pnpm sync-renovate-changesets

View File

@ -6,9 +6,9 @@ This is a monorepo to share miscellaneous Node.js config for [bravo68web](https:
## Apps ## Apps
- [@bravo68web/eslint-config](apps/eslint-config/) - ESLint config - [@bravo68web/eslint-config](apps/eslint-config/) - ESLint config
- [@bravo68web/tsconfig](apps/tsconfig/) - TypeScript config - [@bravo68web/tsconfig](apps/tsconfig/) - TypeScript config
- [@bravo68web/prettier-config](apps/prettier-config/) - Prettier config - [@bravo68web/prettier-config](apps/prettier-config/) - Prettier config
## Strict Configuration ## Strict Configuration

View File

@ -54,46 +54,46 @@ npm install --save-dev @bravo68web/eslint-config
Add the following code to your `.eslintrc.js` or `.eslintrc.json` file: Add the following code to your `.eslintrc.js` or `.eslintrc.json` file:
- Default: (TypeScript is also supported) - Default: (TypeScript is also supported)
```js ```js
module.exports = { module.exports = {
extends: ['@bravo68web'], extends: ["@bravo68web"],
// extends: ['@bravo68web/eslint-config/default'], // if you want to use named config // extends: ['@bravo68web/eslint-config/default'], // if you want to use named config
}; };
``` ```
- Code Style: (prettier) - Code Style: (prettier)
```js ```js
module.exports = { module.exports = {
extends: ['@bravo68web/eslint-config/code-style'], extends: ["@bravo68web/eslint-config/code-style"],
}; };
``` ```
- Typescript Strict: - Typescript Strict:
```js ```js
module.exports = { module.exports = {
extends: ['@bravo68web/eslint-config/typescript-strict'], extends: ["@bravo68web/eslint-config/typescript-strict"],
parserOptions: { parserOptions: {
ecmaVersion: 'latest', ecmaVersion: "latest",
project: './tsconfig.json', project: "./tsconfig.json",
// tsconfigRootDir: __dirname, // if you use tsconfig.json in a different directory // tsconfigRootDir: __dirname, // if you use tsconfig.json in a different directory
}, },
}; };
``` ```
- Ultimate: (TypeScript strict + Code Style) - Ultimate: (TypeScript strict + Code Style)
```js ```js
module.exports = { module.exports = {
extends: ['@bravo68web/eslint-config/ultimate'], extends: ["@bravo68web/eslint-config/ultimate"],
parserOptions: { parserOptions: {
ecmaVersion: 'latest', ecmaVersion: "latest",
project: './tsconfig.json', project: "./tsconfig.json",
// tsconfigRootDir: __dirname, // if you use tsconfig.json in a different directory // tsconfigRootDir: __dirname, // if you use tsconfig.json in a different directory
}, },
}; };
``` ```
@ -103,9 +103,9 @@ And that's it! You're now ready to use
This package is compatible with the following dependencies and Node.js versions: This package is compatible with the following dependencies and Node.js versions:
- ESLint: 8.x - ESLint: 8.x
- TypeScript: 5.x - TypeScript: 5.x
- Node.js: Any version that supports dependencies above - Node.js: Any version that supports dependencies above
**Updating to the latest version of this package is recommended for the best compatibility.** **Updating to the latest version of this package is recommended for the best compatibility.**

View File

@ -1,88 +1,88 @@
{ {
"name": "@bravo68web/eslint-config", "name": "@bravo68web/eslint-config",
"version": "1.0.3", "version": "1.0.3",
"description": "The official ESLint configuration for bravo68web projects", "description": "The official ESLint configuration for bravo68web projects",
"license": "MIT", "license": "MIT",
"author": "Bravo68web <hi@b68.dev> (https://github.com/bravo68web/)", "author": "Bravo68web <hi@b68.dev> (https://github.com/bravo68web/)",
"homepage": "https://github.com/bravo68web/nodejs-config#readme", "homepage": "https://github.com/bravo68web/nodejs-config#readme",
"repository": "git+https://github.com/bravo68web/nodejs-config", "repository": "git+https://github.com/bravo68web/nodejs-config",
"bugs": { "bugs": {
"url": "https://github.com/bravo68web/nodejs-config/issues" "url": "https://github.com/bravo68web/nodejs-config/issues"
},
"files": [
"dist"
],
"scripts": {
"build": "rollup -c --silent",
"lint": "tsc && eslint --fix . --cache",
"test": "vitest run"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": "5.59.9",
"@typescript-eslint/parser": "5.59.9",
"deepmerge": "4.3.1",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-autofix": "1.1.0",
"eslint-plugin-deprecation": "1.4.1",
"eslint-plugin-jsx-a11y": "6.7.1",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.32.2",
"eslint-plugin-regexp": "1.15.0",
"eslint-plugin-security": "1.7.1",
"eslint-plugin-simple-import-sort": "10.0.0",
"eslint-plugin-sonarjs": "0.19.0",
"eslint-plugin-tailwindcss": "3.12.1",
"eslint-plugin-unicorn": "47.0.0"
},
"peerDependencies": {
"eslint": "8.x",
"typescript": "5.x"
},
"devDependencies": {
"@bravo68web/tsconfig": "*",
"@rollup/plugin-commonjs": "25.0.1",
"@rollup/plugin-node-resolve": "15.1.0",
"@rollup/plugin-typescript": "11.1.1",
"@types/deepmerge": "2.2.0",
"@types/eslint": "8.40.1",
"@types/node": "18.16.17",
"@types/rollup-plugin-auto-external": "2.0.2",
"eslint": "8.42.0",
"rollup": "3.24.1",
"rollup-plugin-auto-external": "2.0.0",
"tsec": "0.2.7",
"typescript": "5.1.3",
"vitest": "0.32.0"
},
"keywords": [
"bravo68web",
"eslint",
"eslint-config"
],
"publishConfig": {
"access": "public"
},
"exports": {
".": {
"import": "./dist/default.mjs",
"require": "./dist/default.cjs"
}, },
"./default": { "files": [
"import": "./dist/default.mjs", "dist"
"require": "./dist/default.cjs" ],
"scripts": {
"build": "rollup -c --silent",
"lint": "tsc && eslint --fix . --cache",
"test": "vitest run"
}, },
"./code-style": { "dependencies": {
"import": "./dist/code-style.mjs", "@typescript-eslint/eslint-plugin": "5.59.9",
"require": "./dist/code-style.cjs" "@typescript-eslint/parser": "5.59.9",
"deepmerge": "4.3.1",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-autofix": "1.1.0",
"eslint-plugin-deprecation": "1.4.1",
"eslint-plugin-jsx-a11y": "6.7.1",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.32.2",
"eslint-plugin-regexp": "1.15.0",
"eslint-plugin-security": "1.7.1",
"eslint-plugin-simple-import-sort": "10.0.0",
"eslint-plugin-sonarjs": "0.19.0",
"eslint-plugin-tailwindcss": "3.12.1",
"eslint-plugin-unicorn": "47.0.0"
}, },
"./typescript-strict": { "peerDependencies": {
"import": "./dist/typescript-strict.mjs", "eslint": "8.x",
"require": "./dist/typescript-strict.cjs" "typescript": "5.x"
}, },
"./ultimate": { "devDependencies": {
"import": "./dist/ultimate.mjs", "@bravo68web/tsconfig": "*",
"require": "./dist/ultimate.cjs" "@rollup/plugin-commonjs": "25.0.1",
"@rollup/plugin-node-resolve": "15.1.0",
"@rollup/plugin-typescript": "11.1.1",
"@types/deepmerge": "2.2.0",
"@types/eslint": "8.40.1",
"@types/node": "18.16.17",
"@types/rollup-plugin-auto-external": "2.0.2",
"eslint": "8.42.0",
"rollup": "3.24.1",
"rollup-plugin-auto-external": "2.0.0",
"tsec": "0.2.7",
"typescript": "5.1.3",
"vitest": "0.32.0"
},
"keywords": [
"bravo68web",
"eslint",
"eslint-config"
],
"publishConfig": {
"access": "public"
},
"exports": {
".": {
"import": "./dist/default.mjs",
"require": "./dist/default.cjs"
},
"./default": {
"import": "./dist/default.mjs",
"require": "./dist/default.cjs"
},
"./code-style": {
"import": "./dist/code-style.mjs",
"require": "./dist/code-style.cjs"
},
"./typescript-strict": {
"import": "./dist/typescript-strict.mjs",
"require": "./dist/typescript-strict.cjs"
},
"./ultimate": {
"import": "./dist/ultimate.mjs",
"require": "./dist/ultimate.cjs"
}
} }
}
} }

View File

@ -1,27 +1,27 @@
import fs from 'node:fs'; import fs from "node:fs";
import path from 'node:path'; import path from "node:path";
import rollupPluginCommonjs from '@rollup/plugin-commonjs'; import rollupPluginCommonjs from "@rollup/plugin-commonjs";
import rollupPluginNodeResolve from '@rollup/plugin-node-resolve'; import rollupPluginNodeResolve from "@rollup/plugin-node-resolve";
import rollupPluginTypescript from '@rollup/plugin-typescript'; import rollupPluginTypescript from "@rollup/plugin-typescript";
import rollupPluginAutoExternal from 'rollup-plugin-auto-external'; import rollupPluginAutoExternal from "rollup-plugin-auto-external";
// Read the files in the src directory // Read the files in the src directory
const dir = './src/'; const dir = "./src/";
// Filter the .ts files // Filter the .ts files
const files = fs.readdirSync(dir).filter(file => file.endsWith('.ts')); const files = fs.readdirSync(dir).filter(file => file.endsWith(".ts"));
const plugins = [ const plugins = [
// Automatically mark all dependencies as external // Automatically mark all dependencies as external
rollupPluginAutoExternal(), rollupPluginAutoExternal(),
// Resolve node modules // Resolve node modules
rollupPluginNodeResolve(), rollupPluginNodeResolve(),
// Convert CommonJS modules to ES6 // Convert CommonJS modules to ES6
rollupPluginCommonjs(), rollupPluginCommonjs(),
// Compile TypeScript files // Compile TypeScript files
rollupPluginTypescript({ rollupPluginTypescript({
tsconfig: 'tsconfig.json', tsconfig: "tsconfig.json",
}), }),
]; ];
/** /**
@ -44,16 +44,16 @@ const plugins = [
* @returns {ParticularFormatConfig} The Rollup configuration for CJS builds. * @returns {ParticularFormatConfig} The Rollup configuration for CJS builds.
*/ */
function getCjsConfig(filename) { function getCjsConfig(filename) {
return { return {
input: `${dir}${filename}`, input: `${dir}${filename}`,
output: { output: {
dir: './dist', dir: "./dist",
exports: 'default', exports: "default",
entryFileNames: `${path.basename(filename, '.ts')}.cjs`, entryFileNames: `${path.basename(filename, ".ts")}.cjs`,
format: 'cjs', format: "cjs",
}, },
plugins, plugins,
}; };
} }
/** /**
@ -63,16 +63,16 @@ function getCjsConfig(filename) {
* @returns {ParticularFormatConfig} The Rollup configuration for CJS builds. * @returns {ParticularFormatConfig} The Rollup configuration for CJS builds.
*/ */
function getEsmConfig(filename) { function getEsmConfig(filename) {
return { return {
input: `${dir}${filename}`, input: `${dir}${filename}`,
output: { output: {
dir: './dist', dir: "./dist",
exports: 'default', exports: "default",
entryFileNames: `${path.basename(filename, '.ts')}.mjs`, entryFileNames: `${path.basename(filename, ".ts")}.mjs`,
format: 'esm', format: "esm",
}, },
plugins, plugins,
}; };
} }
/** /**
@ -81,7 +81,7 @@ function getEsmConfig(filename) {
* @returns {Array<ParticularFormatConfig>} The Rollup configuration for CJS and ESM builds. * @returns {Array<ParticularFormatConfig>} The Rollup configuration for CJS and ESM builds.
*/ */
function getEntryConfigs(filename) { function getEntryConfigs(filename) {
return [getCjsConfig(filename), getEsmConfig(filename)]; return [getCjsConfig(filename), getEsmConfig(filename)];
} }
export default files.flatMap(element => getEntryConfigs(element)); export default files.flatMap(element => getEntryConfigs(element));

View File

@ -1,6 +1,6 @@
import merge from 'deepmerge'; import merge from "deepmerge";
import defaultConfig from './default'; import defaultConfig from "./default";
import strictCodeStyleConfig from './sub-rules/prettier'; import strictCodeStyleConfig from "./sub-rules/prettier";
export default merge(defaultConfig, strictCodeStyleConfig); export default merge(defaultConfig, strictCodeStyleConfig);

View File

@ -1,105 +1,105 @@
import type { Linter } from 'eslint'; import type { Linter } from "eslint";
const config: Linter.Config = { const config: Linter.Config = {
env: { env: {
browser: true, browser: true,
es6: true, es6: true,
node: true, node: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:regexp/recommended',
'plugin:unicorn/recommended',
'plugin:sonarjs/recommended',
'plugin:security/recommended',
'plugin:tailwindcss/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/eslint-recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
}, },
ecmaVersion: 'latest', extends: [
}, "eslint:recommended",
plugins: [ "plugin:react/recommended",
'regexp', "plugin:regexp/recommended",
'jsx-a11y', "plugin:unicorn/recommended",
'autofix', "plugin:sonarjs/recommended",
'react', "plugin:security/recommended",
'sonarjs', "plugin:tailwindcss/recommended",
'unicorn', "plugin:@typescript-eslint/recommended",
'@typescript-eslint', "plugin:@typescript-eslint/eslint-recommended",
'simple-import-sort',
],
rules: {
quotes: [
2,
'single',
{
avoidEscape: true,
},
], ],
// Eslint parser: "@typescript-eslint/parser",
'prefer-arrow-callback': 2, parserOptions: {
semi: [2, 'always'], ecmaFeatures: {
// Import sorting jsx: true,
'simple-import-sort/imports': 2, },
'simple-import-sort/exports': 2, ecmaVersion: "latest",
// React
'react/react-in-jsx-scope': 0,
'react/button-has-type': 2,
'react/prop-types': 0,
'react/no-array-index-key': 2,
// SonarJS
'sonarjs/no-duplicate-string': 0,
// Unicorn
'unicorn/no-null': 0,
'unicorn/prefer-module': 0,
'unicorn/no-useless-undefined': 0,
'unicorn/prevent-abbreviations': 0,
'unicorn/no-await-expression-member': 0,
// Typescript
'@typescript-eslint/no-namespace': 0,
'@typescript-eslint/no-misused-promises': 0,
'@typescript-eslint/no-unused-vars': [2],
'@typescript-eslint/no-unsafe-call': 0,
'@typescript-eslint/no-unsafe-assignment': 0,
'@typescript-eslint/no-unsafe-member-access': 0,
},
settings: {
react: {
version: 'detect',
}, },
}, plugins: [
overrides: [ "regexp",
{ "jsx-a11y",
files: ['*.js', '*.jsx', '*.cjs'], "autofix",
rules: { "react",
'@typescript-eslint/no-var-requires': 0, "sonarjs",
}, "unicorn",
}, "@typescript-eslint",
{ "simple-import-sort",
files: ['*.js', '*.jsx', '*.ts', '*.tsx', '*.cjs', '*.mjs', '*.mts', '*.cts'], ],
rules: { rules: {
'simple-import-sort/imports': [ quotes: [
'error', 2,
{ "single",
groups: [ {
['dotenv/config'], avoidEscape: true,
['^node:', '^react$', '^react-dom$', '^next?/|^next$'], },
['^@?\\w'],
['^[\\w]'],
['^'],
['^\\.'],
],
},
], ],
}, // Eslint
"prefer-arrow-callback": 2,
semi: [2, "always"],
// Import sorting
"simple-import-sort/imports": 2,
"simple-import-sort/exports": 2,
// React
"react/react-in-jsx-scope": 0,
"react/button-has-type": 2,
"react/prop-types": 0,
"react/no-array-index-key": 2,
// SonarJS
"sonarjs/no-duplicate-string": 0,
// Unicorn
"unicorn/no-null": 0,
"unicorn/prefer-module": 0,
"unicorn/no-useless-undefined": 0,
"unicorn/prevent-abbreviations": 0,
"unicorn/no-await-expression-member": 0,
// Typescript
"@typescript-eslint/no-namespace": 0,
"@typescript-eslint/no-misused-promises": 0,
"@typescript-eslint/no-unused-vars": [2],
"@typescript-eslint/no-unsafe-call": 0,
"@typescript-eslint/no-unsafe-assignment": 0,
"@typescript-eslint/no-unsafe-member-access": 0,
}, },
], settings: {
react: {
version: "detect",
},
},
overrides: [
{
files: ["*.js", "*.jsx", "*.cjs"],
rules: {
"@typescript-eslint/no-var-requires": 0,
},
},
{
files: ["*.js", "*.jsx", "*.ts", "*.tsx", "*.cjs", "*.mjs", "*.mts", "*.cts"],
rules: {
"simple-import-sort/imports": [
"error",
{
groups: [
["dotenv/config"],
["^node:", "^react$", "^react-dom$", "^next?/|^next$"],
["^@?\\w"],
["^[\\w]"],
["^"],
["^\\."],
],
},
],
},
},
],
}; };
export default config; export default config;

View File

@ -1,12 +1,12 @@
import { Linter } from 'eslint'; import { Linter } from "eslint";
const strictCodeStyleConfig: Linter.Config = { const strictCodeStyleConfig: Linter.Config = {
// Create a strictCodeStyleConfig object of type Linter.Config. // Create a strictCodeStyleConfig object of type Linter.Config.
extends: ['prettier'], // Add the prettier package to the extends array. extends: ["prettier"], // Add the prettier package to the extends array.
plugins: ['prettier'], // Add the prettier package to the plugins array. plugins: ["prettier"], // Add the prettier package to the plugins array.
rules: { rules: {
'prettier/prettier': 2, // Add a rule to enforce the prettier plugin. "prettier/prettier": 2, // Add a rule to enforce the prettier plugin.
}, },
}; };
export default strictCodeStyleConfig; // Export the strictCodeStyleConfig object as the default export. export default strictCodeStyleConfig; // Export the strictCodeStyleConfig object as the default export.

View File

@ -1,38 +1,38 @@
import { Linter } from 'eslint'; import { Linter } from "eslint";
const strictTypescriptConfig: Linter.Config = { const strictTypescriptConfig: Linter.Config = {
parser: '@typescript-eslint/parser', parser: "@typescript-eslint/parser",
extends: [ extends: [
'plugin:@typescript-eslint/strict', "plugin:@typescript-eslint/strict",
'plugin:@typescript-eslint/recommended', "plugin:@typescript-eslint/recommended",
'plugin:@typescript-eslint/recommended-requiring-type-checking', "plugin:@typescript-eslint/recommended-requiring-type-checking",
], ],
plugins: ['deprecation', '@typescript-eslint'], plugins: ["deprecation", "@typescript-eslint"],
parserOptions: { parserOptions: {
ecmaVersion: 'latest', ecmaVersion: "latest",
sourceType: 'module', sourceType: "module",
}, },
rules: { rules: {
// Enforce using the @deprecated tag in JSDoc comments // Enforce using the @deprecated tag in JSDoc comments
'deprecation/deprecation': 1, "deprecation/deprecation": 1,
// Typescript // Typescript
// Disallow await on a non-promise // Disallow await on a non-promise
'@typescript-eslint/no-misused-promises': 0, "@typescript-eslint/no-misused-promises": 0,
// Enforce consistent use of type imports // Enforce consistent use of type imports
'@typescript-eslint/consistent-type-imports': 2, "@typescript-eslint/consistent-type-imports": 2,
// Enforce consistent type exports // Enforce consistent type exports
'@typescript-eslint/consistent-type-exports': 2, "@typescript-eslint/consistent-type-exports": 2,
// Enforce that type arguments will use if not required // Enforce that type arguments will use if not required
'@typescript-eslint/no-redundant-type-constituents': 2, "@typescript-eslint/no-redundant-type-constituents": 2,
// Disallow calling an any type value // Disallow calling an any type value
'@typescript-eslint/no-unsafe-call': 0, "@typescript-eslint/no-unsafe-call": 0,
// Disallow assigning any to variables and properties // Disallow assigning any to variables and properties
'@typescript-eslint/no-unsafe-assignment': 0, "@typescript-eslint/no-unsafe-assignment": 0,
// Disallow member access on any typed variables // Disallow member access on any typed variables
'@typescript-eslint/no-unsafe-member-access': 0, "@typescript-eslint/no-unsafe-member-access": 0,
// Disallow the use of custom TypeScript modules and namespaces // Disallow the use of custom TypeScript modules and namespaces
'@typescript-eslint/no-namespace': 0, "@typescript-eslint/no-namespace": 0,
}, },
}; };
export default strictTypescriptConfig; export default strictTypescriptConfig;

View File

@ -1,6 +1,6 @@
import merge from 'deepmerge'; import merge from "deepmerge";
import defaultConfig from './default'; import defaultConfig from "./default";
import strictTypescriptConfig from './sub-rules/strict-typescript'; import strictTypescriptConfig from "./sub-rules/strict-typescript";
export default merge(defaultConfig, strictTypescriptConfig); export default merge(defaultConfig, strictTypescriptConfig);

View File

@ -1,8 +1,8 @@
import merge from 'deepmerge'; import merge from "deepmerge";
import defaultConfig from './default'; import defaultConfig from "./default";
import strictCodeStyleConfig from './sub-rules/prettier'; import strictCodeStyleConfig from "./sub-rules/prettier";
import strictTypescriptConfig from './sub-rules/strict-typescript'; import strictTypescriptConfig from "./sub-rules/strict-typescript";
const config = merge(strictCodeStyleConfig, strictTypescriptConfig); const config = merge(strictCodeStyleConfig, strictTypescriptConfig);

View File

@ -1,14 +1,14 @@
import { describe } from 'vitest'; import { describe } from "vitest";
import config from '../src/code-style'; import config from "../src/code-style";
import { checkLintingErrors, checkValidity, createEngine } from './utils'; import { checkLintingErrors, checkValidity, createEngine } from "./utils";
describe('Code Style Configuration', () => { describe("Code Style Configuration", () => {
const engine = createEngine(config); const engine = createEngine(config);
// Check the validity of the engine. // Check the validity of the engine.
checkValidity(engine); checkValidity(engine);
// Check for any linting errors. // Check for any linting errors.
checkLintingErrors(engine); checkLintingErrors(engine);
}); });

View File

@ -1,14 +1,14 @@
import { describe } from 'vitest'; import { describe } from "vitest";
import config from '../src/default'; import config from "../src/default";
import { checkLintingErrors, checkValidity, createEngine } from './utils'; import { checkLintingErrors, checkValidity, createEngine } from "./utils";
describe('Default Configuration', () => { describe("Default Configuration", () => {
const engine = createEngine(config); const engine = createEngine(config);
// Check if the script is valid // Check if the script is valid
checkValidity(engine); checkValidity(engine);
// Check if the script has any linting errors // Check if the script has any linting errors
checkLintingErrors(engine); checkLintingErrors(engine);
}); });

View File

@ -1,6 +1,6 @@
const config = { const config = {
apple: 'red', apple: "red",
banana: 'yellow', banana: "yellow",
}; };
export default config; export default config;

View File

@ -1,19 +1,19 @@
import { describe } from 'vitest'; import { describe } from "vitest";
import config from '../src/typescript-strict'; import config from "../src/typescript-strict";
import { checkLintingErrorsFromFile, checkValidity, createEngine } from './utils'; import { checkLintingErrorsFromFile, checkValidity, createEngine } from "./utils";
describe('Typescript Strict Configuration', () => { describe("Typescript Strict Configuration", () => {
const engine = createEngine({ const engine = createEngine({
...config, ...config,
parserOptions: { parserOptions: {
project: './tsconfig.json', project: "./tsconfig.json",
}, },
}); });
// check that the engine is valid // check that the engine is valid
checkValidity(engine); checkValidity(engine);
// check that there are no linting errors in the file // check that there are no linting errors in the file
checkLintingErrorsFromFile(engine, './tests/examples/example-1.ts'); checkLintingErrorsFromFile(engine, "./tests/examples/example-1.ts");
}); });

View File

@ -1,19 +1,19 @@
import { describe } from 'vitest'; import { describe } from "vitest";
import config from '../src/ultimate'; import config from "../src/ultimate";
import { checkLintingErrorsFromFile, checkValidity, createEngine } from './utils'; import { checkLintingErrorsFromFile, checkValidity, createEngine } from "./utils";
describe('Ultimate Configuration', () => { describe("Ultimate Configuration", () => {
const engine = createEngine({ const engine = createEngine({
...config, ...config,
parserOptions: { parserOptions: {
project: './tsconfig.json', project: "./tsconfig.json",
}, },
}); });
// Check the engine's configuration. // Check the engine's configuration.
checkValidity(engine); checkValidity(engine);
// Check the engine's linting errors. // Check the engine's linting errors.
checkLintingErrorsFromFile(engine, './tests/examples/example-1.ts'); checkLintingErrorsFromFile(engine, "./tests/examples/example-1.ts");
}); });

View File

@ -1,38 +1,38 @@
import { ESLint, Linter } from 'eslint'; import { ESLint, Linter } from "eslint";
import { expect, it } from 'vitest'; import { expect, it } from "vitest";
// Create an ESLint engine, based on a base config. // Create an ESLint engine, based on a base config.
export const createEngine = (baseConfig: Linter.Config) => { export const createEngine = (baseConfig: Linter.Config) => {
return new ESLint({ return new ESLint({
useEslintrc: false, // do not use .eslintrc.* files useEslintrc: false, // do not use .eslintrc.* files
baseConfig, // set the base config baseConfig, // set the base config
}); });
}; };
export const checkValidity = (engine: ESLint) => { export const checkValidity = (engine: ESLint) => {
it('is valid configuration', async () => { it("is valid configuration", async () => {
// Linting an empty string is invalid, so we expect it to throw // Linting an empty string is invalid, so we expect it to throw
await expect(engine.lintText('')).resolves.not.toThrow(); await expect(engine.lintText("")).resolves.not.toThrow();
}); });
}; };
// This test ensures that the linting engine is properly configured. // This test ensures that the linting engine is properly configured.
export const checkLintingErrors = (engine: ESLint) => { export const checkLintingErrors = (engine: ESLint) => {
it('does not produce linting errors', async () => { it("does not produce linting errors", async () => {
// Run linting on an empty string. // Run linting on an empty string.
const lintResults = await engine.lintText(''); const lintResults = await engine.lintText("");
// Expect that the linting engine does not produce any errors. // Expect that the linting engine does not produce any errors.
expect(lintResults[0].errorCount).toBe(0); expect(lintResults[0].errorCount).toBe(0);
}); });
}; };
export const checkLintingErrorsFromFile = (engine: ESLint, file: string) => { export const checkLintingErrorsFromFile = (engine: ESLint, file: string) => {
it('does not produce linting errors', async () => { it("does not produce linting errors", async () => {
// Lint the file using the ESLint engine // Lint the file using the ESLint engine
const lintResults = await engine.lintFiles(file); const lintResults = await engine.lintFiles(file);
// Expect that the file has no errors // Expect that the file has no errors
expect(lintResults[0].errorCount).toBe(0); expect(lintResults[0].errorCount).toBe(0);
}); });
}; };

View File

@ -1,9 +1,9 @@
{ {
"compilerOptions": { "compilerOptions": {
"moduleResolution": "node", "moduleResolution": "node",
"noEmit": true "noEmit": true
}, },
"exclude": ["node_modules", "dist"], "exclude": ["node_modules", "dist"],
"extends": "@bravo68web/tsconfig/base.json", "extends": "@bravo68web/tsconfig/base.json",
"include": ["src", "rollup.config.mjs", "tests/examples/example-1.ts"] "include": ["src", "rollup.config.mjs", "tests/examples/example-1.ts"]
} }

View File

@ -6,19 +6,19 @@ Welcome to the `@bravo68web/prettier-config`! This is the Prettier configuration
## Specificed Config ## Specificed Config
- **Single Quotes** - Use single quotes instead of double quotes. - **Single Quotes** - Use single quotes instead of double quotes.
- **Tab Width** - Use **2** spaces for indentation. - **Tab Width** - Use **2** spaces for indentation.
- **Trailing Comma** - Use trailing commas wherever possible. - **Trailing Comma** - Use trailing commas wherever possible.
- **Print Width** - Use a print width of **100** characters. - **Print Width** - Use a print width of **100** characters.
- **Avoid Parentheses** - Avoid parentheses when possible. - **Avoid Parentheses** - Avoid parentheses when possible.
> `x => x * x` instead of `(x) => x * x` > `x => x * x` instead of `(x) => x * x`
- **Truey Bracket Spacing** - Add spaces inside of curly braces. - **Truey Bracket Spacing** - Add spaces inside of curly braces.
> `{ foo: bar }` instead of `{foo: bar}` > `{ foo: bar }` instead of `{foo: bar}`
- **Disabled bracket same line** - Objects and arrays are formatted with each item on a new line. - **Disabled bracket same line** - Objects and arrays are formatted with each item on a new line.
## Prettier Plugins ## Prettier Plugins
@ -60,7 +60,7 @@ Add the following code to your `.prettierrc` or `.prettierrc.json` file:
```json ```json
{ {
"prettier": "@bravo68web/prettier-config" "prettier": "@bravo68web/prettier-config"
} }
``` ```
@ -70,8 +70,8 @@ And that's it! You're now ready to use
This package is compatible with the following Prettier and Node.js versions: This package is compatible with the following Prettier and Node.js versions:
- Prettier: 2.0 or later (recommended: latest v2, before major version 3) - Prettier: 2.0 or later (recommended: latest v2, before major version 3)
- Node.js: Any version that supports Prettier - Node.js: Any version that supports Prettier
**Updating to the latest version of this package is recommended for the best compatibility.** **Updating to the latest version of this package is recommended for the best compatibility.**

View File

@ -1,18 +1,18 @@
{ {
"$schema": "http://json.schemastore.org/prettierrc", "$schema": "http://json.schemastore.org/prettierrc",
"arrowParens": "avoid", "arrowParens": "avoid",
"bracketSameLine": false, "bracketSameLine": false,
"bracketSpacing": true, "bracketSpacing": true,
"jsonRecursiveSort": true, "jsonRecursiveSort": true,
"plugins": [ "plugins": [
"prettier-plugin-prisma", "prettier-plugin-prisma",
"prettier-plugin-sort-json", "prettier-plugin-sort-json",
"prettier-plugin-tailwindcss", "prettier-plugin-tailwindcss",
"prettier-plugin-package-perfection" "prettier-plugin-package-perfection"
], ],
"printWidth": 100, "printWidth": 100,
"semi": true, "semi": true,
"singleQuote": true, "singleQuote": false,
"tabWidth": 2, "tabWidth": 4,
"trailingComma": "all" "trailingComma": "all"
} }

View File

@ -1,39 +1,39 @@
{ {
"name": "@bravo68web/prettier-config", "name": "@bravo68web/prettier-config",
"version": "1.0.3", "version": "1.1.0",
"description": "The official Prettier configuration for bravo68web projects", "description": "The official Prettier configuration for bravo68web projects",
"author": "Bravo68web <hi@b68.dev> (https://github.com/bravo68web/)", "author": "Bravo68web <hi@b68.dev> (https://github.com/bravo68web/)",
"homepage": "https://github.com/bravo68web/nodejs-config#readme", "homepage": "https://github.com/bravo68web/nodejs-config#readme",
"repository": "git+https://github.com/bravo68web/nodejs-config", "repository": "git+https://github.com/bravo68web/nodejs-config",
"bugs": { "bugs": {
"url": "https://github.com/bravo68web/nodejs-config/issues" "url": "https://github.com/bravo68web/nodejs-config/issues"
}, },
"main": "index.json", "main": "index.json",
"files": [ "files": [
"index.json", "index.json",
"package.json", "package.json",
"README.md", "README.md",
"LICENSE" "LICENSE"
], ],
"scripts": { "scripts": {
"test": "vitest run" "test": "vitest run"
}, },
"dependencies": { "dependencies": {
"prettier-plugin-package-perfection": "1.1.0", "prettier-plugin-package-perfection": "1.1.0",
"prettier-plugin-prisma": "4.13.0", "prettier-plugin-prisma": "4.13.0",
"prettier-plugin-sort-json": "1.0.0", "prettier-plugin-sort-json": "1.0.0",
"prettier-plugin-tailwindcss": "0.3.0", "prettier-plugin-tailwindcss": "0.3.0",
"vitest": "0.32.0" "vitest": "0.32.0"
}, },
"peerDependencies": { "peerDependencies": {
"prettier": "2.x" "prettier": "2.x"
}, },
"keywords": [ "keywords": [
"bravo68web", "bravo68web",
"prettier", "prettier",
"prettier-config" "prettier-config"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }
} }

View File

@ -1,20 +1,19 @@
import prettier from 'prettier'; import prettier from "prettier";
import { describe, expect, it } from 'vitest'; import { describe, expect, it } from "vitest";
import config from '../index.json'; import config from "../index.json";
describe('Prettier Config', () => { describe("Prettier Config", () => {
it('is valid configuration', () => { it("is valid configuration", () => {
// Format the code with Prettier // Format the code with Prettier
const code = prettier.format( const code = prettier.format(
'const foo=1', "const foo=1",
Object.assign(config as prettier.Options, { Object.assign(config as prettier.Options, {
parser: 'typescript', parser: "typescript",
}) as prettier.Options, }) as prettier.Options,
); );
// Ensure it matches the expected formatting // Ensure it matches the expected formatting
expect(code).toBe(`const foo = 1; expect(code).toBe(`const foo = 1;\n`);
`); });
});
}); });

View File

@ -16,19 +16,19 @@ npm install --save-dev @bravo68web/tsconfig
Add the following code to your `tsconfig.json` file: Add the following code to your `tsconfig.json` file:
- Default configuration - Default configuration
```json ```json
{ {
"extends": "@bravo68web/tsconfig/base.json" "extends": "@bravo68web/tsconfig/base.json"
} }
``` ```
- Web Frontend configuration - Web Frontend configuration
```json ```json
{ {
"extends": "@bravo68web/tsconfig/web.json" "extends": "@bravo68web/tsconfig/web.json"
} }
``` ```
@ -38,8 +38,8 @@ And that's it! You're now ready to use
This package is compatible with the following TypeScript and Node.js versions: This package is compatible with the following TypeScript and Node.js versions:
- TypeScript: 5.0 or later - TypeScript: 5.0 or later
- Node.js: Any version that supports the above TypeScript version - Node.js: Any version that supports the above TypeScript version
**Updating to the latest version of this package is recommended for the best compatibility.** **Updating to the latest version of this package is recommended for the best compatibility.**

View File

@ -1,38 +1,38 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": { "compilerOptions": {
"allowJs": true, "allowJs": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"allowUnreachableCode": false, "allowUnreachableCode": false,
"allowUnusedLabels": false, "allowUnusedLabels": false,
"alwaysStrict": true, "alwaysStrict": true,
"checkJs": true, "checkJs": true,
"esModuleInterop": true, "esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"isolatedModules": true, "isolatedModules": true,
"module": "esnext", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"noEmit": true, "noEmit": false,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noImplicitAny": true, "noImplicitAny": true,
"noImplicitOverride": true, "noImplicitOverride": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"noImplicitThis": true, "noImplicitThis": true,
"noUncheckedIndexedAccess": false, "noUncheckedIndexedAccess": false,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
"strictFunctionTypes": true, "strictFunctionTypes": true,
"strictNullChecks": true, "strictNullChecks": true,
"strictPropertyInitialization": true, "strictPropertyInitialization": true,
"target": "esnext" "target": "esnext"
}, },
"display": "Default tsconfig.json", "display": "Default tsconfig.json",
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

View File

@ -0,0 +1,25 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"alwaysStrict": false,
"declaration": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"lib": ["es2018", "es5", "dom"],
"module": "ESNext",
"moduleResolution": "node",
"noEmit": true,
"outDir": "build",
"resolveJsonModule": true,
"strict": true,
"target": "ES2017"
},
"display": "NoBuild tsconfig.json",
"exclude": ["node_modules"],
"extends": "./base.json",
"files": ["types/index.d.ts"],
"ts-node": {
"swc": true
}
}

View File

@ -0,0 +1,9 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"noEmit": true
},
"display": "NoBuild tsconfig.json",
"exclude": ["node_modules"],
"extends": "./base.json"
}

View File

@ -0,0 +1,38 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"allowUnreachableCode": true,
"allowUnusedLabels": true,
"alwaysStrict": false,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"module": "esnext",
"moduleResolution": "node",
"noEmit": false,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": false,
"noImplicitOverride": true,
"noImplicitReturns": false,
"noImplicitThis": false,
"noUncheckedIndexedAccess": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": false,
"strictFunctionTypes": false,
"strictNullChecks": false,
"strictPropertyInitialization": false,
"target": "esnext"
},
"display": "Default tsconfig.json",
"exclude": ["node_modules"]
}

View File

@ -1,30 +1,30 @@
{ {
"name": "@bravo68web/tsconfig", "name": "@bravo68web/tsconfig",
"version": "1.0.3", "version": "1.1.0",
"description": "Typescript config for bravo68web, ensure the consistency of code quality.", "description": "Typescript config for bravo68web, ensure the consistency of code quality.",
"license": "MIT", "license": "MIT",
"author": "Bravo68web <hi@b68.dev> (https://github.com/bravo68web/)", "author": "Bravo68web <hi@b68.dev> (https://github.com/bravo68web/)",
"homepage": "https://github.com/bravo68web/nodejs-config#readme", "homepage": "https://github.com/bravo68web/nodejs-config#readme",
"repository": "git+https://github.com/bravo68web/nodejs-config", "repository": "git+https://github.com/bravo68web/nodejs-config",
"bugs": { "bugs": {
"url": "https://github.com/bravo68web/nodejs-config/issues" "url": "https://github.com/bravo68web/nodejs-config/issues"
}, },
"files": [ "files": [
"base.json", "base.json",
"web.json" "web.json"
], ],
"peerDependencies": { "peerDependencies": {
"typescript": "5.x" "typescript": "5.x"
}, },
"devDependencies": { "devDependencies": {
"typescript": "5.1.3" "typescript": "5.1.3"
}, },
"keywords": [ "keywords": [
"bravo68web", "bravo68web",
"tsconfig", "tsconfig",
"typescript" "typescript"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": { "compilerOptions": {
"jsx": "preserve", "jsx": "preserve",
"lib": ["dom", "dom.iterable", "esnext"] "lib": ["dom", "dom.iterable", "esnext"]
}, },
"display": "Website tsconfig.json", "display": "Website tsconfig.json",
"exclude": ["node_modules"], "exclude": ["node_modules"],
"extends": "./base.json" "extends": "./base.json"
} }

View File

@ -1,35 +1,35 @@
{ {
"private": true, "private": true,
"name": "@bravo68web/node-config", "name": "@bravo68web/node-config",
"version": "0.0.0", "version": "0.0.0",
"description": "Sharable Node.js miscellaneous config for bravo68web", "description": "Sharable Node.js miscellaneous config for bravo68web",
"license": "MIT", "license": "MIT",
"repository": "git+https://github.com/bravo68web/nodejs-config", "repository": "git+https://github.com/bravo68web/nodejs-config",
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "turbo build", "build": "turbo build",
"ci:publish": "changeset publish", "ci:publish": "changeset publish",
"ci:version": "changeset version", "ci:version": "changeset version",
"format": "prettier --write .", "format": "prettier --write .",
"preinstall": "npx only-allow pnpm", "preinstall": "npx only-allow pnpm",
"lint": "turbo lint", "lint": "turbo lint",
"prepare": "is-ci || husky install", "prepare": "is-ci || husky install",
"sync-renovate-changesets": "node --loader @esbuild-kit/esm-loader scripts/sync-renovate-changesets.ts", "sync-renovate-changesets": "node --loader @esbuild-kit/esm-loader scripts/sync-renovate-changesets.ts",
"test": "turbo test" "test": "turbo test"
}, },
"dependencies": { "dependencies": {
"@bravo68web/eslint-config": "*", "@bravo68web/eslint-config": "*",
"@bravo68web/prettier-config": "*", "@bravo68web/prettier-config": "*",
"@bravo68web/tsconfig": "*", "@bravo68web/tsconfig": "*",
"@changesets/changelog-github": "0.4.8", "@changesets/changelog-github": "0.4.8",
"@changesets/cli": "2.26.1", "@changesets/cli": "2.26.1",
"@esbuild-kit/esm-loader": "2.5.5", "@esbuild-kit/esm-loader": "2.5.5",
"@types/node": "18.16.17", "@types/node": "18.16.17",
"husky": "8.0.3", "husky": "8.0.3",
"is-ci": "3.0.1", "is-ci": "3.0.1",
"prettier": "2.8.8", "prettier": "2.8.8",
"turbo": "1.10.3" "turbo": "1.10.3"
}, },
"packageManager": "pnpm@8.6.2", "packageManager": "pnpm@8.6.2",
"prettier": "@bravo68web/prettier-config" "prettier": "@bravo68web/prettier-config"
} }

View File

@ -1,2 +1,2 @@
packages: packages:
- apps/* - apps/*

View File

@ -1,5 +1,5 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"baseBranches": ["dev"], "baseBranches": ["dev"],
"extends": ["config:base"] "extends": ["config:base"]
} }

View File

@ -1,35 +1,35 @@
#!/usr/bin/env node #!/usr/bin/env node
/* eslint-disable security/detect-non-literal-fs-filename */ /* eslint-disable security/detect-non-literal-fs-filename */
import { exec as _exec } from 'node:child_process'; import { exec as _exec } from "node:child_process";
import { promises as fs } from 'node:fs'; import { promises as fs } from "node:fs";
import { promisify } from 'node:util'; import { promisify } from "node:util";
const exec = promisify(_exec); const exec = promisify(_exec);
const branch = await exec('git branch --show-current'); const branch = await exec("git branch --show-current");
if (!branch.stdout.startsWith('renovate/')) { if (!branch.stdout.startsWith("renovate/")) {
console.log('Not a renovate branch, skipping'); console.log("Not a renovate branch, skipping");
process.exit(0); process.exit(0);
} }
const diffOutput = await exec('git diff --name-only HEAD~1'); const diffOutput = await exec("git diff --name-only HEAD~1");
const diffFiles = diffOutput.stdout const diffFiles = diffOutput.stdout
.split('\n') .split("\n")
.filter(file => file !== 'package.json') .filter(file => file !== "package.json")
.filter(file => file.includes('package.json')); .filter(file => file.includes("package.json"));
if (diffFiles.some(f => f.startsWith('.changeset'))) { if (diffFiles.some(f => f.startsWith(".changeset"))) {
console.log('Changeset already exists, skipping'); console.log("Changeset already exists, skipping");
process.exit(0); process.exit(0);
} }
// If changed file does not include package.json in monorepo, skip // If changed file does not include package.json in monorepo, skip
if (!diffFiles.some(file => file.includes('package.json'))) { if (!diffFiles.some(file => file.includes("package.json"))) {
console.log('No package.json changes to published packages, skipping'); console.log("No package.json changes to published packages, skipping");
process.exit(0); process.exit(0);
} }
// Get changed dependencies inside package.json files, return array of package { name, version } // Get changed dependencies inside package.json files, return array of package { name, version }
@ -46,100 +46,101 @@ if (!diffFiles.some(file => file.includes('package.json'))) {
*/ */
// Find all changed package.json files and extract their dependencies // Find all changed package.json files and extract their dependencies
const packageJsonFiles = await Promise.all( const packageJsonFiles = await Promise.all(
diffFiles.map(file => fs.readFile(file, 'utf8').then(data => ({ file, data }))), diffFiles.map(file => fs.readFile(file, "utf8").then(data => ({ file, data }))),
); );
const dependencies: { const dependencies: {
name: string; name: string;
newVersion: string; newVersion: string;
projects: string[]; projects: string[];
}[] = []; }[] = [];
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
const getChangedDependencies = ( const getChangedDependencies = (
projectName: string, projectName: string,
newDepsObj: Record<string, string>, newDepsObj: Record<string, string>,
oldDepsObj: Record<string, string>, oldDepsObj: Record<string, string>,
) => { ) => {
for (const [depName, newVersion] of Object.entries(newDepsObj)) { for (const [depName, newVersion] of Object.entries(newDepsObj)) {
if (typeof newVersion !== 'string') continue; if (typeof newVersion !== "string") continue;
const oldVersion: string = oldDepsObj[String(depName)]; const oldVersion: string = oldDepsObj[String(depName)];
// Check if the dependency version has changed // Check if the dependency version has changed
if (oldVersion === newVersion) continue; if (oldVersion === newVersion) continue;
// Check if the dependency exists in other projects and new version is the same // Check if the dependency exists in other projects and new version is the same
if ( if (
dependencies.some(dep => dep.name === depName) && dependencies.some(dep => dep.name === depName) &&
dependencies.some(dep => dep.newVersion === newVersion) dependencies.some(dep => dep.newVersion === newVersion)
) { ) {
const dep = dependencies.find(dep => dep.name === depName); const dep = dependencies.find(dep => dep.name === depName);
if (!dep) continue; if (!dep) continue;
// Add project to existing dependency // Add project to existing dependency
dep.projects.push(projectName); dep.projects.push(projectName);
// Update the element in the array // Update the element in the array
const index = dependencies.findIndex(dep => dep.name === depName); const index = dependencies.findIndex(dep => dep.name === depName);
dependencies[Number(index)] = dep; dependencies[Number(index)] = dep;
} else { } else {
dependencies.push({ name: depName, newVersion, projects: [projectName] }); dependencies.push({ name: depName, newVersion, projects: [projectName] });
}
} }
}
}; };
for (const { file } of packageJsonFiles) { for (const { file } of packageJsonFiles) {
const { stdout: newDepsJson } = await exec(`git show HEAD:${file}`); const { stdout: newDepsJson } = await exec(`git show HEAD:${file}`);
// Get old dependencies from git history // Get old dependencies from git history
const { stdout: oldDepsJson } = await exec(`git show HEAD~1:${file}`); const { stdout: oldDepsJson } = await exec(`git show HEAD~1:${file}`);
const { const {
name: projectName, name: projectName,
dependencies: oldDeps = {}, dependencies: oldDeps = {},
devDependencies: oldDevDeps = {}, devDependencies: oldDevDeps = {},
} = JSON.parse(oldDepsJson); } = JSON.parse(oldDepsJson);
const { dependencies: newDeps = {}, devDependencies: newDevDeps = {} } = JSON.parse(newDepsJson); const { dependencies: newDeps = {}, devDependencies: newDevDeps = {} } =
JSON.parse(newDepsJson);
getChangedDependencies(projectName, newDeps, oldDeps); getChangedDependencies(projectName, newDeps, oldDeps);
getChangedDependencies(projectName, newDevDeps, oldDevDeps); getChangedDependencies(projectName, newDevDeps, oldDevDeps);
} }
// Create changeset // Create changeset
async function createChangeset(fileName: string, packageBumps: string[][], packages: string[]) { async function createChangeset(fileName: string, packageBumps: string[][], packages: string[]) {
let message = ''; let message = "";
for (const [pkg, bump] of packageBumps) { for (const [pkg, bump] of packageBumps) {
message = message + `Updated dependency \`${pkg}\` to \`${bump}\`.\n`; message = message + `Updated dependency \`${pkg}\` to \`${bump}\`.\n`;
} }
const pkgs = packages.map((pkg: string) => `'${pkg}': patch`).join('\n'); const pkgs = packages.map((pkg: string) => `'${pkg}': patch`).join("\n");
const body = `---\n${pkgs}\n---\n\n${message.trim()}\n`; const body = `---\n${pkgs}\n---\n\n${message.trim()}\n`;
await fs.writeFile(fileName, body); await fs.writeFile(fileName, body);
} }
const addedFiles: string[] = []; const addedFiles: string[] = [];
// Create changeset for each changed dependency // Create changeset for each changed dependency
for (const { name, newVersion, projects } of dependencies) { for (const { name, newVersion, projects } of dependencies) {
const safeName = name.replaceAll(/[^\w-]/g, '_').toLowerCase(); const safeName = name.replaceAll(/[^\w-]/g, "_").toLowerCase();
const fileName = `.changeset/${safeName}-${newVersion}.md`; const fileName = `.changeset/${safeName}-${newVersion}.md`;
if (addedFiles.includes(fileName)) continue; if (addedFiles.includes(fileName)) continue;
addedFiles.push(fileName); addedFiles.push(fileName);
const packageBumps = [[name, newVersion]]; const packageBumps = [[name, newVersion]];
const packages = projects; const packages = projects;
await createChangeset(fileName, packageBumps, packages); await createChangeset(fileName, packageBumps, packages);
} }
// Add changeset files to git // Add changeset files to git
for (const fileName of addedFiles) await exec('git add ' + fileName); for (const fileName of addedFiles) await exec("git add " + fileName);
// Commit changeset // Commit changeset
await exec('git commit -C HEAD --amend --no-edit'); await exec("git commit -C HEAD --amend --no-edit");
// Push changeset // Push changeset
await exec('git push --force'); await exec("git push --force");

View File

@ -1,3 +1,3 @@
{ {
"extends": "@bravo68web/tsconfig/base.json" "extends": "@bravo68web/tsconfig/base.json"
} }

View File

@ -1,15 +1,15 @@
{ {
"$schema": "https://turbo.build/schema.json", "$schema": "https://turbo.build/schema.json",
"pipeline": { "pipeline": {
"build": { "build": {
"cache": true, "cache": true,
"outputs": ["**/dist"] "outputs": ["**/dist"]
}, },
"lint": { "lint": {
"cache": true, "cache": true,
"inputs": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"], "inputs": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"],
"outputs": ["**/.eslintcache"] "outputs": ["**/.eslintcache"]
}, },
"test": {} "test": {}
} }
} }