From 8bacfd40da12ec2290cf3d0943935fe716a0979e Mon Sep 17 00:00:00 2001 From: "aritro.ghosh" Date: Wed, 6 May 2026 13:04:54 +0530 Subject: [PATCH] chore: add pre-commit githooks and update gitignore --- .githooks/commit-msg | 85 ++++++++++++++++++++++++++++++ .gitignore | 89 +++++++++++++++++++++++++++++++- package-lock.json | 22 +++++++- package.json | 13 ++++- src/components/Elements.res | 4 +- src/components/HyperElements.res | 4 +- 6 files changed, 207 insertions(+), 10 deletions(-) create mode 100755 .githooks/commit-msg diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 0000000..2c5a927 --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,85 @@ +#!/bin/sh + +# ANSI color codes +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo "${YELLOW}*****~~~~~ Commit hook initiated ~~~~~~*****${NC}" + +commit_msg_file=$1 +commit_msg=$(cat "$commit_msg_file") + +# Formatting +echo +echo "${YELLOW}*****~~~~~ Formatting - Check for unformatted files ~~~~~~*****${NC}" + +# Check for unformatted ReScript files +npm run re:format + +echo +echo "${GREEN}*****~~~~~ All files are formatted. ~~~~~~*****${NC}" +echo + +# Trailing Space Check +echo +echo "${YELLOW}*****~~~~~ Evaluating for trailing spaces ~~~~~~*****${NC}" + +find . -type f -name '.DS_Store' -exec rm {} + + +TRAIL_SRC=$(grep -r '[[:blank:]]$' src --exclude='*.bs.js' --exclude='*.resi') + +if [[ ! -z "$TRAIL_SRC" ]]; then + echo "$TRAIL_SRC" + echo + echo "${RED}!Please remove trailing spaces before committing changes${NC}" + echo "${YELLOW}Usage of EditorConfig [https://editorconfig.org/#download] plugin is recommended for development${NC}" + exit 1 +fi + +echo +echo "${GREEN}*****~~~~~ Done Evaluating ~~~~~~*****${NC}" + +# Commit Message Validation +echo +echo "${YELLOW}*****~~~~~ Commit message validation! ~~~~~*****${NC}" +echo + +commit_regex="^(Merge branch|(feat|fix|chore|refactor|docs|test|style|enhancement|ci|revert)(\([a-zA-Z0-9-]+\))?:).+" + +if ! echo "$commit_msg" | grep -Ei "$commit_regex" ; then + echo "${RED}Aborting commit. Your commit message does not follow the conventional format.${NC}" + echo "${YELLOW}The commit message should begin with one of the following keywords followed by a colon and an optional scope in parentheses:${NC}" + echo "${YELLOW}'feat', 'fix', 'chore', 'refactor', 'docs', 'test', 'style', 'enhancement', 'revert', or 'ci'${NC}" + echo "${YELLOW}Example: 'feat(api): add user authentication endpoint' or 'fix(ui): resolve button alignment issue'${NC}" + exit 1 +fi + +# Gitleaks Secret Scan +echo +echo "${YELLOW}*****~~~~~ Scanning for secrets with Gitleaks ~~~~~~*****${NC}" +echo + +if ! command -v gitleaks &> /dev/null; then + echo "${YELLOW}gitleaks not found. Installing via Homebrew...${NC}" + if command -v brew &> /dev/null; then + brew install gitleaks + else + echo "${RED}Homebrew not found. Please install gitleaks manually: https://github.com/gitleaks/gitleaks${NC}" + exit 1 + fi +fi + +if ! gitleaks protect --staged --redact --verbose; then + echo "${RED}Gitleaks detected secrets in staged changes. Aborting commit.${NC}" + echo "${YELLOW}Please remove the secrets before committing.${NC}" + exit 1 +fi + +echo "${GREEN}*****~~~~~ No secrets detected ~~~~~~*****${NC}" + +echo +echo "${GREEN}*****~~~~~ Commit hook completed ~~~~~~*****${NC}" +echo +exit 0 diff --git a/.gitignore b/.gitignore index dc692af..9f82d28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,89 @@ +# Dependencies node_modules -.DS_Store + +# Build outputs lib/bs -yarn.lock \ No newline at end of file +lib/ocaml +.merlin + +# ReScript +.bsb.lock + +# Package manager lockfiles +yarn.lock + +# OS files +.DS_Store +Thumbs.db + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +*.log + +# Environment variables +.env +.env.local +.env.*.local + +# Coverage +coverage/ + +# Temp +tmp/ +temp/ + +# IDE - VSCode +.vscode/ +*.code-workspace + +# IDE - JetBrains (IntelliJ, WebStorm, etc.) +.idea/ +*.iml +*.iws +*.ipr + +# IDE - Vim/Neovim +*.swp +*.swo +*~ +.netrwhist + +# IDE - Emacs +\#*\# +.\#* + +# IDE - Sublime Text +*.sublime-project +*.sublime-workspace + +# AI Agents - Cursor +.cursor/ +.cursorignore +.cursorindexingignore + +# AI Agents - OpenCode +.opencode/ + +# AI Agents - GitHub Copilot +.github/copilot-instructions.md + +# AI Agents - Cline / Roo +.cline/ +.roo/ +.clinerules + +# AI Agents - Windsurf +.windsurfrules + +# AI Agents - Claude / Anthropic +CLAUDE.md +.claude/ + +# AI Agents - Aider +.aider* + +# AI Agents - General +.ai/ +*.aigenerated \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3259fdd..d2f806b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { "name": "@juspay-tech/react-hyper-js", - "version": "2.3.0", + "version": "2.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@juspay-tech/react-hyper-js", - "version": "2.3.0", + "version": "2.3.1", + "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@rescript/core": "^0.7.0", @@ -18,6 +19,7 @@ "@babel/preset-env": "^7.27.2", "@babel/preset-react": "^7.27.1", "babel-loader": "^10.0.0", + "husky": "^9.1.7", "rescript": "^11.1.0", "webpack": "^5.99.9", "webpack-cli": "^6.0.1" @@ -2557,6 +2559,22 @@ "node": ">= 0.4" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", diff --git a/package.json b/package.json index d4747d1..c2496ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@juspay-tech/react-hyper-js", - "version": "2.3.0", + "version": "2.3.1", "main": "dist/bundle.js", "files": [ "dist/", @@ -24,18 +24,27 @@ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "scripts": { + "pre-commit": "bash .githooks/commit-msg", "build": "webpack --mode production", "re:build": "rescript", "re:start": "rescript build -w", "re:format": "rescript format -all", "re:clean": "rescript clean", - "publish:public": "npm publish --access public" + "publish:public": "npm publish --access public", + "setup:hooks": "git config core.hooksPath .githooks && chmod +x .githooks/commit-msg", + "postinstall": "npm run setup:hooks" + }, + "husky": { + "hooks": { + "pre-commit": "npm run pre-commit" + } }, "devDependencies": { "@babel/core": "^7.27.4", "@babel/preset-env": "^7.27.2", "@babel/preset-react": "^7.27.1", "babel-loader": "^10.0.0", + "husky": "^9.1.7", "rescript": "^11.1.0", "webpack": "^5.99.9", "webpack-cli": "^6.0.1" diff --git a/src/components/Elements.res b/src/components/Elements.res index 9dc2ecb..19c4310 100644 --- a/src/components/Elements.res +++ b/src/components/Elements.res @@ -6,7 +6,7 @@ let make = (~children, ~stripe: Promise.t, ~options: JSON React.useEffect0(() => { stripe - ->Js.Promise.then_((switchInstance: OrcaJs.switchInstance) => { + ->(Js.Promise.then_((switchInstance: OrcaJs.switchInstance) => { let orcaElementsConfig = switchInstance.elements(options) let newElemValues: Context.elementsType = { options: elementOptions, @@ -31,7 +31,7 @@ let make = (~children, ~stripe: Promise.t, ~options: JSON setSwitchState(_ => switchValClone) setElementsState(_ => newElemValues) Promise.resolve(switchValClone) - }, _) + }, _)) ->ignore None }) diff --git a/src/components/HyperElements.res b/src/components/HyperElements.res index 198a368..5944761 100644 --- a/src/components/HyperElements.res +++ b/src/components/HyperElements.res @@ -9,7 +9,7 @@ let make = (~children, ~hyper: Promise.t, ~options: JSON. React.useEffect0(() => { hyper - ->Js.Promise.then_((switchInstance: OrcaJs.switchInstance) => { + ->(Js.Promise.then_((switchInstance: OrcaJs.switchInstance) => { let orcaElementsConfig = switchInstance.elements(options) let newElemValues: Context.elementsType = { options: elementOptions, @@ -41,7 +41,7 @@ let make = (~children, ~hyper: Promise.t, ~options: JSON. setElementsState(_ => newElemValues) setPaymentSessionState(_ => newPaymentSessionValues) Promise.resolve(switchValClone) - }, _) + }, _)) ->ignore None })