feat(nx-dev): plugin quality indicators (#18426)

This commit is contained in:
Isaac Mann 2023-08-03 11:15:05 -04:00 committed by GitHub
parent bf5111c342
commit f1a90bfd1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1267 additions and 51 deletions

View File

@ -5,6 +5,27 @@ _[Please make sure you have read the submission guidelines before posting an PR]
Thanks for submitting your Nx Plugin to our community plugins list. Make sure to follow these steps to ensure that your PR is approved in a timely manner. Thanks for submitting your Nx Plugin to our community plugins list. Make sure to follow these steps to ensure that your PR is approved in a timely manner.
## Plugin Requirements
Before you submit your plugin to be listed in our registry, it needs to meet the following requirements:
- Run some kind of automated e2e tests in your repository
- Include `@nx/devkit` as a `dependency` in the plugin's `package.json`
- List a `repository.url` in the plugin's `package.json`
i.e.
```
{
"repository": {
"type": "git",
"url": "https://github.com/nrwl/nx.git",
"directory": "packages/web"
}
}
```
Note: We reserve the right to remove unmaintained plugins from the registry. If the plugins become maintained again, they can be resubmitted to the registry.
## Steps to Submit Your Plugin ## Steps to Submit Your Plugin
- Use the following commit message template: `chore(core): nx plugin submission [PLUGIN_NAME]` - Use the following commit message template: `chore(core): nx plugin submission [PLUGIN_NAME]`
- Update the `community/approved-plugins.json` file with a new entry for your plugin that includes `name`, `url`, `description`: - Update the `community/approved-plugins.json` file with a new entry for your plugin that includes `name`, `url`, `description`:
@ -21,7 +42,7 @@ Example:
}] }]
``` ```
Once merged, your will plugin will be available when running the `nx list` command, and will also be available in the Plugin browser on [nx.dev](https://nx.dev) Once merged, your plugin will be available when running the `nx list` command, and will also be available in the Plugin Registry on [nx.dev](https://nx.dev/extending-nx/registry)
--> -->
# Community Plugin Submission # Community Plugin Submission

View File

@ -25,14 +25,24 @@
"url": "https://github.com/nxkit/nxkit" "url": "https://github.com/nxkit/nxkit"
}, },
{ {
"name": "nx-plugins", "name": "nx-plugin-esbuild",
"description": "Nx plugin integrations with ESBuild / Vite / Snowpack / Prisma, with derived ESBuild / Snowpack / ... plugins.", "description": "Nx plugin integrations with ESBuild.",
"url": "https://nx-plugins.netlify.app/" "url": "https://nx-plugins.netlify.app/"
}, },
{ {
"name": "@codebrew/nx-aws-cdk", "name": "nx-plugin-vite",
"description": "An Nx plugin for aws cdk develop.", "description": "Nx plugin integrations with Vite.",
"url": "https://github.com/codebrewlab/nx-plugins/tree/main/packages/nx-aws-cdk" "url": "https://nx-plugins.netlify.app/"
},
{
"name": "nx-plugin-snowpack",
"description": "Nx plugin integrations with Snowpack.",
"url": "https://nx-plugins.netlify.app/"
},
{
"name": "nx-plugin-prisma",
"description": "Nx plugin integrations with Snowpack.",
"url": "https://nx-plugins.netlify.app/"
}, },
{ {
"name": "@ago-dev/nx-aws-cdk-v2", "name": "@ago-dev/nx-aws-cdk-v2",
@ -74,21 +84,11 @@
"description": "An Nx plugin for developing cross-platform applications using Capacitor", "description": "An Nx plugin for developing cross-platform applications using Capacitor",
"url": "https://github.com/nxext/nx-extensions/tree/main/packages/capacitor" "url": "https://github.com/nxext/nx-extensions/tree/main/packages/capacitor"
}, },
{
"name": "@nxtend/firebase",
"description": "An Nx plugin for developing applications using Firebase",
"url": "https://github.com/nxtend-team/nxtend/tree/main/packages/firebase"
},
{ {
"name": "@angular-architects/ddd", "name": "@angular-architects/ddd",
"description": "Nx plugin for structuring a monorepo with domains and layers", "description": "Nx plugin for structuring a monorepo with domains and layers",
"url": "https://github.com/angular-architects/nx-ddd-plugin" "url": "https://github.com/angular-architects/nx-ddd-plugin"
}, },
{
"name": "@offeringsolutions/nx-karma-to-jest",
"description": "Nx plugin for replacing karma with jest in an Nx workspace",
"url": "https://github.com/FabianGosebrink/nx-karma-to-jest"
},
{ {
"name": "@flowaccount/nx-serverless", "name": "@flowaccount/nx-serverless",
"description": "Nx plugin for node/angular-universal schematics and deployment builders in an Nx workspace", "description": "Nx plugin for node/angular-universal schematics and deployment builders in an Nx workspace",
@ -109,21 +109,6 @@
"description": "Nx plugin to run playwright e2e tests in an Nx workspace", "description": "Nx plugin to run playwright e2e tests in an Nx workspace",
"url": "https://github.com/Bielik20/nx-plugins/tree/master/packages/nx-playwright" "url": "https://github.com/Bielik20/nx-plugins/tree/master/packages/nx-playwright"
}, },
{
"name": "@dev-thought/nx-deploy-it",
"description": "Nx plugin to deploy applications on your favorite cloud provider",
"url": "https://github.com/Dev-Thought/nx-plugins/tree/master/libs/nx-deploy-it"
},
{
"name": "@offeringsolutions/nx-protractor-to-cypress",
"description": "Nx plugin to replace protractor with cypress in an nx workspace",
"url": "https://github.com/FabianGosebrink/nx-protractor-to-cypress"
},
{
"name": "@angular-custom-builders/lite-serve",
"description": "Nx plugin to run the e2e test on an existing dist folder",
"url": "https://github.com/mauriziovitale/angular-plugins/tree/master/libs/lite-serve"
},
{ {
"name": "@nx-plus/nuxt", "name": "@nx-plus/nuxt",
"description": "Nx plugin adding first class support for Nuxt in your Nx workspace.", "description": "Nx plugin adding first class support for Nuxt in your Nx workspace.",
@ -235,7 +220,7 @@
"url": "https://github.com/trafilea/nx-shopify" "url": "https://github.com/trafilea/nx-shopify"
}, },
{ {
"name": "nx-dotnet", "name": "@nx-dotnet/core",
"description": "Nx plugin for developing and housing .NET projects within an Nx workspace.", "description": "Nx plugin for developing and housing .NET projects within an Nx workspace.",
"url": "https://github.com/nx-dotnet/nx-dotnet" "url": "https://github.com/nx-dotnet/nx-dotnet"
}, },

View File

