From 8c5b0fb58c632e98c17ebc43788f58e7d9d985a1 Mon Sep 17 00:00:00 2001 From: Alex Grover Date: Tue, 25 Jun 2024 10:31:15 -0400 Subject: [PATCH 1/5] Add prettier, husky, lint-staged, CI config --- .eslintrc.json | 2 +- .github/workflows/ci.yml | 23 ++ .gitignore | 3 + .husky/pre-commit | 1 + .prettierignore | 1 + .prettierrc | 1 + package-lock.json | 571 +++++++++++++++++++++++++++++++++++++-- package.json | 15 +- 8 files changed, 593 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.eslintrc.json b/.eslintrc.json index bffb357..4d765f2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,3 @@ { - "extends": "next/core-web-vitals" + "extends": ["next/core-web-vitals", "prettier"] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6323278 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,23 @@ +name: ci + +on: + push: + branches: ["main"] + pull_request: + types: [opened, synchronize] + +jobs: + check: + name: Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "npm" + - run: npm install + env: + HUSKY: 0 + - run: npm run lint + - run: npm run prettier diff --git a/.gitignore b/.gitignore index 00bba9b..18ba6d4 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# ide files +.idea/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a680367 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +.next diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/package-lock.json b/package-lock.json index cf84d35..7de60ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,11 @@ "@types/react-dom": "^18", "eslint": "^8", "eslint-config-next": "14.2.3", + "eslint-config-prettier": "^9.1.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.7", "postcss": "^8", + "prettier": "3.3.2", "tailwindcss": "^3.4.1", "typescript": "^5.4.5" } @@ -4679,11 +4683,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -4990,6 +4994,72 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -5097,6 +5167,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -6003,6 +6079,18 @@ } } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -6383,6 +6471,12 @@ "@ethersproject/wordlists": "5.7.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -6398,7 +6492,6 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "license": "MIT", - "peer": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -6422,7 +6515,6 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6435,7 +6527,6 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "license": "MIT", - "peer": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -6579,9 +6670,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6858,6 +6949,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -6896,7 +6999,6 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "license": "MIT", - "peer": true, "engines": { "node": ">=16" }, @@ -7313,11 +7415,25 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=16.17.0" } }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -7867,7 +7983,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "license": "MIT", - "peer": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -8352,6 +8467,66 @@ "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.3.tgz", "integrity": "sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==" }, + "node_modules/lint-staged": { + "version": "15.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", + "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.4", + "execa": "~8.0.1", + "lilconfig": "~3.1.1", + "listr2": "~8.2.1", + "micromatch": "~4.0.7", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.4.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/listhen": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/listhen/-/listhen-1.7.2.tgz", @@ -8393,6 +8568,102 @@ "node": "^14.18.0 || >=16.10.0" } }, + "node_modules/listr2": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", + "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lit": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", @@ -8508,6 +8779,184 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -8557,8 +9006,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", @@ -8569,11 +9017,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -8914,7 +9362,6 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "license": "MIT", - "peer": true, "dependencies": { "path-key": "^4.0.0" }, @@ -8930,7 +9377,6 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9371,6 +9817,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -9608,6 +10066,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -10251,6 +10724,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -10583,6 +11062,46 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sonic-boom": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz", @@ -10675,6 +11194,15 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -10850,7 +11378,6 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/package.json b/package.json index f78776f..7bece42 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "prettier": "prettier . --check", + "prepare": "husky" }, "dependencies": { "@farcaster/hub-nodejs": "^0.11.11", @@ -38,8 +40,19 @@ "@types/react-dom": "^18", "eslint": "^8", "eslint-config-next": "14.2.3", + "eslint-config-prettier": "^9.1.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.7", "postcss": "^8", + "prettier": "3.3.2", "tailwindcss": "^3.4.1", "typescript": "^5.4.5" + }, + "lint-staged": { + "**/*.{js,jsx,ts,tsx}": [ + "eslint --fix", + "prettier --write --ignore-unknown" + ], + "!**/*.{js,jsx,ts,tsx}": "prettier --write --ignore-unknown" } } From 3370e78619ba6d4d200be635d8900bdbbc433ce2 Mon Sep 17 00:00:00 2001 From: Alex Grover Date: Tue, 25 Jun 2024 10:31:55 -0400 Subject: [PATCH 2/5] Run prettier --- README.md | 1 + components.json | 2 +- src/app/[identifier]/page.tsx | 77 ++- .../frames/actions/view-on-explorer/route.tsx | 4 +- src/app/frames/frames.ts | 6 +- src/app/frames/route.tsx | 2 +- src/app/globals.css | 121 +++-- src/app/layout.tsx | 10 +- src/app/page.tsx | 34 +- src/app/providers.tsx | 17 +- src/components/cast-component.tsx | 57 ++- src/components/collapsible-code.tsx | 70 +-- src/components/home.tsx | 56 ++- src/components/modal-component.tsx | 19 +- src/components/profile-component.tsx | 32 +- src/components/search.tsx | 4 +- src/components/ui/avatar.tsx | 26 +- src/components/ui/button.tsx | 26 +- src/components/ui/card.tsx | 47 +- src/components/ui/collapsible.tsx | 12 +- src/components/ui/input.tsx | 16 +- src/components/ui/select.tsx | 58 +-- src/constants.ts | 467 +++++++++--------- src/hooks/fetchEmbedData.ts | 35 +- src/hooks/useClipboard.ts | 38 +- src/lib/utils.ts | 377 ++++++++------ src/middleware.ts | 38 +- tailwind.config.ts | 16 +- 28 files changed, 937 insertions(+), 731 deletions(-) diff --git a/README.md b/README.md index 94b14f1..e72c600 100644 --- a/README.md +++ b/README.md @@ -12,5 +12,6 @@ This is a simple website to track event propagation across Farcaster. In some ca ## Contributing You can contribute in many ways: + - reporting a bug in [Issues](https://github.com/neynarxyz/explorer/issues) - submitting a [pull request](https://github.com/neynarxyz/explorer/pulls) diff --git a/components.json b/components.json index 8c574b7..7559f63 100644 --- a/components.json +++ b/components.json @@ -14,4 +14,4 @@ "components": "@/components", "utils": "@/lib/utils" } -} \ No newline at end of file +} diff --git a/src/app/[identifier]/page.tsx b/src/app/[identifier]/page.tsx index c2add27..6be296f 100644 --- a/src/app/[identifier]/page.tsx +++ b/src/app/[identifier]/page.tsx @@ -64,7 +64,9 @@ export default function Page({ params }: ResponseProps) { } }); - const missingTypes = expectedTypes.filter((type) => !foundTypes.has(type)); + const missingTypes = expectedTypes.filter( + (type) => !foundTypes.has(type), + ); return missingTypes; } @@ -79,13 +81,16 @@ export default function Page({ params }: ResponseProps) { if (!pfp) missingObjects.push("PFP"); if (!displayName) missingObjects.push("Display Name"); if (!bio) missingObjects.push("Bio"); - if (!username || username === expectedUsername) missingObjects.push("Username"); + if (!username || username === expectedUsername) + missingObjects.push("Username"); return missingObjects; }; const warpcastAuthorMissing = checkWarning(data.apiData.warpcast?.author); - const neynarAuthorMissing = checkWarning(data.apiData.neynar?.author?.author); + const neynarAuthorMissing = checkWarning( + data.apiData.neynar?.author?.author, + ); const warpcastAuthorHubMissing = checkWarning(data.hubData?.[0]?.author); const neynarAuthorHubMissing = checkWarning(data.hubData?.[1]?.author); const warpcastCastMissing = [] as any; @@ -110,7 +115,11 @@ export default function Page({ params }: ResponseProps) { fetchData(); }, [hash, fid]); - const openModal = (title: string, response: any, missingObjects: string[]) => { + const openModal = ( + title: string, + response: any, + missingObjects: string[], + ) => { setModalTitle(title); setModalData({ ...response, missingObjects }); setIsModalOpen(true); @@ -143,7 +152,11 @@ export default function Page({ params }: ResponseProps) { const authorFid = warpcastCast?.author?.fid || neynarCast?.cast?.author?.fid; - const renderHeader = (label: string, data: any | null, missingObjects: string[]) => { + const renderHeader = ( + label: string, + data: any | null, + missingObjects: string[], + ) => { if (!data) { return null; } @@ -159,7 +172,9 @@ export default function Page({ params }: ResponseProps) { return ( ) : null} {authorFid ? ( - ) : null} @@ -205,11 +234,27 @@ export default function Page({ params }: ResponseProps) { ) : ( <> - {renderHeader("Warpcast API", warpcastAuthor, warpcastAuthorMissing)} + {renderHeader( + "Warpcast API", + warpcastAuthor, + warpcastAuthorMissing, + )} {renderHeader("Warpcast API", warpcastCast, warpcastCastMissing)} - {renderHeader("Warpcast Hub (Hoyt)", nemesAuthor, warpcastAuthorHubMissing)} - {renderHeader("Warpcast Hub (Hoyt)", nemesCast, warpcastCastHubMissing)} - {renderHeader("Neynar Hub", neynarHubAuthor, neynarAuthorHubMissing)} + {renderHeader( + "Warpcast Hub (Hoyt)", + nemesAuthor, + warpcastAuthorHubMissing, + )} + {renderHeader( + "Warpcast Hub (Hoyt)", + nemesCast, + warpcastCastHubMissing, + )} + {renderHeader( + "Neynar Hub", + neynarHubAuthor, + neynarAuthorHubMissing, + )} {renderHeader("Neynar Hub", neynarHubCast, neynarCastHubMissing)} {renderHeader("Neynar API", neynarAuthor, neynarAuthorMissing)} {renderHeader("Neynar API", neynarCast, neynarCastMissing)} diff --git a/src/app/frames/actions/view-on-explorer/route.tsx b/src/app/frames/actions/view-on-explorer/route.tsx index 7566ab3..3964458 100644 --- a/src/app/frames/actions/view-on-explorer/route.tsx +++ b/src/app/frames/actions/view-on-explorer/route.tsx @@ -22,6 +22,6 @@ export const POST = frames(async (ctx) => { return Response.json({ message: `View on Neynar Explorer`, link: `${seo.url}/${hash}`, - type: 'message' + type: "message", }); -}); \ No newline at end of file +}); diff --git a/src/app/frames/frames.ts b/src/app/frames/frames.ts index 5e4d65b..ca79034 100644 --- a/src/app/frames/frames.ts +++ b/src/app/frames/frames.ts @@ -1,12 +1,12 @@ import { createFrames } from "frames.js/next"; export type State = { - count: number; + count: number; }; - + export const frames = createFrames({ initialState: { count: 0, }, basePath: "/frames", -}); \ No newline at end of file +}); diff --git a/src/app/frames/route.tsx b/src/app/frames/route.tsx index 7c9d62d..c480a2d 100644 --- a/src/app/frames/route.tsx +++ b/src/app/frames/route.tsx @@ -27,4 +27,4 @@ export const GET = frames(async (ctx) => { , ], }; -}); \ No newline at end of file +}); diff --git a/src/app/globals.css b/src/app/globals.css index 3a81358..1c241db 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,79 +1,79 @@ @tailwind base; - @tailwind components; - @tailwind utilities; +@tailwind components; +@tailwind utilities; - @layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; - --radius: 0.5rem; - } + --radius: 0.5rem; + } - .dark { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - } + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; } +} - @layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; } +} /* globals.css */ /* Customize nprogress */ @@ -91,13 +91,10 @@ height: 2px; } +.farcaster-embed-container { + max-height: 320px; +} - - .farcaster-embed-container { - max-height: 320px; - } - - .farcaster-embed-container img { - max-height: 75px; /* This makes the image's max height equal to the container's max height */ - } - \ No newline at end of file +.farcaster-embed-container img { + max-height: 75px; /* This makes the image's max height equal to the container's max height */ +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 75f2f28..b079e32 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -34,7 +34,11 @@ export default function RootLayout({
- +
@@ -48,7 +52,9 @@ export default function RootLayout({
-
{children}
+
+ {children} +
@@ -231,29 +231,29 @@ export default function Page({ params }: ResponseProps) { ) : ( <> {renderHeader( - "Warpcast API", + 'Warpcast API', warpcastAuthor, - warpcastAuthorMissing, + warpcastAuthorMissing )} - {renderHeader("Warpcast API", warpcastCast, warpcastCastMissing)} + {renderHeader('Warpcast API', warpcastCast, warpcastCastMissing)} {renderHeader( - "Warpcast Hub (Hoyt)", + 'Warpcast Hub (Hoyt)', nemesAuthor, - warpcastAuthorHubMissing, + warpcastAuthorHubMissing )} {renderHeader( - "Warpcast Hub (Hoyt)", + 'Warpcast Hub (Hoyt)', nemesCast, - warpcastCastHubMissing, + warpcastCastHubMissing )} {renderHeader( - "Neynar Hub", + 'Neynar Hub', neynarHubAuthor, - neynarAuthorHubMissing, + neynarAuthorHubMissing )} - {renderHeader("Neynar Hub", neynarHubCast, neynarCastHubMissing)} - {renderHeader("Neynar API", neynarAuthor, neynarAuthorMissing)} - {renderHeader("Neynar API", neynarCast, neynarCastMissing)} + {renderHeader('Neynar Hub', neynarHubCast, neynarCastHubMissing)} + {renderHeader('Neynar API', neynarAuthor, neynarAuthorMissing)} + {renderHeader('Neynar API', neynarCast, neynarCastMissing)} )}
diff --git a/src/app/frames/actions/view-on-explorer/route.tsx b/src/app/frames/actions/view-on-explorer/route.tsx index 3964458..d71001d 100644 --- a/src/app/frames/actions/view-on-explorer/route.tsx +++ b/src/app/frames/actions/view-on-explorer/route.tsx @@ -1,17 +1,17 @@ -import { NextRequest } from "next/server"; -import { frames } from "../../frames"; -import { ActionMetadata } from "frames.js"; -import { seo } from "@/constants"; +import { NextRequest } from 'next/server'; +import { frames } from '../../frames'; +import { ActionMetadata } from 'frames.js'; +import { seo } from '@/constants'; export const GET = async (req: NextRequest) => { const actionMetadata: ActionMetadata = { action: { - type: "post", + type: 'post', }, - icon: "info", - name: "View on Neynar Explorer", + icon: 'info', + name: 'View on Neynar Explorer', aboutUrl: `${seo.url}`, - description: "View the details of a cast on Neynar Explorer", + description: 'View the details of a cast on Neynar Explorer', }; return Response.json(actionMetadata); @@ -22,6 +22,6 @@ export const POST = frames(async (ctx) => { return Response.json({ message: `View on Neynar Explorer`, link: `${seo.url}/${hash}`, - type: "message", + type: 'message', }); }); diff --git a/src/app/frames/frames.ts b/src/app/frames/frames.ts index ca79034..a612763 100644 --- a/src/app/frames/frames.ts +++ b/src/app/frames/frames.ts @@ -1,4 +1,4 @@ -import { createFrames } from "frames.js/next"; +import { createFrames } from 'frames.js/next'; export type State = { count: number; @@ -8,5 +8,5 @@ export const frames = createFrames({ initialState: { count: 0, }, - basePath: "/frames", + basePath: '/frames', }); diff --git a/src/app/frames/route.tsx b/src/app/frames/route.tsx index c480a2d..d499cdd 100644 --- a/src/app/frames/route.tsx +++ b/src/app/frames/route.tsx @@ -1,10 +1,10 @@ /* eslint-disable react/jsx-key */ -import { Button } from "frames.js/next"; -import { frames } from "./frames"; -import { seo } from "@/constants"; +import { Button } from 'frames.js/next'; +import { frames } from './frames'; +import { seo } from '@/constants'; function constructCastActionUrl(params: { url: string }): string { - const baseUrl = "https://warpcast.com/~/add-cast-action"; + const baseUrl = 'https://warpcast.com/~/add-cast-action'; const urlParams = new URLSearchParams({ url: params.url, }); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e418a6a..ad3acbc 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,15 +1,15 @@ /* eslint-disable @next/next/no-img-element */ -"use client"; -import "./globals.css"; -import Link from "next/link"; -import Providers from "./providers"; -import Search from "@/components/search"; -import { usePathname } from "next/navigation"; -import { useEffect } from "react"; -import { seo } from "@/constants"; -import { Card, CardContent } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { DownloadIcon } from "lucide-react"; +'use client'; +import './globals.css'; +import Link from 'next/link'; +import Providers from './providers'; +import Search from '@/components/search'; +import { usePathname } from 'next/navigation'; +import { useEffect } from 'react'; +import { seo } from '@/constants'; +import { Card, CardContent } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { DownloadIcon } from 'lucide-react'; export default function RootLayout({ children, @@ -39,7 +39,7 @@ export default function RootLayout({ href="https://www.neynar.com" target="_blank" > - Neynar logo + Neynar logo @@ -57,7 +57,7 @@ export default function RootLayout({
-
diff --git a/src/components/modal-component.tsx b/src/components/modal-component.tsx index be6c175..bf34f05 100644 --- a/src/components/modal-component.tsx +++ b/src/components/modal-component.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef } from 'react'; interface ModalProps { isOpen: boolean; @@ -26,13 +26,13 @@ const Modal: React.FC = ({ }; if (isOpen) { - document.addEventListener("mousedown", handleOutsideClick); + document.addEventListener('mousedown', handleOutsideClick); } else { - document.removeEventListener("mousedown", handleOutsideClick); + document.removeEventListener('mousedown', handleOutsideClick); } return () => { - document.removeEventListener("mousedown", handleOutsideClick); + document.removeEventListener('mousedown', handleOutsideClick); }; }, [isOpen, toggleModal]); @@ -50,7 +50,7 @@ const Modal: React.FC = ({

{title}

{missingObjects && missingObjects.length > 0 && (
- Missing: {missingObjects.join(", ")} + Missing: {missingObjects.join(', ')}
)}
diff --git a/src/components/profile-component.tsx b/src/components/profile-component.tsx index b302f24..3f40f3c 100644 --- a/src/components/profile-component.tsx +++ b/src/components/profile-component.tsx @@ -1,12 +1,12 @@ -import { AvatarImage, AvatarFallback, Avatar } from "@/components/ui/avatar"; +import { AvatarImage, AvatarFallback, Avatar } from '@/components/ui/avatar'; import { CardHeader, CardContent, CardFooter, Card, -} from "@/components/ui/card"; +} from '@/components/ui/card'; //note: not using this in favor of https://github.com/pugson/react-farcaster-embed, but this is a good example of how to render a cast. -import Link from "next/link"; +import Link from 'next/link'; export function ProfileComponent({ pfp, url }: any) { if (!pfp) return null; diff --git a/src/components/search.tsx b/src/components/search.tsx index f27e9e3..80403b8 100644 --- a/src/components/search.tsx +++ b/src/components/search.tsx @@ -1,16 +1,16 @@ -"use client"; -import { Input } from "@/components/ui/input"; -import { Button } from "@/components/ui/button"; -import { useEffect, useRef, useState } from "react"; -import { useRouter } from "next13-progressbar"; -import { usePathname } from "next/navigation"; -import { SearchIcon } from "lucide-react"; +'use client'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { useEffect, useRef, useState } from 'react'; +import { useRouter } from 'next13-progressbar'; +import { usePathname } from 'next/navigation'; +import { SearchIcon } from 'lucide-react'; export default function Search() { const router = useRouter(); const path = usePathname(); const [identifier, setIdentifier] = useState( - decodeURIComponent(path.slice(1)), + decodeURIComponent(path.slice(1)) ); useEffect(() => { diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx index 09cd14d..1346957 100644 --- a/src/components/ui/avatar.tsx +++ b/src/components/ui/avatar.tsx @@ -1,9 +1,9 @@ -"use client"; +'use client'; -import * as React from "react"; -import * as AvatarPrimitive from "@radix-ui/react-avatar"; +import * as React from 'react'; +import * as AvatarPrimitive from '@radix-ui/react-avatar'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; const Avatar = React.forwardRef< React.ElementRef, @@ -12,8 +12,8 @@ const Avatar = React.forwardRef< @@ -26,7 +26,7 @@ const AvatarImage = React.forwardRef< >(({ className, ...props }, ref) => ( )); @@ -39,8 +39,8 @@ const AvatarFallback = React.forwardRef< diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 57c9fe4..81e2e6e 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,36 +1,36 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', { variants: { variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", + default: 'bg-primary text-primary-foreground hover:bg-primary/90', destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", + 'bg-destructive text-destructive-foreground hover:bg-destructive/90', outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", + 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline', }, size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", + default: 'h-10 px-4 py-2', + sm: 'h-9 rounded-md px-3', + lg: 'h-11 rounded-md px-8', + icon: 'h-10 w-10', }, }, defaultVariants: { - variant: "default", - size: "default", + variant: 'default', + size: 'default', }, - }, + } ); export interface ButtonProps @@ -41,7 +41,7 @@ export interface ButtonProps const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; + const Comp = asChild ? Slot : 'button'; return ( ( {...props} /> ); - }, + } ); -Button.displayName = "Button"; +Button.displayName = 'Button'; export { Button, buttonVariants }; diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx index 9bae0fd..4bc649d 100644 --- a/src/components/ui/card.tsx +++ b/src/components/ui/card.tsx @@ -1,6 +1,6 @@ -import * as React from "react"; +import * as React from 'react'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; const Card = React.forwardRef< HTMLDivElement, @@ -9,21 +9,21 @@ const Card = React.forwardRef<
)); -Card.displayName = "Card"; +Card.displayName = 'Card'; const CardHeader = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( -
+
)); -CardHeader.displayName = "CardHeader"; +CardHeader.displayName = 'CardHeader'; const CardTitle = React.forwardRef< HTMLParagraphElement, @@ -32,13 +32,13 @@ const CardTitle = React.forwardRef<

)); -CardTitle.displayName = "CardTitle"; +CardTitle.displayName = 'CardTitle'; const CardDescription = React.forwardRef< HTMLParagraphElement, @@ -46,19 +46,19 @@ const CardDescription = React.forwardRef< >(({ className, ...props }, ref) => (

)); -CardDescription.displayName = "CardDescription"; +CardDescription.displayName = 'CardDescription'; const CardContent = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( -

+
)); -CardContent.displayName = "CardContent"; +CardContent.displayName = 'CardContent'; const CardFooter = React.forwardRef< HTMLDivElement, @@ -66,11 +66,11 @@ const CardFooter = React.forwardRef< >(({ className, ...props }, ref) => (
)); -CardFooter.displayName = "CardFooter"; +CardFooter.displayName = 'CardFooter'; export { Card, diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible.tsx index cb003d1..86ab87d 100644 --- a/src/components/ui/collapsible.tsx +++ b/src/components/ui/collapsible.tsx @@ -1,6 +1,6 @@ -"use client"; +'use client'; -import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; +import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'; const Collapsible = CollapsiblePrimitive.Root; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 9d631e7..d2008f0 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -1,6 +1,6 @@ -import * as React from "react"; +import * as React from 'react'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; export interface InputProps extends React.InputHTMLAttributes {} @@ -11,15 +11,15 @@ const Input = React.forwardRef( ); - }, + } ); -Input.displayName = "Input"; +Input.displayName = 'Input'; export { Input }; diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx index 9218f68..9f3ef21 100644 --- a/src/components/ui/select.tsx +++ b/src/components/ui/select.tsx @@ -1,10 +1,10 @@ -"use client"; +'use client'; -import * as React from "react"; -import * as SelectPrimitive from "@radix-ui/react-select"; -import { Check, ChevronDown, ChevronUp } from "lucide-react"; +import * as React from 'react'; +import * as SelectPrimitive from '@radix-ui/react-select'; +import { Check, ChevronDown, ChevronUp } from 'lucide-react'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; const Select = SelectPrimitive.Root; @@ -19,8 +19,8 @@ const SelectTrigger = React.forwardRef< span]:line-clamp-1", - className, + 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1', + className )} {...props} > @@ -39,8 +39,8 @@ const SelectScrollUpButton = React.forwardRef< @@ -56,8 +56,8 @@ const SelectScrollDownButton = React.forwardRef< @@ -70,15 +70,15 @@ SelectScrollDownButton.displayName = const SelectContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, children, position = "popper", ...props }, ref) => ( +>(({ className, children, position = 'popper', ...props }, ref) => ( {children} @@ -105,7 +105,7 @@ const SelectLabel = React.forwardRef< >(({ className, ...props }, ref) => ( )); @@ -118,8 +118,8 @@ const SelectItem = React.forwardRef< @@ -140,7 +140,7 @@ const SelectSeparator = React.forwardRef< >(({ className, ...props }, ref) => ( )); diff --git a/src/constants.ts b/src/constants.ts index d9575ff..8f917c2 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,72 +1,72 @@ export const seo = { - title: "Farcaster Explorer", - description: "Explore event propogation on farcaster.", - ogImage: "https://i.imgur.com/RMI9pRh.png", - url: "https://explorer.neynar.com", + title: 'Farcaster Explorer', + description: 'Explore event propogation on farcaster.', + ogImage: 'https://i.imgur.com/RMI9pRh.png', + url: 'https://explorer.neynar.com', }; export const hubs = [ // {"shortname": "nemes", "url": "https://nemes.farcaster.xyz:2281"}, - { shortname: "hoyt", url: "https://hoyt.farcaster.xyz:2281" }, - { shortname: "Neynar hub", url: "https://hub-api.neynar.com" }, + { shortname: 'hoyt', url: 'https://hoyt.farcaster.xyz:2281' }, + { shortname: 'Neynar hub', url: 'https://hub-api.neynar.com' }, // {"shortname": "lamia", "url": "https://lamia.farcaster.xyz:2281"}, ]; export const neynarHub = { - shortname: "Neynar hub", - url: "https://hub-api.neynar.com", + shortname: 'Neynar hub', + url: 'https://hub-api.neynar.com', }; -export const defaultHash = "0x3e7326f8da760ed926c1fe82e1444cd528fe6c78"; +export const defaultHash = '0x3e7326f8da760ed926c1fe82e1444cd528fe6c78'; export const tokenBearer = `${process.env.NEXT_PUBLIC_TOKEN_SECRET}`; export const defaultFID = 242661; export const exampleCast = { - object: "cast", - hash: "0xc5af16a18f1ec1ae101635f12cdad4b4a64d9107", - thread_hash: "0xc5af16a18f1ec1ae101635f12cdad4b4a64d9107", + object: 'cast', + hash: '0xc5af16a18f1ec1ae101635f12cdad4b4a64d9107', + thread_hash: '0xc5af16a18f1ec1ae101635f12cdad4b4a64d9107', parent_hash: null, parent_url: - "chain://eip155:1/erc721:0xfd8427165df67df6d7fd689ae67c8ebf56d9ca61", + 'chain://eip155:1/erc721:0xfd8427165df67df6d7fd689ae67c8ebf56d9ca61', root_parent_url: - "chain://eip155:1/erc721:0xfd8427165df67df6d7fd689ae67c8ebf56d9ca61", + 'chain://eip155:1/erc721:0xfd8427165df67df6d7fd689ae67c8ebf56d9ca61', parent_author: { fid: null, }, author: { - object: "user", + object: 'user', fid: 194, - custody_address: "0xb95dc10483be18f7c69ddf78d4baafecc01c5530", - username: "rish", - display_name: "rish", - pfp_url: "https://i.imgur.com/naZWL9n.gif", + custody_address: '0xb95dc10483be18f7c69ddf78d4baafecc01c5530', + username: 'rish', + display_name: 'rish', + pfp_url: 'https://i.imgur.com/naZWL9n.gif', profile: { bio: { - text: "building /neynar 🪐 | neynar.com | /rish ", + text: 'building /neynar 🪐 | neynar.com | /rish ', }, }, follower_count: 155933, following_count: 698, verifications: [ - "0x5a927ac639636e534b678e81768ca19e2c6280b7", - "0xe9e261852ea62150eee685807df8fe3f211310a0", + '0x5a927ac639636e534b678e81768ca19e2c6280b7', + '0xe9e261852ea62150eee685807df8fe3f211310a0', ], verified_addresses: { eth_addresses: [ - "0x5a927ac639636e534b678e81768ca19e2c6280b7", - "0xe9e261852ea62150eee685807df8fe3f211310a0", + '0x5a927ac639636e534b678e81768ca19e2c6280b7', + '0xe9e261852ea62150eee685807df8fe3f211310a0', ], sol_addresses: [], }, - active_status: "inactive", + active_status: 'inactive', power_badge: true, }, - text: "when @automod likes your cast", - timestamp: "2024-05-26T14:13:03.000Z", + text: 'when @automod likes your cast', + timestamp: '2024-05-26T14:13:03.000Z', embeds: [ { - url: "https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/963666e6-e986-4f80-aada-db3ef9b48800/original", + url: 'https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/963666e6-e986-4f80-aada-db3ef9b48800/original', }, { - url: "https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/720ba645-7be4-4dfb-5990-77354fc4f400/original", + url: 'https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/720ba645-7be4-4dfb-5990-77354fc4f400/original', }, ], reactions: { @@ -75,45 +75,45 @@ export const exampleCast = { likes: [ { fid: 284408, - fname: "spaceman-spiff", + fname: 'spaceman-spiff', }, { fid: 584770, - fname: "sempas2024", + fname: 'sempas2024', }, { fid: 546979, - fname: "anchor06", + fname: 'anchor06', }, { fid: 585945, - fname: "layk", + fname: 'layk', }, { fid: 549906, - fname: "trouble25.eth", + fname: 'trouble25.eth', }, ], recasts: [ { fid: 580720, - fname: "anri", + fname: 'anri', }, { fid: 581042, - fname: "sheeesh", + fname: 'sheeesh', }, { fid: 576074, - fname: "nikalaygogol", + fname: 'nikalaygogol', }, { fid: 566243, - fname: "tagaria", + fname: 'tagaria', }, { fid: 574864, - fname: "fpw", + fname: 'fpw', }, ], }, @@ -122,15 +122,15 @@ export const exampleCast = { }, mentioned_profiles: [ { - object: "user", + object: 'user', fid: 368422, - custody_address: "0x16d25ca06a054fc7752e1ae63ca8b23ce6fa2da4", - username: "automod", - display_name: "automod", - pfp_url: "https://i.imgur.com/K1SLPRA.jpg", + custody_address: '0x16d25ca06a054fc7752e1ae63ca8b23ce6fa2da4', + username: 'automod', + display_name: 'automod', + pfp_url: 'https://i.imgur.com/K1SLPRA.jpg', profile: { bio: { - text: "automod.sh - automate channel norms", + text: 'automod.sh - automate channel norms', mentioned_profiles: [], }, }, @@ -141,82 +141,82 @@ export const exampleCast = { eth_addresses: [], sol_addresses: [], }, - active_status: "inactive", + active_status: 'inactive', power_badge: false, }, ], }; export const FIDPFP = - "https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA"; -export const warpcastURLProfile = "https://warpcast.com/dylsteck.eth"; -export const warpcastURLPFP = "https://i.imgur.com/2UTZYvn.png"; + 'https://res.cloudinary.com/merkle-manufactory/image/fetch/c_fill,f_png,w_256/https://lh3.googleusercontent.com/MyUBL0xHzMeBu7DXQAqv0bM9y6s4i4qjnhcXz5fxZKS3gwWgtamxxmxzCJX7m2cuYeGalyseCA2Y6OBKDMR06TWg2uwknnhdkDA1AA'; +export const warpcastURLProfile = 'https://warpcast.com/dylsteck.eth'; +export const warpcastURLPFP = 'https://i.imgur.com/2UTZYvn.png'; export const warpcastURLCastURL = - "https://warpcast.com/kevinoconnell/0x6afc370b"; + 'https://warpcast.com/kevinoconnell/0x6afc370b'; export const warpcastURLCast = { - object: "cast", - hash: "0x6afc370bab152b23bdedc73d16a5296a0b708762", - thread_hash: "0x6afc370bab152b23bdedc73d16a5296a0b708762", + object: 'cast', + hash: '0x6afc370bab152b23bdedc73d16a5296a0b708762', + thread_hash: '0x6afc370bab152b23bdedc73d16a5296a0b708762', parent_hash: null, - parent_url: "https://warpcast.com/~/channel/kevinoconnell", - root_parent_url: "https://warpcast.com/~/channel/kevinoconnell", + parent_url: 'https://warpcast.com/~/channel/kevinoconnell', + root_parent_url: 'https://warpcast.com/~/channel/kevinoconnell', parent_author: { fid: null, }, author: { - object: "user", + object: 'user', fid: 4564, - custody_address: "0x4622146b77ecefe4ca7552a81949d54eac991512", - username: "kevinoconnell", - display_name: "kevin", - pfp_url: "https://i.imgur.com/hKWxU5e.jpg", + custody_address: '0x4622146b77ecefe4ca7552a81949d54eac991512', + username: 'kevinoconnell', + display_name: 'kevin', + pfp_url: 'https://i.imgur.com/hKWxU5e.jpg', profile: { bio: { - text: "I like building things and exploring new places. MrKevinOConnell.github\n\nDoing work at @neynar", + text: 'I like building things and exploring new places. MrKevinOConnell.github\n\nDoing work at @neynar', }, }, follower_count: 30869, following_count: 2269, verifications: [ - "0xedd3783e8c7c52b80cfbd026a63c207edc9cbee7", - "0x69689f02c4154b049fb42761ef8fa00808f1b7ea", + '0xedd3783e8c7c52b80cfbd026a63c207edc9cbee7', + '0x69689f02c4154b049fb42761ef8fa00808f1b7ea', ], verified_addresses: { eth_addresses: [ - "0xedd3783e8c7c52b80cfbd026a63c207edc9cbee7", - "0x69689f02c4154b049fb42761ef8fa00808f1b7ea", + '0xedd3783e8c7c52b80cfbd026a63c207edc9cbee7', + '0x69689f02c4154b049fb42761ef8fa00808f1b7ea', ], sol_addresses: [], }, - active_status: "inactive", + active_status: 'inactive', power_badge: true, }, - text: "Mint Stinson beach :)", - timestamp: "2024-05-25T20:48:50.000Z", + text: 'Mint Stinson beach :)', + timestamp: '2024-05-25T20:48:50.000Z', embeds: [ { - url: "https://zora.co/collect/base:0x9a73abb628a9177768c387ce56d152c4b696dc7f/2?referrer=0xEdd3783e8c7c52b80cfBD026a63C207Edc9CbeE7", + url: 'https://zora.co/collect/base:0x9a73abb628a9177768c387ce56d152c4b696dc7f/2?referrer=0xEdd3783e8c7c52b80cfBD026a63C207Edc9CbeE7', }, ], frames: [ { - version: "vNext", - title: "Stinson beach", + version: 'vNext', + title: 'Stinson beach', image: - "https://zora.co/api/thumbnail/fc/8453/0x9a73abb628a9177768c387ce56d152c4b696dc7f/2", - image_aspect_ratio: "1:1", + 'https://zora.co/api/thumbnail/fc/8453/0x9a73abb628a9177768c387ce56d152c4b696dc7f/2', + image_aspect_ratio: '1:1', buttons: [ { index: 1, - title: "Mint", - action_type: "mint", - target: "eip155:8453:0x9a73abb628a9177768c387ce56d152c4b696dc7f:2", + title: 'Mint', + action_type: 'mint', + target: 'eip155:8453:0x9a73abb628a9177768c387ce56d152c4b696dc7f:2', }, ], input: {}, state: {}, frames_url: - "https://zora.co/collect/base:0x9a73abb628a9177768c387ce56d152c4b696dc7f/2?referrer=0xEdd3783e8c7c52b80cfBD026a63C207Edc9CbeE7", + 'https://zora.co/collect/base:0x9a73abb628a9177768c387ce56d152c4b696dc7f/2?referrer=0xEdd3783e8c7c52b80cfBD026a63C207Edc9CbeE7', }, ], reactions: { @@ -225,33 +225,33 @@ export const warpcastURLCast = { likes: [ { fid: 581042, - fname: "sheeesh", + fname: 'sheeesh', }, { fid: 558760, - fname: "haliava", + fname: 'haliava', }, { fid: 563661, - fname: "airdr0phunter", + fname: 'airdr0phunter', }, { fid: 579082, - fname: "enerdgiua", + fname: 'enerdgiua', }, { fid: 528664, - fname: "merish", + fname: 'merish', }, ], recasts: [ { fid: 581042, - fname: "sheeesh", + fname: 'sheeesh', }, { fid: 302652, - fname: "thisgal", + fname: 'thisgal', }, ], }, diff --git a/src/hooks/fetchEmbedData.ts b/src/hooks/fetchEmbedData.ts index 812b98d..1c2b16b 100644 --- a/src/hooks/fetchEmbedData.ts +++ b/src/hooks/fetchEmbedData.ts @@ -1,7 +1,7 @@ -"use client"; +'use client'; //NOTE: Not using this hook in the project, but it is a good example of how to render embeds from a cast. -import { useCallback, useEffect, useState } from "react"; -import { getEmbedType } from "@/lib/utils"; +import { useCallback, useEffect, useState } from 'react'; +import { getEmbedType } from '@/lib/utils'; // Assuming onSubmit should be a function provided by the component that will trigger data fetching const useFetchEmbedData = (embeds: any[]) => { @@ -15,7 +15,7 @@ const useFetchEmbedData = (embeds: any[]) => { const embedData = await Promise.all( embeds.map(async (embed) => { return await getEmbedType(embed.url); - }), + }) ); const firstValidEmbedData = embedData.find((embed: any) => embed !== null); setEmbed(firstValidEmbedData); diff --git a/src/hooks/useClipboard.ts b/src/hooks/useClipboard.ts index 0760315..14ec582 100644 --- a/src/hooks/useClipboard.ts +++ b/src/hooks/useClipboard.ts @@ -1,4 +1,4 @@ -import { useState, useRef } from "react"; +import { useState, useRef } from 'react'; export function useClipboard() { const [copied, setCopied] = useState(false); diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 2cc38bd..f8e68e3 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,7 +1,7 @@ -import axios from "axios"; -import { type ClassValue, clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; -import { hubs, tokenBearer } from "@/constants"; +import axios from 'axios'; +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; +import { hubs, tokenBearer } from '@/constants'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); @@ -15,7 +15,7 @@ interface HubType { const fetchHubData = async ( fid: number | null, hash: string | null, - isCast = true, + isCast = true ) => { const promises = hubs.map(async (hub) => { const authorData = await fetchFidFromHub(fid, hub, isCast); @@ -42,7 +42,7 @@ interface ApiResponse { const fetchApiData = async ( fid: number | null, - identifier: string | null, + identifier: string | null ): Promise => { let neynarAuthor: any = null; let neynarCast: any = null; @@ -54,7 +54,7 @@ const fetchApiData = async ( let warpcastCastResponseStart = null; try { - if (identifier && (!isWarpcastURL || identifier.split("/").length >= 5)) { + if (identifier && (!isWarpcastURL || identifier.split('/').length >= 5)) { try { warpcastCastResponseStart = performance.now(); @@ -80,12 +80,12 @@ const fetchApiData = async ( if ( fid || - (isWarpcastURL && identifier && identifier.split("/").length === 4) + (isWarpcastURL && identifier && identifier.split('/').length === 4) ) { const warpcastAuthorApiStart = performance.now(); try { warpcastAuthor = await fetchWarpcastAuthor( - authorFid?.toString() ?? (identifier as any), + authorFid?.toString() ?? (identifier as any) ); } catch (error) { warpcastAuthor = formatError(error); @@ -93,7 +93,7 @@ const fetchApiData = async ( try { neynarAuthor = await fetchAuthorFromNeynarAPI( - authorFid?.toString() ?? (identifier as any), + authorFid?.toString() ?? (identifier as any) ); } catch (error) { neynarAuthor = formatError(error); @@ -105,13 +105,13 @@ const fetchApiData = async ( neynarAuthor, neynarCast, warpcastAuthorApiStart, - warpcastCastResponseStart ?? 0, + warpcastCastResponseStart ?? 0 ); } return formatEmptyResponse(warpcastCast, neynarCast); } catch (error) { - console.error("Error in fetchApiData", error); + console.error('Error in fetchApiData', error); return formatErrorResponse(error, warpcastCast, neynarCast); } }; @@ -119,7 +119,7 @@ const fetchApiData = async ( const fetchWarpcastCast = async ( hash: string | null, isWarpcastURL: boolean, - identifier: string | null, + identifier: string | null ) => { let cast = null; try { @@ -127,29 +127,29 @@ const fetchWarpcastCast = async ( const response = await axios.get( `https://api.warpcast.com/v2/thread-casts?castHash=${hash}`, { - headers: { "Content-Type": "application/json" }, - }, + headers: { 'Content-Type': 'application/json' }, + } ); cast = response.data?.result?.casts.find((cast: any) => - cast.hash.startsWith(hash), + cast.hash.startsWith(hash) ) || (null as any); - } else if (identifier && identifier.split("/").length > 3) { - const username = identifier.split("/")[3]; - const hashPrefix = identifier.split("/")[4]; + } else if (identifier && identifier.split('/').length > 3) { + const username = identifier.split('/')[3]; + const hashPrefix = identifier.split('/')[4]; const response = await axios.get( `https://api.warpcast.com/v2/user-thread-casts?castHashPrefix=${hashPrefix}&username=${username}&limit=15`, { - headers: { "Content-Type": "application/json" }, - }, + headers: { 'Content-Type': 'application/json' }, + } ); cast = response.data?.result?.casts.find((cast: any) => - cast.hash.startsWith(hashPrefix), + cast.hash.startsWith(hashPrefix) ) || null; } if (!cast) { - return { error: "Cast not found" }; + return { error: 'Cast not found' }; } return { ...cast, error: null }; } catch (error) { @@ -166,17 +166,17 @@ const fetchWarpcastAuthor = async (identifier: string | null) => { const response = await axios.get( `https://api.warpcast.com/v2/user?fid=${identifier}`, { - headers: { "Content-Type": "application/json" }, - }, + headers: { 'Content-Type': 'application/json' }, + } ); return response.data?.result?.user || null; - } else if (identifier && identifier.split("/").length >= 3) { - const username = identifier?.split("/")[3]; + } else if (identifier && identifier.split('/').length >= 3) { + const username = identifier?.split('/')[3]; const response = await axios.get( `https://api.warpcast.com/v2/user-by-username?username=${username}`, { - headers: { "Content-Type": "application/json" }, - }, + headers: { 'Content-Type': 'application/json' }, + } ); return response.data?.result?.user || null; } @@ -192,7 +192,7 @@ const formatResponse = ( neynarAuthor: any, neynarCast: any, warpcastAuthorApiStart: number, - warpcastCastResponseStart: number, + warpcastCastResponseStart: number ) => ({ warpcast: { author: { ...warpcastAuthor }, @@ -200,24 +200,24 @@ const formatResponse = ( warpcastCast && Object.keys(warpcastCast).length > 0 ? { ...warpcastCast } : null, - name: "Warpcast API", + name: 'Warpcast API', }, neynar: { author: neynarAuthor, cast: neynarCast && Object.keys(neynarCast).length > 0 ? neynarCast : null, - name: "Neynar API", + name: 'Neynar API', }, }); const formatEmptyResponse = (warpcastCast: any, neynarCast: any) => ({ warpcast: { cast: warpcastCast, - name: "Warpcast API", + name: 'Warpcast API', author: null, }, neynar: { cast: neynarCast, - name: "Neynar API", + name: 'Neynar API', author: null, }, }); @@ -225,7 +225,7 @@ const formatEmptyResponse = (warpcastCast: any, neynarCast: any) => ({ const formatErrorResponse = ( error: any, warpcastCast: any = null, - neynarCast: any = null, + neynarCast: any = null ) => { const errorInfo = { message: error.message, @@ -243,12 +243,12 @@ const formatErrorResponse = ( return { warpcast: { cast: warpcastCast, - name: "Warpcast API", + name: 'Warpcast API', author: null, }, neynar: { cast: neynarCast, - name: "Neynar API", + name: 'Neynar API', author: null, }, error: errorInfo, @@ -272,7 +272,7 @@ const formatError = (error: any) => ({ export async function fetchCastAndFidData( hash: string | null, - fid: number | null, + fid: number | null ) { if (!hash && !fid) return { apiData: null, hubData: null }; const apiData = await fetchApiData(fid, hash); @@ -294,7 +294,7 @@ export async function fetchCastAndFidData( const hubData = await fetchHubData( processedFid, processedHash, - apiData.neynar?.cast || apiData.warpcast?.cast, + apiData.neynar?.cast || apiData.warpcast?.cast ); return { apiData, hubData }; } @@ -303,21 +303,21 @@ export async function fetchCastFromHub( hash: string | null, fid: number | null, hub: HubType, - isCast = true, + isCast = true ) { if (!fid || !hash || !isCast) return null; try { let headers: { - "Content-Type": string; + 'Content-Type': string; api_key?: string; - "x-airstack-hubs"?: string; - } = { "Content-Type": "application/json" }; - if (hub.shortname === "Neynar hub") { + 'x-airstack-hubs'?: string; + } = { 'Content-Type': 'application/json' }; + if (hub.shortname === 'Neynar hub') { headers.api_key = `${process.env.NEXT_PUBLIC_NEYNAR_API_KEY}`; } const response = await axios.get( `${hub.url}/v1/castById?fid=${fid}&hash=${hash}`, - { headers }, + { headers } ); return { data: response.data, error: null }; } catch (e) { @@ -327,17 +327,17 @@ export async function fetchCastFromHub( export async function fetchCastFromNeynarAPI( identifier: string, - isURL: boolean = false, + isURL: boolean = false ) { try { const cast = await axios.get( - `https://api.neynar.com/v2/farcaster/cast?identifier=${identifier}&type=${isURL ? "url" : "hash"}`, + `https://api.neynar.com/v2/farcaster/cast?identifier=${identifier}&type=${isURL ? 'url' : 'hash'}`, { headers: { - "Content-Type": "application-json", + 'Content-Type': 'application-json', api_key: `${process.env.NEXT_PUBLIC_NEYNAR_API_KEY}`, }, - }, + } ); return { cast: cast.data.cast, error: null }; @@ -349,16 +349,16 @@ export async function fetchCastFromNeynarAPI( export async function fetchFidFromHub( fid: number | null, hub: HubType, - isCast = true, + isCast = true ) { if (!fid || isCast) return null; try { let headers: { - "Content-Type": string; + 'Content-Type': string; api_key?: string; - "x-airstack-hubs"?: string; - } = { "Content-Type": "application/json" }; - if (hub.shortname === "Neynar hub") { + 'x-airstack-hubs'?: string; + } = { 'Content-Type': 'application/json' }; + if (hub.shortname === 'Neynar hub') { headers.api_key = `${process.env.NEXT_PUBLIC_NEYNAR_API_KEY}`; } const response = await axios.get(`${hub.url}/v1/userDataByFid?fid=${fid}`, { @@ -367,7 +367,7 @@ export async function fetchFidFromHub( const verificationsResponse = await axios.get( `${hub.url}/v1/verificationsByFid?fid=2?fid=${fid}`, - { headers }, + { headers } ); return { @@ -395,10 +395,10 @@ function isEmbedVideoValid(url: string): boolean { export async function getEmbedType(url: string) { const isImage = await isEmbedImageValid(url); - if (isImage) return { type: "image", url }; + if (isImage) return { type: 'image', url }; const isVideo = isEmbedVideoValid(url); - if (isVideo) return { type: "video", url }; + if (isVideo) return { type: 'video', url }; return null; } @@ -411,24 +411,24 @@ export async function fetchAuthorFromNeynarAPI(identifier: string) { `https://api.neynar.com/v2/farcaster/user/bulk?fids=${identifier}`, { headers: { - "Content-Type": "application-json", + 'Content-Type': 'application-json', api_key: `${process.env.NEXT_PUBLIC_NEYNAR_API_KEY}`, }, - }, + } ); const author = authorData.data.users[0]; return { author, error: null }; } else { - const username = identifier.split("/")[3]; + const username = identifier.split('/')[3]; const authorData = await axios.get( `https://api.neynar.com/v1/farcaster/user-by-username?username=${username}`, { headers: { - "Content-Type": "application-json", + 'Content-Type': 'application-json', api_key: `${process.env.NEXT_PUBLIC_NEYNAR_API_KEY}`, }, - }, + } ); return { author: authorData.data.result.user, error: null }; } @@ -439,5 +439,5 @@ export async function fetchAuthorFromNeynarAPI(identifier: string) { export const isValidWarpcastUrl = (url: string | null) => { if (!url) return false; - return url.includes("https://warpcast.com"); + return url.includes('https://warpcast.com'); }; diff --git a/src/middleware.ts b/src/middleware.ts index c37414f..bd50c1a 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,27 +1,27 @@ -import { NextResponse } from "next/server"; +import { NextResponse } from 'next/server'; -import type { NextRequest } from "next/server"; +import type { NextRequest } from 'next/server'; export function middleware(req: NextRequest) { - const env = process.env.VERCEL_ENV ?? "development"; - if (env === "development") { + const env = process.env.VERCEL_ENV ?? 'development'; + if (env === 'development') { return NextResponse.next(); } //check if url has Authentication header passed in - if (!req.headers.get("Authorization")) { - return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); + if (!req.headers.get('Authorization')) { + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); } //get authorization header - const authHeader = req.headers.get("Authorization"); + const authHeader = req.headers.get('Authorization'); //Add better token flow if (authHeader !== process.env.NEXT_PUBLIC_TOKEN_SECRET) { - return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); } return NextResponse.next(); } export const config = { - matcher: "/api/:path*", + matcher: '/api/:path*', }; diff --git a/tailwind.config.ts b/tailwind.config.ts index 41668a3..8deeaa7 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,80 +1,80 @@ -import type { Config } from "tailwindcss"; +import type { Config } from 'tailwindcss'; const config = { - darkMode: ["class"], + darkMode: ['class'], content: [ - "./pages/**/*.{ts,tsx}", - "./components/**/*.{ts,tsx}", - "./app/**/*.{ts,tsx}", - "./src/**/*.{ts,tsx}", + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', ], - prefix: "", + prefix: '', theme: { container: { center: true, - padding: "2rem", + padding: '2rem', screens: { - "2xl": "1400px", + '2xl': '1400px', }, }, extend: { colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', }, secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', }, destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))', }, muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))', }, accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))', }, popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))', }, card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))', }, }, borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)', }, keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, + 'accordion-down': { + from: { height: '0' }, + to: { height: 'var(--radix-accordion-content-height)' }, }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, + 'accordion-up': { + from: { height: 'var(--radix-accordion-content-height)' }, + to: { height: '0' }, }, }, animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out', }, }, }, - plugins: [require("tailwindcss-animate")], + plugins: [require('tailwindcss-animate')], } satisfies Config; export default config;