diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d6c9537..a3bad5f 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -14,5 +14,8 @@ module.exports = { 'warn', { allowConstantExport: true }, ], + 'max-len': ['error', { code: 100 }], + 'no-console': 'error', + 'semi': ['error', 'never'] }, } diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..8b7aa0e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +Story: ... + +1. Why this change is required? + - ... +2. What problem does it solve? + - ... + +## Implementation +1. +2. +3. + +## Checklist +- [x] Fulfilled specs +- [x] Ensured code is readable +- [x] Consistency in architecture +- [x] Added Test diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 87b8219..6909961 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -13,4 +13,5 @@ jobs: with: node-version: '20.x' - run: npm ci + - run: npm run lint - run: npm run test diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..994a6e7 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "arrowParens": "avoid", + "printWidth": 100 +} diff --git a/package-lock.json b/package-lock.json index 1a6ed5e..cf29925 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", "happy-dom": "^14.12.0", + "prettier": "^3.3.1", "typescript": "^5.2.2", "vite": "^5.2.0", "vitest": "^1.6.0", @@ -5045,6 +5046,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", + "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", diff --git a/package.json b/package.json index feb7115..95132b5 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", "happy-dom": "^14.12.0", + "prettier": "^3.3.1", "typescript": "^5.2.2", "vite": "^5.2.0", "vitest": "^1.6.0", diff --git a/src/App.test.tsx b/src/App.test.tsx index 6e4ef93..ad60949 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,15 +1,16 @@ -import { render } from '@testing-library/react'; -import App from './App'; +import { test, expect } from 'vitest' +import { render } from '@testing-library/react' +import App from './App' -it('runs vitest', () => { - expect(1).toBe(1); -}); +test('runs vitest', () => { + expect(1).toBe(1) +}) -it('renders text', () => { - const wrapper = render(); - expect(wrapper).toBeTruthy(); +test('renders text', () => { + const wrapper = render() + expect(wrapper).toBeTruthy() - const { getByText } = wrapper; - expect(getByText('Vite + React')).toBeTruthy(); -}); + const { getByText } = wrapper + expect(getByText('Vite + React')).toBeTruthy() +}) diff --git a/src/lib/pkce.ts b/src/lib/pkce.ts index d2f061f..bbe653d 100644 --- a/src/lib/pkce.ts +++ b/src/lib/pkce.ts @@ -1,44 +1,44 @@ -import { Sha256 } from '@aws-crypto/sha256-js'; +import { Sha256 } from '@aws-crypto/sha256-js' export const toSha256 = async (data: string): Promise => { - if (!data) throw new Error('data is required'); + if (!data) throw new Error('data is required') - const hash = new Sha256(); - hash.update(data); + const hash = new Sha256() + hash.update(data) - const hashed = await hash.digest(); - return hashed; + const hashed = await hash.digest() + return hashed } // refer to base64url-encoding in RFC 7636 // https://datatracker.ietf.org/doc/html/rfc7636#appendix-A export const toBase64Url = (bytes: Uint8Array) => { - if (bytes.length === 0) throw new Error('bytes must not be empty'); - - const charCodes = Array.from(bytes); - let str = btoa(String.fromCharCode.apply(null, charCodes)); - str = str.split('=')[0]; - str = str.replace(/\+/g, '-'); - str = str.replace(/\//g, '_'); - return str; + if (bytes.length === 0) throw new Error('bytes must not be empty') + + const charCodes = Array.from(bytes) + let str = btoa(String.fromCharCode.apply(null, charCodes)) + str = str.split('=')[0] + str = str.replace(/\+/g, '-') + str = str.replace(/\//g, '_') + return str } // refer to random string generation in RFC 7636 // https://datatracker.ietf.org/doc/html/rfc7636#section-4.1 export const createRandomString = (length: number = 34): string => { - if (length === 0) throw new Error('length must be greater than 0'); + if (length === 0) throw new Error('length must be greater than 0') - const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; - let randomString = ''; + const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~' + let randomString = '' for (let i = 0; i < length; i++) { - const randomIndex = Math.floor(Math.random() * charset.length); - randomString += charset[randomIndex]; + const randomIndex = Math.floor(Math.random() * charset.length) + randomString += charset[randomIndex] } - return randomString; + return randomString } export const createPKCECodeChallenge = async (codeVerifier: string): string => { const hashed: Uint8Array = await toSha256(codeVerifier) const codeChallenge = toBase64Url(hashed) - return codeChallenge; + return codeChallenge }