@ -19,7 +19,27 @@ After that, you can then install your plugin like any other npm package,
## List your Nx Plugin ## List your Nx Plugin
Nx provides a utility (`nx list`) that lists both core and community plugins. To submit your plugin, please follow the steps below: Nx provides a utility (`nx list`) that lists both core and community plugins. You can submit your plugin to be added to this list, but it needs to meet a few criteria first:
- Run some kind of automated e2e tests in your repository
- Include `@nx/devkit` as a `dependency` in the plugin's `package.json`
- List a `repository.url` in the plugin's `package.json`
```jsonc {% fileName="package.json" %}
{
"repository": {
"type": "git",
"url": "https://github.com/nrwl/nx.git",
"directory": "packages/web"
}
}
```
{% callout type="warning" title="Unmaintained Plugins" %}
We reserve the right to remove unmaintained plugins from the registry. If the plugins become maintained again, they can be resubmitted to the registry.
{% /callout %}
Once those criteria are met, you can submit your plugin by following the steps below:
- Fork the [Nx repo](https://github.com/nrwl/nx/fork) (if you haven't already) - Fork the [Nx repo](https://github.com/nrwl/nx/fork) (if you haven't already)
- Update the [`community/approved-plugins.json` file](https://github.com/nrwl/nx/blob/master/community/approved-plugins.json) with a new entry for your plugin that includes name, url and description - Update the [`community/approved-plugins.json` file](https://github.com/nrwl/nx/blob/master/community/approved-plugins.json) with a new entry for your plugin that includes name, url and description

View File

@ -0,0 +1,676 @@
{
"@nx/angular": {
"lastPublishedDate": "2023-07-31T13:26:25.163Z",
"npmDownloads": 451513,
"githubStars": 18547
},
"@nx/cypress": {
"lastPublishedDate": "2023-07-31T13:26:10.027Z",
"npmDownloads": 1206854,
"githubStars": 18547
},
"@nx/detox": {
"lastPublishedDate": "2023-07-31T13:26:44.703Z",
"npmDownloads": 74541,
"githubStars": 18547
},
"@nx/devkit": {
"lastPublishedDate": "2023-07-31T13:25:14.034Z",
"npmDownloads": 4620584,
"githubStars": 18547
},
"@nx/esbuild": {
"lastPublishedDate": "2023-07-31T13:25:35.264Z",
"npmDownloads": 229089,
"githubStars": 18547
},
"@nx/eslint-plugin": {
"lastPublishedDate": "2023-07-31T13:25:37.806Z",
"npmDownloads": 1588081,
"githubStars": 18547
},
"@nx/expo": {
"lastPublishedDate": "2023-07-31T13:26:57.711Z",
"npmDownloads": 28596,
"githubStars": 18547
},
"@nx/express": {
"lastPublishedDate": "2023-07-31T13:26:32.209Z",
"npmDownloads": 141777,
"githubStars": 18547
},
"@nx/jest": {
"lastPublishedDate": "2023-07-31T13:25:46.305Z",
"npmDownloads": 1786802,
"githubStars": 18547
},
"@nx/js": {
"lastPublishedDate": "2023-07-31T13:25:30.195Z",
"npmDownloads": 2560691,
"githubStars": 18547
},
"@nx/linter": {
"lastPublishedDate": "2023-07-31T13:25:53.612Z",
"npmDownloads": 1975637,
"githubStars": 18547
},
"@nx/nest": {
"lastPublishedDate": "2023-07-31T13:26:35.646Z",
"npmDownloads": 490567,
"githubStars": 18547
},
"@nx/next": {
"lastPublishedDate": "2023-07-31T13:26:54.477Z",
"npmDownloads": 384056,
"githubStars": 18547
},
"@nx/node": {
"lastPublishedDate": "2023-07-31T13:26:12.510Z",
"npmDownloads": 830340,
"githubStars": 18547
},
"nx": {
"lastPublishedDate": "2023-07-31T13:25:19.774Z",
"npmDownloads": 16270290,
"githubStars": 18547
},
"@nx/playwright": {
"lastPublishedDate": "2023-08-03T03:30:49.402Z",
"npmDownloads": "",
"githubStars": 18547
},
"@nx/plugin": {
"lastPublishedDate": "2023-07-31T13:26:17.005Z",
"npmDownloads": 615978,
"githubStars": 18547
},
"@nx/react": {
"lastPublishedDate": "2023-07-31T13:26:19.350Z",
"npmDownloads": 828724,
"githubStars": 18547
},
"@nx/react-native": {
"lastPublishedDate": "2023-07-31T13:27:02.407Z",
"npmDownloads": 45656,
"githubStars": 18547
},
"@nx/rollup": {
"lastPublishedDate": "2023-07-31T13:25:56.293Z",
"npmDownloads": 143102,
"githubStars": 18547
},
"@nx/storybook": {
"lastPublishedDate": "2023-07-31T13:26:41.485Z",
"npmDownloads": 589880,
"githubStars": 18547
},
"@nx/vite": {
"lastPublishedDate": "2023-07-31T13:25:59.567Z",
"npmDownloads": 302208,
"githubStars": 18547
},
"@nx/web": {
"lastPublishedDate": "2023-07-31T13:26:02.010Z",
"npmDownloads": 1029649,
"githubStars": 18547
},
"@nx/webpack": {
"lastPublishedDate": "2023-07-31T13:26:06.719Z",
"npmDownloads": 1197589,
"githubStars": 18547
},
"@nx/workspace": {
"lastPublishedDate": "2023-07-31T13:25:27.694Z",
"npmDownloads": 2602643,
"githubStars": 18547
},
"@ahryman40k/nx-vitepress": {
"lastPublishedDate": "2022-12-23T01:15:39.916Z",
"npmDownloads": 51,
"githubStars": 0
},
"@nightwatch/nx": {
"lastPublishedDate": "2022-12-05T21:50:17.172Z",
"npmDownloads": 59,
"githubStars": 2
},
"@nxkit/playwright": {
"lastPublishedDate": "2023-06-06T17:50:01.235Z",
"npmDownloads": 16854,
"githubStars": 36
},
"qwik-nx": {
"lastPublishedDate": "2023-07-27T04:27:50.074Z",
"npmDownloads": 3896,
"githubStars": 113,
"nxVersion": ">= 15 <= 17"
},
"@nxkit/style-dictionary": {
"lastPublishedDate": "2023-06-06T17:50:01.313Z",
"npmDownloads": 8575,
"githubStars": 36
},
"nx-plugin-esbuild": {
"lastPublishedDate": "2021-10-02T13:53:16.067Z",
"npmDownloads": 480,
"githubStars": -1,
"nxVersion": "12.7.2"
},
"nx-plugin-vite": {
"lastPublishedDate": "2022-07-09T09:40:02.353Z",
"npmDownloads": 560,
"githubStars": 94
},
"nx-plugin-snowpack": {
"lastPublishedDate": "2021-10-04T02:55:28.868Z",
"npmDownloads": 39,
"githubStars": -1,
"nxVersion": "12.7.2"
},
"nx-plugin-prisma": {
"lastPublishedDate": "2021-09-30T04:07:48.904Z",
"npmDownloads": 12,
"githubStars": -1,
"nxVersion": "12.7.2"
},
"@codebrew/nx-aws-cdk": {
"lastPublishedDate": "2022-01-28T05:22:43.508Z",
"npmDownloads": 1576,
"githubStars": 20,
"nxVersion": ""
},
"@ago-dev/nx-aws-cdk-v2": {
"lastPublishedDate": "2023-05-08T11:33:02.618Z",
"npmDownloads": 37529,
"githubStars": 30,
"nxVersion": ""
},
"@berenddeboer/nx-sst": {
"lastPublishedDate": "2023-07-28T02:12:51.950Z",
"npmDownloads": 1222,
"githubStars": 4,
"nxVersion": ">= 15 <= 17"
},
"@rxap/plugin-localazy": {
"lastPublishedDate": "2022-12-14T13:23:03.536Z",
"npmDownloads": 511,
"githubStars": -1,
"nxVersion": ">= 14 <= 16"
},
"nx-electron": {
"lastPublishedDate": "2023-06-22T13:23:58.845Z",
"npmDownloads": 15276,
"githubStars": 273,
"nxVersion": ">= 14.1 <= 16"
},
"nx-stylelint": {
"lastPublishedDate": "2023-02-16T14:16:46.275Z",
"npmDownloads": 120338,
"githubStars": 64,
"nxVersion": ">= 14 <= 16"
},
"@nxext/ionic-react": {
"lastPublishedDate": "2023-05-26T12:53:11.721Z",
"npmDownloads": 689,
"githubStars": -1
},
"@nxext/ionic-angular": {
"lastPublishedDate": "2023-05-26T12:52:58.419Z",
"npmDownloads": 33272,
"githubStars": 190
},
"@nxext/capacitor": {
"lastPublishedDate": "2023-06-12T07:43:34.104Z",
"npmDownloads": 51591,
"githubStars": 395,
"nxVersion": ">= 15 <= 17"
},
"@nxtend/firebase": {
"lastPublishedDate": "2021-12-02T15:22:22.629Z",
"npmDownloads": 291,
"githubStars": 190,
"nxVersion": "12.0.0"
},
"@angular-architects/ddd": {
"lastPublishedDate": "2023-05-20T19:52:32.293Z",
"npmDownloads": 20613,
"githubStars": 276
},
"@offeringsolutions/nx-karma-to-jest": {
"lastPublishedDate": "2020-03-08T19:29:18.913Z",
"npmDownloads": 18,
"githubStars": 9
},
"@flowaccount/nx-serverless": {
"lastPublishedDate": "2023-07-10T19:06:16.916Z",
"npmDownloads": 7236,
"githubStars": -1,
"nxVersion": ">= 13.10 <= 15"
},
"@ns3/nx-serverless": {
"lastPublishedDate": "2023-07-12T07:08:25.829Z",
"npmDownloads": 55611,
"githubStars": 59
},
"@ns3/nx-jest-playwright": {
"lastPublishedDate": "2023-05-03T07:05:36.802Z",
"npmDownloads": 7036,
"githubStars": 59
},
"@ns3/nx-playwright": {
"lastPublishedDate": "2023-05-03T07:05:36.629Z",
"npmDownloads": 4907,
"githubStars": 59
},
"@dev-thought/nx-deploy-it": {
"lastPublishedDate": "2021-02-12T21:12:18.923Z",
"npmDownloads": 218,
"githubStars": 77
},
"@offeringsolutions/nx-protractor-to-cypress": {
"lastPublishedDate": "2021-03-04T15:12:40.394Z",
"npmDownloads": 11,
"githubStars": 4,
"nxVersion": ""
},
"@angular-custom-builders/lite-serve": {
"lastPublishedDate": "2021-03-08T14:21:34.424Z",
"npmDownloads": 1682,
"githubStars": 6
},
"@nx-plus/nuxt": {
"lastPublishedDate": "2022-07-02T16:45:19.149Z",
"npmDownloads": 3343,
"githubStars": 298,
"nxVersion": ">= 13.10 <= 15"
},
"@nx-plus/vue": {
"lastPublishedDate": "2022-12-05T02:51:23.682Z",
"npmDownloads": 9789,
"githubStars": 298,
"nxVersion": ">= 14 <= 16"
},
"@nx-plus/docusaurus": {
"lastPublishedDate": "2022-12-05T02:51:37.534Z",
"npmDownloads": 61760,
"githubStars": 298,
"nxVersion": ">= 14 <= 16"
},
"@twittwer/compodoc": {
"lastPublishedDate": "2023-06-25T12:35:20.159Z",
"npmDownloads": 18068,
"githubStars": 40,
"nxVersion": ">= 15 <= 17"
},
"@enio.ai/nx-install": {
"lastPublishedDate": "2023-03-05T20:18:09.761Z",
"npmDownloads": 61,
"githubStars": 22,
"nxVersion": ">= 14.1 <= 16"
},
"@enio.ai/typedoc": {
"lastPublishedDate": "2023-03-05T20:17:20.752Z",
"npmDownloads": 3643,
"githubStars": 22,
"nxVersion": ">= 14.1 <= 16"
},
"@nxext/svelte": {
"lastPublishedDate": "2023-05-26T12:47:54.560Z",
"npmDownloads": 5277,
"githubStars": 395
},
"@nxext/stencil": {
"lastPublishedDate": "2023-06-21T09:20:15.486Z",
"npmDownloads": 11402,
"githubStars": 395,
"nxVersion": ">= 15 <= 17"
},
"@nxext/vite": {
"lastPublishedDate": "2023-02-28T19:05:21.436Z",
"npmDownloads": 24063,
"githubStars": 395,
"nxVersion": ">= 14.1 <= 16"
},
"@nxext/solid": {
"lastPublishedDate": "2023-05-26T12:47:38.232Z",
"npmDownloads": 1555,
"githubStars": 395
},
"@joelcode/gcp-function": {
"lastPublishedDate": "2021-09-15T16:46:35.377Z",
"npmDownloads": 29,
"githubStars": -1
},
"@nx-go/nx-go": {
"lastPublishedDate": "2022-10-17T07:48:25.180Z",
"npmDownloads": 242857,
"githubStars": -1
},
"@nx-golang/gin": {
"lastPublishedDate": "2023-01-04T14:57:24.660Z",
"npmDownloads": 37,
"githubStars": 0
},
"@angular-architects/module-federation": {
"lastPublishedDate": "2023-06-20T16:52:19.205Z",
"npmDownloads": 445713,
"githubStars": 577
},
"@nxrocks/nx-spring-boot": {
"lastPublishedDate": "2023-05-12T16:58:52.743Z",
"npmDownloads": 6938,
"githubStars": 231,
"nxVersion": ">= 15 <= 17"
},
"@trumbitta/nx-plugin-openapi": {
"lastPublishedDate": "2022-08-28T20:54:50.978Z",
"npmDownloads": 27028,
"githubStars": -1,
"nxVersion": "13.0.0"
},
"@trumbitta/nx-plugin-unused-deps": {
"lastPublishedDate": "2022-08-28T20:55:11.226Z",
"npmDownloads": 65267,
"githubStars": -1,
"nxVersion": "13.0.0"
},
"@nxrocks/nx-flutter": {
"lastPublishedDate": "2023-05-12T16:59:33.230Z",
"npmDownloads": 8587,
"githubStars": 231,
"nxVersion": ">= 15 <= 17"
},
"@srleecode/domain": {
"lastPublishedDate": "2023-06-22T13:44:39.620Z",
"npmDownloads": 381,
"githubStars": -1,
"nxVersion": ""
},
"@jscutlery/semver": {
"lastPublishedDate": "2023-07-31T06:50:30.918Z",
"npmDownloads": 523358,
"githubStars": 619,
"nxVersion": ">= 15 <= 17"
},
"ngx-deploy-npm": {
"lastPublishedDate": "2023-05-15T07:18:38.684Z",
"npmDownloads": 287616,
"githubStars": 99,
"nxVersion": ">= 15 <= 17"
},
"@trafilea/nx-shopify": {
"lastPublishedDate": "2021-06-02T19:51:43.707Z",
"npmDownloads": 102,
"githubStars": 42,
"nxVersion": "12.0.8"
},
"@nx-dotnet/core": {
"lastPublishedDate": "2023-04-12T17:54:41.139Z",
"npmDownloads": 58546,
"githubStars": 214,
"nxVersion": ">= 14.1 <= 16"
},
"@nxrocks/nx-quarkus": {
"lastPublishedDate": "2023-05-12T16:59:55.758Z",
"npmDownloads": 10003,
"githubStars": 231,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/gcp-secrets": {
"lastPublishedDate": "2023-06-22T17:40:46.440Z",
"npmDownloads": 95,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/gcp-storage": {
"lastPublishedDate": "2023-06-22T17:40:53.943Z",
"npmDownloads": 987,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/gcp-functions": {
"lastPublishedDate": "2023-07-22T09:38:42.753Z",
"npmDownloads": 4113,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/gcp-deployment-manager": {
"lastPublishedDate": "2023-06-22T17:40:40.176Z",
"npmDownloads": 107,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/gcp-cloud-run": {
"lastPublishedDate": "2023-06-22T17:40:52.218Z",
"npmDownloads": 2142,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/translations": {
"lastPublishedDate": "2023-06-22T17:40:44.178Z",
"npmDownloads": 233,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/firebase-hosting": {
"lastPublishedDate": "2023-07-13T10:38:12.436Z",
"npmDownloads": 1382,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/e2e-runner": {
"lastPublishedDate": "2023-07-21T20:54:54.000Z",
"npmDownloads": 6501,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/vercel": {
"lastPublishedDate": "2023-07-28T08:36:42.305Z",
"npmDownloads": 820,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/strapi": {
"lastPublishedDate": "2023-07-12T07:02:19.604Z",
"npmDownloads": 9188,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/playwright": {
"lastPublishedDate": "2023-06-22T17:40:55.663Z",
"npmDownloads": 7561,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/terraform": {
"lastPublishedDate": "2023-06-22T17:40:57.454Z",
"npmDownloads": 570,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nx-extend/pulumi": {
"lastPublishedDate": "2023-06-22T17:40:59.131Z",
"npmDownloads": 467,
"githubStars": 98,
"nxVersion": ">= 15 <= 17"
},
"@nativescript/nx": {
"lastPublishedDate": "2023-07-05T22:55:56.178Z",
"npmDownloads": 10409,
"githubStars": 58,
"nxVersion": ">= 15 <= 17"
},
"@nx-clean/plugin-core": {
"lastPublishedDate": "2022-03-10T15:36:11.690Z",
"npmDownloads": 145,
"githubStars": 65,
"nxVersion": ""
},
"@jnxplus/nx-boot-gradle": {
"lastPublishedDate": "2023-07-28T16:33:38.123Z",
"npmDownloads": 2384,
"githubStars": -1,
"nxVersion": ">= 15 <= 17"
},
"@jnxplus/nx-boot-maven": {
"lastPublishedDate": "2023-07-28T16:34:00.918Z",
"npmDownloads": 7475,
"githubStars": -1,
"nxVersion": ">= 15 <= 17"
},
"@nxtensions/astro": {
"lastPublishedDate": "2023-07-30T14:40:23.494Z",
"npmDownloads": 4841,
"githubStars": 43,
"nxVersion": ">= 15 <= 17"
},
"@nxrs/cargo": {
"lastPublishedDate": "2022-05-25T02:55:50.238Z",
"npmDownloads": 2601,
"githubStars": 101
},
"nx-uvu": {
"lastPublishedDate": "2023-06-16T16:07:57.812Z",
"npmDownloads": 563,
"githubStars": -1,
"nxVersion": ">= 15 <= 17"
},
"@ndrsg/nx-http": {
"lastPublishedDate": "2022-06-07T13:16:25.323Z",
"npmDownloads": 18,
"githubStars": 6,
"nxVersion": "14.0.0"
},
"@diogovcs/graphql-mesh": {
"lastPublishedDate": "2023-01-22T11:38:26.303Z",
"npmDownloads": 633,
"githubStars": -1
},
"@computas/nx-yarn": {
"lastPublishedDate": "2022-05-30T07:04:03.376Z",
"npmDownloads": 463,
"githubStars": -1,
"nxVersion": ">= 13.10 <= 15"
},
"@theunderscorer/nx-semantic-release": {
"lastPublishedDate": "2023-07-16T18:50:55.453Z",
"npmDownloads": 17537,
"githubStars": 61,
"nxVersion": ">= 15 <= 17"
},
"nx-pwm": {
"lastPublishedDate": "2022-12-03T18:41:17.623Z",
"npmDownloads": 19,
"githubStars": 4,
"nxVersion": ">= 14 <= 16"
},
"@nxrocks/nx-micronaut": {
"lastPublishedDate": "2023-05-12T16:59:13.295Z",
"npmDownloads": 201,
"githubStars": 231,
"nxVersion": ">= 15 <= 17"
},
"@koliveira15/nx-sonarqube": {
"lastPublishedDate": "2023-08-02T00:25:44.844Z",
"npmDownloads": 43559,
"githubStars": 21
},
"@mands/nx-playwright": {
"lastPublishedDate": "2023-05-16T10:59:21.495Z",
"npmDownloads": 63690,
"githubStars": 58
},
"@diogovcs/stryker-mutator": {
"lastPublishedDate": "2023-03-18T12:51:54.214Z",
"npmDownloads": 2414,
"githubStars": -1,
"nxVersion": ""
},
"@spaceribs/nx-web-ext": {
"lastPublishedDate": "2023-07-16T15:45:19.229Z",
"npmDownloads": 256,
"githubStars": 5,
"nxVersion": ">= 15 <= 17"
},
"@spaceribs/nx-betterer": {
"lastPublishedDate": "2023-07-16T15:45:12.663Z",
"npmDownloads": 176,
"githubStars": 5,
"nxVersion": ">= 15 <= 17"
},
"@nx-tools/nx-container": {
"lastPublishedDate": "2023-06-21T06:38:36.059Z",
"npmDownloads": 103868,
"githubStars": 261,
"nxVersion": ">= 15 <= 17"
},
"@nxrocks/nx-melos": {
"lastPublishedDate": "2023-05-12T17:00:25.890Z",
"npmDownloads": 166,
"githubStars": 231,
"nxVersion": ">= 15 <= 17"
},
"@monodon/rust": {
"lastPublishedDate": "2023-06-30T16:35:58.528Z",
"npmDownloads": 7138,
"githubStars": 15,
"nxVersion": ">= 15 <= 17"
},
"nx-mesh": {
"lastPublishedDate": "2023-04-26T20:23:43.825Z",
"npmDownloads": 2113,
"githubStars": 19,
"nxVersion": ">= 14.1 <= 16"
},
"@nxazure/func": {
"lastPublishedDate": "2023-06-17T22:19:57.878Z",
"npmDownloads": 2041,
"githubStars": 9
},
"@rbnx/webdriverio": {
"lastPublishedDate": "2023-05-05T06:51:41.339Z",
"npmDownloads": 233,
"githubStars": 7,
"nxVersion": ">= 15 <= 17"
},
"nx-ngrok": {
"lastPublishedDate": "2023-04-17T21:34:27.110Z",
"npmDownloads": 244,
"githubStars": 0,
"nxVersion": ">= 14.1 <= 16"
},
"@nxrocks/nx-ktor": {
"lastPublishedDate": "2023-05-25T05:35:48.467Z",
"npmDownloads": 27,
"githubStars": 231,
"nxVersion": ">= 15 <= 17"
},
"nx-size-limit": {
"lastPublishedDate": "2023-04-22T07:50:24.764Z",
"npmDownloads": 313,
"githubStars": 7
},
"@jnxplus/nx-quarkus-gradle": {
"lastPublishedDate": "2023-07-28T16:33:30.811Z",
"npmDownloads": 750,
"githubStars": -1,
"nxVersion": ">= 15 <= 17"
},
"@jnxplus/nx-quarkus-maven": {
"lastPublishedDate": "2023-07-28T16:33:52.833Z",
"npmDownloads": 725,
"githubStars": -1,
"nxVersion": ">= 15 <= 17"
},
"@loft-orbital/terraform": {
"lastPublishedDate": "2023-03-25T21:03:22.028Z",
"npmDownloads": 432,
"githubStars": -1
},
"@nxlv/python": {
"lastPublishedDate": "2023-07-06T13:05:49.453Z",
"npmDownloads": 9584,
"githubStars": 43,
"nxVersion": ">= 15 <= 17"
}
}

View File

@ -13,6 +13,7 @@ import { useRef } from 'react';
import { menusApi } from '../../lib/menus.api'; import { menusApi } from '../../lib/menus.api';
import { useNavToggle } from '../../lib/navigation-toggle.effect'; import { useNavToggle } from '../../lib/navigation-toggle.effect';
import { nxPackagesApi } from '../../lib/packages.api'; import { nxPackagesApi } from '../../lib/packages.api';
import * as qualityIndicators from './quality-indicators.json';
declare const fetch: any; declare const fetch: any;
@ -50,10 +51,13 @@ export async function getStaticProps(): Promise<{ props: BrowseProps }> {
name: plugin.packageName, name: plugin.packageName,
description: plugin.description ?? '', description: plugin.description ?? '',
url: plugin.path, url: plugin.path,
...qualityIndicators[plugin.packageName],
nxVersion: 'official',
isOfficial: true, isOfficial: true,
})), })),
...pluginList.map((plugin) => ({ ...pluginList.map((plugin) => ({
...plugin, ...plugin,
...qualityIndicators[plugin.name],
isOfficial: false, isOfficial: false,
})), })),
], ],

