Rate an Open Source Repo!
-- Open Source is about collaboration and sharing knowledge. But some - repos have a better DX (Developer Experience), share your experience - with the community! -
-diff --git a/.env.example b/.env.example
index 5176e2f..a77ccb7 100644
--- a/.env.example
+++ b/.env.example
@@ -1,8 +1,9 @@
NEXT_PUBLIC_BASE_URL=http://localhost:3000
NEXT_PUBLIC_APPWRITE_URL=
NEXT_PUBLIC_APPWRITE_PROJECT_ID=
-APPWRITE_DATABASE_ID=
+NEXT_PUBLIC_APPWRITE_DATABASE_ID=
+NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID=
+NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID=
+NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID=
+
APPWRITE_API_KEY=
-APPWRITE_COLLECTION_APP_ID=
-APPWRITE_COLLECTION_RATINGS_ID=
-APPWRITE_COLLECTION_REPOS_ID=
diff --git a/README.md b/README.md
index 1f99c41..5116308 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ When considering your rating here are a few points you might like to think about
- [x] List popular Repos
- [x] Leaderboard of most active users
- [x] README badges
-- [ ] Search Repos (coming soon)
+- [x] Search Repos
Want to see any other features? [Open an issue](https://github.com/EddieHubCommunity/RepoRater/issues) and let us know.
@@ -30,7 +30,7 @@ Want to see any other features? [Open an issue](https://github.com/EddieHubCommu
- [NextJS](https://nextjs.org)
- [Appwrite](https://appwrite.io)
-- [DaisyUI](https://daisyui.com) ([Tailwind](https://tailwindcss.com))
+- [Tailwind](https://tailwindcss.com)
## Quickstart for development
@@ -51,12 +51,22 @@ Want to see any other features? [Open an issue](https://github.com/EddieHubCommu
- `name`: string (128, required)
- `votes`: integer
- `rating`: float
- - `owner`: string (128)
- - `logo`: string (512)
+ <<<<<<< HEAD
+ - `owner`: string
+ - `logo`: string
6. Copy `.env.example` template file to `.env`
-7. Get you private keys from Appwrite (Overview > Integrations > "API Keys" tab > "+ Create API key" button) and add them to `.env` template (all data are required)
+7. Get you private keys from Appwrite and add them to `.env` template (all data are required)
8. Create an OAuth app on GitHub and connect it with Appwrite Authentication
-9. Run the development server with:
+9. On collections `ratings` and `repos` enable read permissions for `all` users
+10. Create index on collection `repos`, named `url_search` with the attribute `url` and type `fulltext`
+11. # Run the development server with:
+ - `owner`: string (128)
+ - `logo`: string (512)
+12. Copy `.env.example` template file to `.env`
+13. Get you private keys from Appwrite (Overview > Integrations > "API Keys" tab > "+ Create API key" button) and add them to `.env` template (all data are required)
+14. Create an OAuth app on GitHub and connect it with Appwrite Authentication
+15. Run the development server with:
+ > > > > > > > prototype
```bash
npm ci
@@ -136,7 +146,7 @@ jobs:
More details https://github.com/xkrishguptaa/action-repo-rater
-## API (3rd party apps)
+## API (for your 3rd party apps)
You can consume our data for your own apps.
@@ -172,6 +182,16 @@ Optional paramater `?minimumVotes=5` (default is `5`)
```json
[
+ {
+ "url": "https://github.com/appwrite/appwrite",
+ "logo": "https://avatars.githubusercontent.com/u/25003669?v=4",
+ "description": "Build like a team of hundreds_",
+ "rating": 4.9,
+ "votes": 310,
+ "owner": "appwrite",
+ "name": "appwrite",
+ "badgeViews": 321
+ },
{
"url": "https://github.com/EddieHubCommunity/BioDrop",
"logo": "https://avatars.githubusercontent.com/u/66388388?v=4",
@@ -180,21 +200,56 @@ Optional paramater `?minimumVotes=5` (default is `5`)
"votes": 49,
"owner": "EddieHubCommunity",
"name": "BioDrop",
- "badgeViews": 143
+ "badgeViews": 109
+ }
+]
+```
+
+### All Repos with Search
+
+GET https://repo-rater.eddiehub.org/api/repos
+
+Optional paramater `?keyword=EddieHub`
+
+```json
+[
+ {
+ "url": "https://github.com/EddieHubCommunity/BioDrop",
+ "logo": "https://avatars.githubusercontent.com/u/66388388?v=4",
+ "description": "Connect to your audience with a single link. Showcase the content you create and your projects in one place. Make it easier for people to find, follow and subscribe.",
+ "rating": 4.75,
+ "votes": 49,
+ "owner": "EddieHubCommunity",
+ "name": "BioDrop",
+ "badgeViews": 321
},
{
- "url": "https://github.com/appwrite/appwrite",
- "logo": "https://avatars.githubusercontent.com/u/25003669?v=4",
- "description": "Build like a team of hundreds_",
- "rating": 4.3333333333333,
- "votes": 310,
- "owner": "appwrite",
- "name": "appwrite",
- "badgeViews": 768
+ "url": "https://github.com/EddieHubCommunity/RepoRater",
+ "logo": "https://avatars.githubusercontent.com/u/66388388?v=4",
+ "description": "Connect to your audience with a single link. Showcase the content you create and your projects in one place. Make it easier for people to find, follow and subscribe.",
+ "rating": 4.6,
+ "votes": 12,
+ "owner": "EddieHubCommunity",
+ "name": "RepoRater",
+ "badgeViews": 98
}
]
```
+### App stats
+
+GET https://repo-rater.eddiehub.org/api/stats
+
+```json
+{
+ "ratings": 1137,
+ "repos": 657,
+ "stars": 53,
+ "$createdAt": "2023-12-24T07:41:21.204+00:00",
+ "$updatedAt": "2024-01-02T20:42:33.660+00:00"
+}
+```
+
## Community
Come and chat with the community in the EddieHub Discord http://discord.eddiehub.org
diff --git a/package-lock.json b/package-lock.json
index d475e04..2210132 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,10 +8,13 @@
"name": "repo-rater4",
"version": "0.1.0",
"dependencies": {
+ "@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.1.1",
+ "@tailwindcss/forms": "^0.5.7",
"@vercel/analytics": "^1.1.1",
"appwrite": "^13.0.1",
"badge-maker": "^3.3.1",
+ "javascript-time-ago": "^2.5.9",
"next": "14.0.4",
"node-appwrite": "^11.1.0",
"react": "^18",
@@ -21,7 +24,7 @@
"@types/node": "20.10.4",
"@types/react": "18.2.45",
"autoprefixer": "^10.0.1",
- "daisyui": "^4.4.20",
+ "daisyui": "^4.4.24",
"eslint": "^8",
"eslint-config-next": "14.0.4",
"postcss": "^8",
@@ -41,7 +44,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -117,6 +119,21 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@headlessui/react": {
+ "version": "1.7.17",
+ "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.17.tgz",
+ "integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==",
+ "dependencies": {
+ "client-only": "^0.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16 || ^17 || ^18",
+ "react-dom": "^16 || ^17 || ^18"
+ }
+ },
"node_modules/@heroicons/react": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.1.tgz",
@@ -162,7 +179,6 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
- "dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -176,7 +192,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
- "dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -185,7 +200,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
- "dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -193,14 +207,12 @@
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.20",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
- "dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
@@ -359,7 +371,6 @@
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
@@ -372,7 +383,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
"engines": {
"node": ">= 8"
}
@@ -381,7 +391,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
@@ -404,6 +413,17 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@tailwindcss/forms": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz",
+ "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==",
+ "dependencies": {
+ "mini-svg-data-uri": "^1.2.3"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
+ }
+ },
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -630,14 +650,12 @@
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -658,8 +676,7 @@
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
},
"node_modules/argparse": {
"version": "2.0.1",
@@ -935,14 +952,12 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -956,7 +971,6 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -966,7 +980,6 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -1044,7 +1057,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -1096,7 +1108,6 @@
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "dev": true,
"funding": [
{
"type": "individual",
@@ -1123,7 +1134,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -1168,7 +1178,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -1176,8 +1185,7 @@
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/cross-fetch": {
"version": "3.1.5",
@@ -1235,7 +1243,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
"bin": {
"cssesc": "bin/cssesc"
},
@@ -1259,9 +1266,9 @@
}
},
"node_modules/daisyui": {
- "version": "4.4.20",
- "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.4.20.tgz",
- "integrity": "sha512-AR2fuFVVLHVTdbkV+XWAqjtymEoxXksrsEMkdzPQo2wANtWjSXuODUzePNade64gJ0Y2CdQtiQkaZI7fWcp13g==",
+ "version": "4.4.24",
+ "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.4.24.tgz",
+ "integrity": "sha512-u/B3484J08V7N0rIYymnC+SyxOjlYQL+2vyhHWV+/KC+VaUcbEF2Z3H06eCPgdTiZ0J+ml44aH7wBhIymPFQ+g==",
"dev": true,
"dependencies": {
"css-selector-tokenizer": "^0.8",
@@ -1357,8 +1364,7 @@
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
},
"node_modules/dir-glob": {
"version": "3.0.1",
@@ -1375,8 +1381,7 @@
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
},
"node_modules/doctrine": {
"version": "3.0.0",
@@ -1971,7 +1976,6 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -1987,7 +1991,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -2017,7 +2020,6 @@
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
"dependencies": {
"reusify": "^1.0.4"
}
@@ -2038,7 +2040,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -2139,14 +2140,12 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -2160,7 +2159,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -2259,7 +2257,6 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -2418,7 +2415,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
- "dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
@@ -2464,7 +2460,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -2473,8 +2468,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/internal-slot": {
"version": "1.0.6",
@@ -2535,7 +2529,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -2575,7 +2568,6 @@
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
- "dev": true,
"dependencies": {
"hasown": "^2.0.0"
},
@@ -2602,7 +2594,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2638,7 +2629,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -2671,7 +2661,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -2849,11 +2838,18 @@
"set-function-name": "^2.0.1"
}
},
+ "node_modules/javascript-time-ago": {
+ "version": "2.5.9",
+ "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.5.9.tgz",
+ "integrity": "sha512-pQ8mNco/9g9TqWXWWjP0EWl6i/lAQScOyEeXy5AB+f7MfLSdgyV9BJhiOD1zrIac/lrxPYOWNbyl/IW8CW5n0A==",
+ "dependencies": {
+ "relative-time-format": "^1.1.6"
+ }
+ },
"node_modules/jiti": {
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
"integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
- "dev": true,
"bin": {
"jiti": "bin/jiti.js"
}
@@ -2964,7 +2960,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true,
"engines": {
"node": ">=10"
}
@@ -2972,8 +2967,7 @@
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/locate-path": {
"version": "6.0.0",
@@ -3023,7 +3017,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
"engines": {
"node": ">= 8"
}
@@ -3032,7 +3025,6 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
"dependencies": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
@@ -3060,11 +3052,18 @@
"node": ">= 0.6"
}
},
+ "node_modules/mini-svg-data-uri": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
+ "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
+ "bin": {
+ "mini-svg-data-uri": "cli.js"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -3091,7 +3090,6 @@
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
@@ -3245,7 +3243,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3263,7 +3260,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3272,7 +3268,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -3390,7 +3385,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
"dependencies": {
"wrappy": "1"
}
@@ -3467,7 +3461,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3484,8 +3477,7 @@
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-type": {
"version": "4.0.0",
@@ -3505,7 +3497,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
"engines": {
"node": ">=8.6"
},
@@ -3517,7 +3508,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3526,7 +3516,6 @@
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -3535,7 +3524,6 @@
"version": "8.4.32",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz",
"integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -3563,7 +3551,6 @@
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
@@ -3580,7 +3567,6 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
- "dev": true,
"dependencies": {
"camelcase-css": "^2.0.1"
},
@@ -3599,7 +3585,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -3634,7 +3619,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
"integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==",
- "dev": true,
"engines": {
"node": ">=14"
}
@@ -3643,7 +3627,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
"integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
- "dev": true,
"dependencies": {
"postcss-selector-parser": "^6.0.11"
},
@@ -3662,7 +3645,6 @@
"version": "6.0.13",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
"integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
- "dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -3674,8 +3656,7 @@
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/prelude-ls": {
"version": "1.2.1",
@@ -3715,7 +3696,6 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -3764,7 +3744,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
"dependencies": {
"pify": "^2.3.0"
}
@@ -3773,7 +3752,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -3824,11 +3802,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/relative-time-format": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-1.1.6.tgz",
+ "integrity": "sha512-aCv3juQw4hT1/P/OrVltKWLlp15eW1GRcwP1XdxHrPdZE9MtgqFpegjnTjLhi2m2WI9MT/hQQtE+tjEWG1hgkQ=="
+ },
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
- "dev": true,
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
@@ -3863,7 +3845,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
@@ -3888,7 +3869,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -4180,7 +4160,6 @@
"version": "3.34.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
"integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==",
- "dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.2",
"commander": "^4.0.0",
@@ -4202,7 +4181,6 @@
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -4234,7 +4212,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -4246,7 +4223,6 @@
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.6.tgz",
"integrity": "sha512-AKjF7qbbLvLaPieoKeTjG1+FyNZT6KaJMJPFeQyLfIp7l82ggH1fbHJSsYIvnbTFQOlkh+gBYpyby5GT1LIdLw==",
- "dev": true,
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@@ -4298,7 +4274,6 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
"dependencies": {
"any-promise": "^1.0.0"
}
@@ -4307,7 +4282,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
@@ -4319,7 +4293,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -4347,8 +4320,7 @@
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
},
"node_modules/tsconfig-paths": {
"version": "3.15.0",
@@ -4533,8 +4505,7 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/watchpack": {
"version": "2.4.0",
@@ -4656,8 +4627,7 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/yallist": {
"version": "4.0.0",
@@ -4669,7 +4639,6 @@
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
"integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
- "dev": true,
"engines": {
"node": ">= 14"
}
diff --git a/package.json b/package.json
index b7726f2..d799f12 100644
--- a/package.json
+++ b/package.json
@@ -9,10 +9,13 @@
"lint": "next lint"
},
"dependencies": {
+ "@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.1.1",
+ "@tailwindcss/forms": "^0.5.7",
"@vercel/analytics": "^1.1.1",
"appwrite": "^13.0.1",
"badge-maker": "^3.3.1",
+ "javascript-time-ago": "^2.5.9",
"next": "14.0.4",
"node-appwrite": "^11.1.0",
"react": "^18",
@@ -22,7 +25,7 @@
"@types/node": "20.10.4",
"@types/react": "18.2.45",
"autoprefixer": "^10.0.1",
- "daisyui": "^4.4.20",
+ "daisyui": "^4.4.24",
"eslint": "^8",
"eslint-config-next": "14.0.4",
"postcss": "^8",
diff --git a/src/app/api/activity/route.js b/src/app/api/activity/route.js
new file mode 100644
index 0000000..af1ab16
--- /dev/null
+++ b/src/app/api/activity/route.js
@@ -0,0 +1,28 @@
+import { Query, Databases } from "node-appwrite";
+import TimeAgo from "javascript-time-ago";
+
+import { clientAdmin } from "@/config/appwrite-server";
+
+import en from "javascript-time-ago/locale/en";
+
+TimeAgo.addDefaultLocale(en);
+const timeAgo = new TimeAgo("en-US");
+
+export const dynamic = "force-dynamic";
+
+export async function GET() {
+ let ratings = await new Databases(clientAdmin()).listDocuments(
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID,
+ [Query.orderDesc("$updatedAt"), Query.limit(25)]
+ );
+
+ ratings = ratings.documents.map((rating) => ({
+ username: rating.username,
+ url: rating.url,
+ timeAgo: timeAgo.format(Math.floor(new Date(rating.$updatedAt).getTime())),
+ updatedAt: rating.$updatedAt,
+ }));
+
+ return Response.json(ratings);
+}
diff --git a/src/app/api/badge/route.js b/src/app/api/badge/route.js
index 8083a6b..9d2ad7e 100644
--- a/src/app/api/badge/route.js
+++ b/src/app/api/badge/route.js
@@ -3,6 +3,8 @@ import sdk, { Query } from "node-appwrite";
import { clientAdmin } from "@/config/appwrite-server";
+export const dynamic = "force-dynamic";
+
export async function GET(request) {
const styles = ["plastic", "flat", "flat-square", "for-the-badge", "social"];
const params = request.nextUrl.searchParams;
@@ -13,8 +15,8 @@ export async function GET(request) {
// get repo rating from database
const repos = await new sdk.Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_REPOS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
[Query.equal("owner", [owner]), Query.equal("name", [name]), Query.limit(1)]
);
const data = repos.documents[0];
@@ -22,8 +24,8 @@ export async function GET(request) {
// increment views using badge
if (data) {
await new sdk.Databases(clientAdmin()).updateDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_REPOS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
data.$id,
{
badgeViews: data.badgeViews + 1,
diff --git a/src/app/api/leaderboard/route.js b/src/app/api/leaderboard/route.js
index a93a189..edb7308 100644
--- a/src/app/api/leaderboard/route.js
+++ b/src/app/api/leaderboard/route.js
@@ -2,10 +2,12 @@ import { Query, Databases } from "node-appwrite";
import { clientAdmin } from "@/config/appwrite-server";
+export const dynamic = "force-dynamic";
+
export async function GET() {
const ratings = await new Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_RATINGS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID,
[Query.limit(1000)]
);
const users = ratings.documents.reduce((acc, rating) => {
diff --git a/src/app/api/popular/route.js b/src/app/api/popular/route.js
index ea67832..55665eb 100644
--- a/src/app/api/popular/route.js
+++ b/src/app/api/popular/route.js
@@ -2,13 +2,15 @@ import { Query, Databases } from "node-appwrite";
import { clientAdmin } from "@/config/appwrite-server";
+export const dynamic = "force-dynamic";
+
export async function GET(request) {
const params = request.nextUrl.searchParams;
const minimumVotes = params.get("minimumVotes");
const repos = await new Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_REPOS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
[
Query.select([
"url",
diff --git a/src/app/api/rate/route.js b/src/app/api/rate/route.js
index 3bd0b4e..ccc2a09 100644
--- a/src/app/api/rate/route.js
+++ b/src/app/api/rate/route.js
@@ -27,8 +27,9 @@ export async function POST(request) {
console.info(`User ${username} submitted rating for ${data.url}`);
// 0. get repo from github api
- const repoPath = data.url.split("github.com/");
- if (repoPath.length !== 2 || !repoPath[1]) {
+ const urlClean = data.url.endsWith("/") ? data.url.slice(0, -1) : data.url;
+ const repoPath = urlClean.split("github.com/");
+ if (repoPath.length !== 2) {
return Response.json({ success: false, error: "Invalid URL" });
}
const repoData = await getRepo(repoPath[1], session.providerAccessToken);
@@ -43,42 +44,42 @@ export async function POST(request) {
// get app total stats to increment
const appTotal = (
await new sdk.Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_APP_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID,
[Query.limit(1)]
)
).documents[0];
// 1. check if user already rated this repo
const userRepoRating = await new sdk.Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_RATINGS_ID,
- [Query.equal("url", [data.url]), Query.equal("username", [username])]
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID,
+ [Query.equal("url", [urlClean]), Query.equal("username", [username])]
);
// 2a. update in ratings collection
if (userRepoRating.total === 1) {
- console.info(`User ${username} already rated ${data.url} updating rating`);
+ console.info(`User ${username} already rated ${urlClean} updating rating`);
await new sdk.Databases(clientAdmin()).updateDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_RATINGS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID,
userRepoRating.documents[0].$id,
{
username: username,
- url: data.url,
+ url: urlClean,
rating: rating,
}
);
} else {
// 2b. create in ratings collection
- console.info(`User ${username} rating ${data.url} for the first time`);
+ console.info(`User ${username} rating ${urlClean} for the first time`);
await new sdk.Databases(clientAdmin()).createDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_RATINGS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID,
sdk.ID.unique(),
{
username: username,
- url: data.url,
+ url: urlClean,
rating: rating,
}
);
@@ -87,8 +88,8 @@ export async function POST(request) {
// 2c. update app rating count
console.info("Increment app total ratings");
await new sdk.Databases(clientAdmin()).updateDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_APP_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID,
appTotal.$id,
{
ratings: appTotal.ratings + 1,
@@ -97,21 +98,21 @@ export async function POST(request) {
);
// 3. check if repo exists
- console.info(`Checking if repo ${data.url} exists in database`);
+ console.info(`Checking if repo ${urlClean} exists in database`);
const repos = await new sdk.Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_REPOS_ID,
- [Query.equal("url", [data.url])]
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
+ [Query.equal("url", [urlClean])]
);
// 4a. update in repos collection + calculate new rating
if (repos.total === 1) {
- console.info(`Repo ${data.url} found in database update rating`);
+ console.info(`Repo ${urlClean} found in database update rating`);
// get all ratings for this repo
const ratings = await new sdk.Databases(clientAdmin()).listDocuments(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_RATINGS_ID,
- [Query.equal("url", [data.url])]
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_RATINGS_ID,
+ [Query.equal("url", [urlClean])]
);
// save new repo rating
@@ -119,8 +120,8 @@ export async function POST(request) {
ratings.documents.reduce((acc, cur) => acc + cur.rating, 0) /
ratings.total;
await new sdk.Databases(clientAdmin()).updateDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_REPOS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
repos.documents[0].$id,
{
...githubRepo,
@@ -131,15 +132,15 @@ export async function POST(request) {
} else {
// 4a. create in repos collection
console.info(
- `Repo ${data.url} not found in database create repo and ratings`
+ `Repo ${urlClean} not found in database create repo and ratings`
);
await new sdk.Databases(clientAdmin()).createDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_REPOS_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
sdk.ID.unique(),
{
...githubRepo,
- url: data.url,
+ url: urlClean,
rating: rating,
votes: 1,
}
@@ -147,8 +148,8 @@ export async function POST(request) {
// 4b. update app repo count
console.info("Increment app total repos");
await new sdk.Databases(clientAdmin()).updateDocument(
- process.env.APPWRITE_DATABASE_ID,
- process.env.APPWRITE_COLLECTION_APP_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID,
appTotal.$id,
{
repos: appTotal.repos + 1,
diff --git a/src/app/api/repos/route.js b/src/app/api/repos/route.js
new file mode 100644
index 0000000..a2bf364
--- /dev/null
+++ b/src/app/api/repos/route.js
@@ -0,0 +1,46 @@
+import { Query, Databases } from "node-appwrite";
+
+import { clientAdmin } from "@/config/appwrite-server";
+
+export const dynamic = "force-dynamic";
+
+export async function GET(request) {
+ const params = request.nextUrl.searchParams;
+ const minimumVotes = params.get("minimumVotes");
+ const keyword = params.get("keyword");
+
+ const repos = await new Databases(clientAdmin()).listDocuments(
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_REPOS_ID,
+ [
+ Query.select([
+ "url",
+ "logo",
+ "description",
+ "rating",
+ "votes",
+ "owner",
+ "name",
+ "badgeViews",
+ ]),
+ Query.orderDesc("rating"),
+ Query.orderDesc("votes"),
+ minimumVotes && Query.greaterThanEqual("votes", parseInt(minimumVotes)),
+ Query.limit(100),
+ keyword && Query.search("url", keyword),
+ ]
+ );
+
+ const all = repos.documents.map((repo) => ({
+ url: repo.url,
+ logo: repo.logo,
+ description: repo.description,
+ rating: repo.rating,
+ votes: repo.votes,
+ owner: repo.owner,
+ name: repo.name,
+ badgeViews: repo.badgeViews,
+ }));
+
+ return Response.json(all);
+}
diff --git a/src/app/api/stats/route.js b/src/app/api/stats/route.js
new file mode 100644
index 0000000..1ddc934
--- /dev/null
+++ b/src/app/api/stats/route.js
@@ -0,0 +1,17 @@
+import { Query, Databases } from "node-appwrite";
+
+import { clientAdmin } from "@/config/appwrite-server";
+
+export const dynamic = "force-dynamic";
+
+export async function GET() {
+ const data = (
+ await new Databases(clientAdmin()).listDocuments(
+ process.env.NEXT_PUBLIC_APPWRITE_DATABASE_ID,
+ process.env.NEXT_PUBLIC_APPWRITE_COLLECTION_APP_ID,
+ [Query.limit(1)]
+ )
+ ).documents[0];
+
+ return Response.json(data);
+}
diff --git a/src/app/auth/login/page.js b/src/app/auth/login/page.js
deleted file mode 100644
index 99f8330..0000000
--- a/src/app/auth/login/page.js
+++ /dev/null
@@ -1,33 +0,0 @@
-"use client";
-
-import { account } from "@/config/appwrite-client";
-
-export default function Page() {
- const login = async () => {
- account.createOAuth2Session(
- "github",
- `${process.env.NEXT_PUBLIC_BASE_URL}/`,
- `${process.env.NEXT_PUBLIC_BASE_URL}/auth/login`
- );
- };
-
- return (
-
- Open Source is about collaboration and sharing knowledge. But some
- repos have a better DX (Developer Experience), share your experience
- with the community!
- Rate an Open Source Repo!
-
- Rate Open Source GitHub Repositories on their Developer - Experience (DX). -
-