View File

@ -1,8 +1,18 @@
import {
ArrowDownIcon,
ClockIcon,
StarIcon,
} from '@heroicons/react/24/outline';
export interface PluginCardProps { export interface PluginCardProps {
name: string; name: string;
description: string; description: string;
url: string; url: string;
isOfficial: boolean; isOfficial: boolean;
lastPublishedDate?: string;
npmDownloads?: string;
githubStars?: string;
nxVersion?: string;
} }
export function PluginCard({ export function PluginCard({
@ -10,9 +20,13 @@ export function PluginCard({
description, description,
url, url,
isOfficial, isOfficial,
lastPublishedDate,
npmDownloads,
githubStars,
nxVersion,
}: PluginCardProps): JSX.Element { }: PluginCardProps): JSX.Element {
return ( return (
<div className="focus-within:ring-focus-within:ring-blue-500 relative flex w-full overflow-hidden rounded-lg border border border-slate-200 bg-white shadow-sm transition hover:bg-slate-50 dark:border-slate-900 dark:bg-slate-800/60 dark:focus-within:ring-sky-500 dark:hover:bg-slate-800"> <div className="focus-within:ring-focus-within:ring-blue-500 relative flex w-full rounded-lg border border border-slate-200 bg-white shadow-sm transition hover:bg-slate-50 dark:border-slate-900 dark:bg-slate-800/60 dark:focus-within:ring-sky-500 dark:hover:bg-slate-800">
<div className="flex w-full flex-col px-4 py-3"> <div className="flex w-full flex-col px-4 py-3">
<h3 className="mb-4 flex items-center font-semibold leading-tight"> <h3 className="mb-4 flex items-center font-semibold leading-tight">
<svg <svg
@ -31,22 +45,140 @@ export function PluginCard({
href={url} href={url}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
title={name} className="focus:outline-none flex flex-col grow"
className="focus:outline-none"
> >
<span className="absolute inset-0" aria-hidden="true" /> <span className="absolute inset-0" aria-hidden="true" />
<p className="line-clamp-3 mb-6 text-sm">{description}</p> <p className="line-clamp-3 mb-2 text-sm grow">{description}</p>
<div className="flex flex-wrap justify-between items-center py-0.5 text-xs font-medium capitalize">
<div className="mr-1 my-1">
<LastPublishedWidget
lastPublishedDate={lastPublishedDate}
></LastPublishedWidget>
</div>
<div className="mx-1 my-1">
<NpmDownloadsWidget
npmDownloads={npmDownloads}
></NpmDownloadsWidget>
</div>
<div className="mx-1 my-1">
<GithubStarsWidget githubStars={githubStars}></GithubStarsWidget>
</div>
<div className="flex-grow flex justify-end">
{isOfficial ? ( {isOfficial ? (
<span <div
title="Official plugins are maintained by the Nx Team" data-tooltip="Maintained by the Nx Team"
className="bg-green-500 absolute bottom-3 right-4 rounded-full px-3 py-0.5 text-xs font-medium capitalize text-white" className="ml-1 my-1 border inline-block bg-green-50 border-green-300 text-green-600 dark:border-green-900 dark:bg-green-900/30 dark:text-green-400 rounded-full px-3 py-0.5 text-xs font-medium capitalize"
> >
Official Nx Team
</span> </div>
) : null} ) : (
<div className="ml-1 my-1">
<NxVersionWidget nxVersion={nxVersion}></NxVersionWidget>
</div>
)}
</div>
</div>
</a> </a>
</div> </div>
</div> </div>
); );
} }
export function LastPublishedWidget({
lastPublishedDate,
}: {
lastPublishedDate: string | undefined;
}) {
if (!lastPublishedDate) {
return <div className="w-20"></div>;
}
return (
<abbr data-tooltip="Most Recent Release Date">
<ClockIcon className="h-4 w-4 inline-block mx-0.5 align-bottom"></ClockIcon>
{/* yyyy-MM-dd */}
<span>{new Date(lastPublishedDate).toISOString().slice(0, 10)}</span>
<span className="md:hidden">
<br />
<small>Most Recent Release Date</small>
</span>
</abbr>
);
}
function NpmDownloadsWidget({
npmDownloads,
}: {
npmDownloads: string | undefined;
}) {
if (!npmDownloads) {
return <div className="w-8"></div>;
}
return (
<abbr data-tooltip="Monthly NPM Downloads">
<ArrowDownIcon className="h-4 w-4 inline-block mx-0.5 align-bottom"></ArrowDownIcon>
{shortenNumber(npmDownloads)}
<span className="md:hidden">
<br />
<small>Monthly NPM Downloads</small>
</span>
</abbr>
);
}
function GithubStarsWidget({
githubStars,
}: {
githubStars: string | undefined;
}) {
if (!githubStars || githubStars == '-1') {
return <div className="w-8"></div>;
}
return (
<abbr data-tooltip="GitHub Stars">
<StarIcon className="h-4 w-4 inline-block mx-0.5 align-bottom"></StarIcon>
{shortenNumber(githubStars)}
<span className="md:hidden">
<br />
<small>GitHub Stars</small>
</span>
</abbr>
);
}
function shortenNumber(number: string | number): string {
const num = Number.parseInt(number + '');
if (num > 1000000) {
return Math.floor(num / 1000000) + 'M';
}
if (num > 1000) {
return Math.floor(num / 1000) + 'k';
}
return num + '';
}
function NxVersionWidget({ nxVersion }: { nxVersion: string | undefined }) {
if (!nxVersion) {
return <div className="w-20"></div>;
}
return (
<abbr data-tooltip="Supported Nx Versions">
{/* Nx Logo */}
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 inline-block mx-0.5 align-bottom"
fill="currentColor"
>
<title>Nx</title>
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
</svg>
{nxVersion}
<span className="md:hidden">
<br />
<small>Supported Nx Versions</small>
</span>
</abbr>
);
}

View File

@ -1,3 +1,10 @@
import {
ArrowDownIcon,
ArrowLongDownIcon,
ArrowLongUpIcon,
ClockIcon,
StarIcon,
} from '@heroicons/react/24/outline';
import { MagnifyingGlassIcon } from '@heroicons/react/24/solid'; import { MagnifyingGlassIcon } from '@heroicons/react/24/solid';
import { PluginCard, SectionHeading } from '@nx/nx-dev/ui-common'; import { PluginCard, SectionHeading } from '@nx/nx-dev/ui-common';
import { useState } from 'react'; import { useState } from 'react';
@ -7,6 +14,26 @@ interface Plugin {
name: string; name: string;
url: string; url: string;
isOfficial: boolean; isOfficial: boolean;
lastPublishedDate?: string;
npmDownloads?: string;
githubStars?: string;
nxVersion?: string;
}
type OrderByStatus =
| 'lastPublishDate'
| 'npmDownloads'
| 'githubStars'
| 'nxVersion'
| undefined;
interface Modifiers {
term: string;
officialStatus: 'official' | 'community' | undefined;
minimumDownloads: number | undefined;
minimumStars: number | undefined;
minimumNxVersion: string | undefined;
orderBy: OrderByStatus;
orderDirection: 'ASC' | 'DESC';
} }
export function PluginDirectory({ export function PluginDirectory({
@ -14,12 +41,33 @@ export function PluginDirectory({
}: { }: {
pluginList: Plugin[]; pluginList: Plugin[];
}): JSX.Element { }): JSX.Element {
const [searchTerm, setSearchTerm] = useState(''); const [modifiers, setModifiers] = useState<Modifiers>({
term: '',
officialStatus: undefined,
minimumDownloads: undefined,
minimumStars: undefined,
minimumNxVersion: undefined,
orderBy: undefined,
orderDirection: 'ASC',
});
function setOrderBy(status: OrderByStatus) {
if (modifiers.orderBy === status) {
setModifiers({
...modifiers,
orderDirection: modifiers.orderDirection === 'ASC' ? 'DESC' : 'ASC',
});
} else {
setModifiers({
...modifiers,
orderBy: status,
});
}
}
return ( return (
<div id="plugin-directory"> <div id="plugin-directory">
<div className="flex w-full flex-col justify-between gap-8 md:flex-row "> <div className="flex w-full flex-col justify-between gap-8 md:flex-row ">
<SectionHeading as="h2" variant="display" id="plugins-registry"> <SectionHeading as="h2" variant="display" id="plugins-registry">
Nx Plugins Registry <span className="whitespace-nowrap">Nx Plugins</span> Registry
</SectionHeading> </SectionHeading>
<div> <div>
<label htmlFor="search" className="sr-only"> <label htmlFor="search" className="sr-only">
@ -34,28 +82,160 @@ export function PluginDirectory({
name="search" name="search"
className="block w-full rounded-md border border-slate-300 bg-white py-2 pl-10 pr-3 text-sm placeholder-slate-500 transition focus:placeholder-slate-400 dark:border-slate-900 dark:bg-slate-700" className="block w-full rounded-md border border-slate-300 bg-white py-2 pl-10 pr-3 text-sm placeholder-slate-500 transition focus:placeholder-slate-400 dark:border-slate-900 dark:bg-slate-700"
placeholder="Quick search" placeholder="Quick search"
onChange={(event) => setSearchTerm(event.target.value)} onChange={(event) =>
setModifiers({ ...modifiers, term: event.target.value })
}
type="search" type="search"
/> />
</div> </div>
<div className="text-xs my-2 flex whitespace-nowrap">
<div className="py-1 mr-1">Order by:</div>
<div className="flex flex-wrap gap-1">
<button
className="rounded-sm border border-slate-200 bg-white py-1 px-1 font-semibold transition hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
onClick={() => setOrderBy('lastPublishDate')}
>
<ClockIcon className="h-4 w-4 inline-block mr-0.5 align-bottom"></ClockIcon>
Release Date
{modifiers.orderBy === 'lastPublishDate' &&
modifiers.orderDirection === 'DESC' ? (
<ArrowLongUpIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongUpIcon>
) : null}
{modifiers.orderBy === 'lastPublishDate' &&
modifiers.orderDirection === 'ASC' ? (
<ArrowLongDownIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongDownIcon>
) : null}
</button>
<button
className="rounded-sm border border-slate-200 bg-white py-1 px-1 font-semibold transition hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
onClick={() => setOrderBy('npmDownloads')}
>
<ArrowDownIcon className="h-4 w-4 inline-block mr-0.5 align-bottom"></ArrowDownIcon>
Downloads
{modifiers.orderBy === 'npmDownloads' &&
modifiers.orderDirection === 'DESC' ? (
<ArrowLongUpIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongUpIcon>
) : null}
{modifiers.orderBy === 'npmDownloads' &&
modifiers.orderDirection === 'ASC' ? (
<ArrowLongDownIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongDownIcon>
) : null}
</button>
<button
className="rounded-sm border border-slate-200 bg-white py-1 px-1 font-semibold transition hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
onClick={() => setOrderBy('githubStars')}
>
<StarIcon className="h-4 w-4 inline-block mr-0.5 align-bottom"></StarIcon>
GH Stars
{modifiers.orderBy === 'githubStars' &&
modifiers.orderDirection === 'DESC' ? (
<ArrowLongUpIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongUpIcon>
) : null}
{modifiers.orderBy === 'githubStars' &&
modifiers.orderDirection === 'ASC' ? (
<ArrowLongDownIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongDownIcon>
) : null}
</button>
<button
className="rounded-sm border border-slate-200 bg-white py-1 px-1 font-semibold transition hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700"
onClick={() => setOrderBy('nxVersion')}
>
{/* Nx Logo */}
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 inline-block mx-0.5 align-bottom"
fill="currentColor"
>
<title>Nx</title>
<path d="M11.987 14.138l-3.132 4.923-5.193-8.427-.012 8.822H0V4.544h3.691l5.247 8.833.005-3.998 3.044 4.759zm.601-5.761c.024-.048 0-3.784.008-3.833h-3.65c.002.059-.005 3.776-.003 3.833h3.645zm5.634 4.134a2.061 2.061 0 0 0-1.969 1.336 1.963 1.963 0 0 1 2.343-.739c.396.161.917.422 1.33.283a2.1 2.1 0 0 0-1.704-.88zm3.39 1.061c-.375-.13-.8-.277-1.109-.681-.06-.08-.116-.17-.176-.265a2.143 2.143 0 0 0-.533-.642c-.294-.216-.68-.322-1.18-.322a2.482 2.482 0 0 0-2.294 1.536 2.325 2.325 0 0 1 4.002.388.75.75 0 0 0 .836.334c.493-.105.46.36 1.203.518v-.133c-.003-.446-.246-.55-.75-.733zm2.024 1.266a.723.723 0 0 0 .347-.638c-.01-2.957-2.41-5.487-5.37-5.487a5.364 5.364 0 0 0-4.487 2.418c-.01-.026-1.522-2.39-1.538-2.418H8.943l3.463 5.423-3.379 5.32h3.54l1.54-2.366 1.568 2.366h3.541l-3.21-5.052a.7.7 0 0 1-.084-.32 2.69 2.69 0 0 1 2.69-2.691h.001c1.488 0 1.736.89 2.057 1.308.634.826 1.9.464 1.9 1.541a.707.707 0 0 0 1.066.596zm.35.133c-.173.372-.56.338-.755.639-.176.271.114.412.114.412s.337.156.538-.311c.104-.231.14-.488.103-.74z" />
</svg>
Nx Version
{modifiers.orderBy === 'nxVersion' &&
modifiers.orderDirection === 'DESC' ? (
<ArrowLongUpIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongUpIcon>
) : null}
{modifiers.orderBy === 'nxVersion' &&
modifiers.orderDirection === 'ASC' ? (
<ArrowLongDownIcon className="h-4 w-4 inline-block ml-0.5 align-bottom"></ArrowLongDownIcon>
) : null}
</button>
</div>
</div>
</div> </div>
</div> </div>
<div className="my-12 grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3"> <div className="my-12 grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
{pluginList {pluginList
.filter((plugin) => .filter((plugin) =>
!!searchTerm !!modifiers.term
? plugin.name.toLowerCase().includes(searchTerm.toLowerCase()) || ? plugin.name
.toLowerCase()
.includes(modifiers.term.toLowerCase()) ||
plugin.description plugin.description
.toLowerCase() .toLowerCase()
.includes(searchTerm.toLowerCase()) .includes(modifiers.term.toLowerCase())
: true : true
) )
.sort((a, b) => {
if (modifiers.orderBy === 'lastPublishDate') {
return (
(modifiers.orderDirection === 'ASC' ? 1 : -1) *
(new Date(a.lastPublishedDate || '').getTime() -
new Date(b.lastPublishedDate || '').getTime())
);
} else if (modifiers.orderBy === 'npmDownloads') {
return (
(modifiers.orderDirection === 'ASC' ? 1 : -1) *
(Number.parseInt(a.npmDownloads || '0') -
Number.parseInt(b.npmDownloads || '0'))
);
} else if (modifiers.orderBy === 'githubStars') {
return (
(modifiers.orderDirection === 'ASC' ? 1 : -1) *
(Number.parseInt(a.githubStars || '0') -
Number.parseInt(b.githubStars || '0'))
);
} else if (modifiers.orderBy === 'nxVersion') {
const versionValueMap: Record<string, number> = {
unknown: 0,
'12': 12,
'13': 13,
'14': 14,
'15': 15,
'16': 16,
'17': 17,
'18': 18,
'>= 15': 17,
'>= 14': 16,
'>= 13': 15,
official: 1000,
};
function getValueFromVersion(version: string = 'unknown') {
const mapKey =
Object.keys(versionValueMap).find((key) =>
version.startsWith(key)
) || 'unknown';
return versionValueMap[mapKey];
}
return (
(modifiers.orderDirection === 'ASC' ? 1 : -1) *
(getValueFromVersion(a.nxVersion) -
getValueFromVersion(b.nxVersion))
);
}
return 0;
})
.map((plugin) => ( .map((plugin) => (
<PluginCard <PluginCard
key={plugin.name} key={plugin.name}
name={plugin.name} name={plugin.name}
description={plugin.description} description={plugin.description}
isOfficial={plugin.isOfficial} isOfficial={plugin.isOfficial}
lastPublishedDate={plugin.lastPublishedDate}
npmDownloads={plugin.npmDownloads}
githubStars={plugin.githubStars}
nxVersion={plugin.nxVersion}
url={plugin.url} url={plugin.url}
/> />
))} ))}

View File

@ -0,0 +1,198 @@
import { writeFileSync } from 'fs';
import axios from 'axios';
interface Interval {
start: Date;
end: Date;
}
interface PluginRegistry {
name: string;
description: string;
url: string;
}
const packagesJson = require('../../nx-dev/nx-dev/public/documentation/generated/manifests/packages.json');
const officialPlugins = Object.keys(packagesJson)
.filter(
(m: any) =>
packagesJson[m].name !== 'add-nx-to-monorepo' &&
packagesJson[m].name !== 'cra-to-nx' &&
packagesJson[m].name !== 'create-nx-plugin' &&
packagesJson[m].name !== 'create-nx-workspace' &&
packagesJson[m].name !== 'make-angular-cli-faster' &&
packagesJson[m].name !== 'tao'
)
.map((k) => ({
name: packagesJson[k].name === 'nx' ? 'nx' : '@nx/' + packagesJson[k].name,
description: packagesJson[k].description,
url: packagesJson[k].githubRoot,
}));
const plugins =
require('../../community/approved-plugins.json') as PluginRegistry[];
async function main() {
const qualityIndicators: any = {};
const { data } = await axios.get(`https://api.github.com/repos/nrwl/nx`, {
headers: {
Authorization: `Bearer ${process.env.GITHUB_PAT}`,
},
});
const nxGithubStars = data.stargazers_count;
for (let i = 0; i < officialPlugins.length; i++) {
const plugin = officialPlugins[i];
console.log(`Fetching data for ${plugin.name}`);
const npmData = await getNpmData(plugin, true);
const npmDownloads = await getNpmDownloads(plugin);
qualityIndicators[plugin.name] = {
lastPublishedDate: npmData.lastPublishedDate,
npmDownloads,
githubStars: nxGithubStars,
};
}
for (let i = 0; i < plugins.length; i++) {
const plugin = plugins[i];
console.log(`Fetching data for ${plugin.name}`);
const npmData = await getNpmData(plugin);
const npmDownloads = await getNpmDownloads(plugin);
const githubStars = await getGithubStars(npmData.githubRepo);
qualityIndicators[plugin.name] = {
lastPublishedDate: npmData.lastPublishedDate,
npmDownloads,
githubStars,
nxVersion: npmData.nxVersion,
};
}
writeFileSync(
'./nx-dev/nx-dev/pages/extending-nx/quality-indicators.json',
JSON.stringify(qualityIndicators, null, 2)
);
}
main();
// Publish date (and github directory, readme content)
// i.e. https://registry.npmjs.org/@nxkit/playwright
async function getNpmData(plugin: PluginRegistry, skipNxVersion = false) {
try {
const { data } = await axios.get(
`https://registry.npmjs.org/${plugin.name}`
);
const lastPublishedDate = data.time[data['dist-tags'].latest];
const nxVersion = skipNxVersion || (await getNxVersion(data));
if (!data.repository) {
console.warn('- No repository defined in package.json!');
return { lastPublishedDate, nxVersion, githubRepo: '' };
}
const url: String = data.repository.url;
const githubRepo = url
.slice(url.indexOf('github.com/') + 11)
.replace('.git', '');
return {
lastPublishedDate,
githubRepo,
nxVersion,
// readmeContent: plugin.name
};
} catch (ex) {
return { lastPublishedDate: '', githubRepo: '' };
}
}
// Download count
// i.e. https://api.npmjs.org/downloads/point/2023-06-01:2023-07-01/@nxkit/playwright
async function getNpmDownloads(plugin: PluginRegistry) {
const lastMonth = getLastMonth();
try {
const { data } = await axios.get(
`https://api.npmjs.org/downloads/point/${stringifyIntervalForUrl(
lastMonth
)}/${plugin.name}`
);
return data.downloads;
} catch (ex) {
return '';
}
}
export function getLastMonth() {
const now = new Date();
const oneMonthAgo = new Date();
oneMonthAgo.setMonth(now.getMonth() - 1);
return {
start: oneMonthAgo,
end: now,
};
}
export function stringifyIntervalForUrl(interval: Interval): string {
return `${stringifyDate(interval.start)}:${stringifyDate(interval.end)}`;
}
export function stringifyDate(date: Date) {
// yyyy-MM-dd
return date.toISOString().slice(0, 10);
}
// Stars
// i.e. https://api.github.com/repos/nxkit/nxkit
async function getGithubStars(repo: String) {
try {
const { data } = await axios.get(`https://api.github.com/repos/${repo}`, {
headers: {
Authorization: `Bearer ${process.env.GITHUB_PAT}`,
},
});
return data.stargazers_count;
} catch (ex) {
console.warn('- Could not load GitHub stars!');
return -1;
}
}
async function getNxVersion(data: any) {
const latest = data['dist-tags'].latest;
const nxPackages = [
'@nx/devkit',
'@nrwl/devkit',
'@nx/workspace',
'@nrwl/workspace',
];
let devkitVersion = '';
for (let i = 0; i < nxPackages.length && !devkitVersion; i++) {
const packageName = nxPackages[i];
if (data.versions[latest]?.dependencies) {
devkitVersion = data.versions[latest]?.dependencies[packageName];
if (devkitVersion) {
return await findNxRange(packageName, devkitVersion);
}
}
if (!devkitVersion && data.versions[latest]?.peerDependencies) {
devkitVersion = data.versions[latest]?.peerDependencies[packageName];
if (devkitVersion) {
return await findNxRange(packageName, devkitVersion);
}
}
}
console.warn('- No dependency on @nx/devkit!');
return devkitVersion;
}
async function findNxRange(packageName: string, devkitVersion: string) {
devkitVersion = devkitVersion
.replace('^', '')
.replace('>=', '')
.replace('>', '');
const lookupPackage = packageName.includes('@nx')
? '@nx/devkit'
: '@nrwl/devkit';
const { data: devkitData } = await axios.get(
`https://registry.npmjs.org/${lookupPackage}`
);
if (!devkitData.versions[devkitVersion]?.peerDependencies) {
const dependencies = devkitData.versions[devkitVersion]?.dependencies;
return dependencies && (dependencies?.nx || dependencies['@nrwl/tao']);
}
return devkitData.versions[devkitVersion]?.peerDependencies.nx;
}