mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-02-21 07:29:37 +01:00
chore: website metrics (#5041)
* metrics charts example * metrics charts example * metrics charts example * Update npmjs_downloads.json
This commit is contained in:
parent
4b16eb2c35
commit
c5e174cdc5
@ -13,7 +13,10 @@
|
||||
]
|
||||
],
|
||||
"ignoredPackages": [
|
||||
"docusaurus-plugin-downloads",
|
||||
"docusaurus-plugin-contributors",
|
||||
"@verdaccio/test-cli-commons",
|
||||
"@verdaccio/local-scripts",
|
||||
"@verdaccio/e2e-cli-npm6",
|
||||
"@verdaccio/e2e-cli-npm7",
|
||||
"@verdaccio/e2e-cli-npm8",
|
||||
|
@ -49,7 +49,7 @@
|
||||
"generator-verdaccio-plugin": "5.0.0",
|
||||
"@verdaccio/test-helper": "3.0.0",
|
||||
"@verdaccio/local-publish": "0.0.2",
|
||||
"@verdaccio/crowdin-translations": "1.0.0",
|
||||
"@verdaccio/local-scripts": "1.0.0",
|
||||
"customprefix-auth": "2.0.0",
|
||||
"@verdaccio/ui-components": "3.0.0",
|
||||
"@verdaccio/utils": "7.0.0",
|
||||
|
10
.github/workflows/static-data.yml
vendored
10
.github/workflows/static-data.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
# pull_request:
|
||||
schedule:
|
||||
# twice peer week
|
||||
- cron: '0 0 * * 1,4'
|
||||
- cron: '0 0 * * 1,3,5,7'
|
||||
# for now, scheduled, we can enable on push master but not make much sense now
|
||||
# push:
|
||||
# branches:
|
||||
@ -29,8 +29,12 @@ jobs:
|
||||
uses: ./.github/actions/install-app
|
||||
with:
|
||||
reporter: 'default'
|
||||
- name: Build Translations percentage
|
||||
run: pnpm --filter @verdaccio/crowdin-translations build
|
||||
- name: Get Translations percentage
|
||||
run: pnpm --filter @verdaccio/local-scripts run translations
|
||||
- name: Get npmjs downloads
|
||||
run: pnpm --filter @verdaccio/local-scripts run downloads:npmjs
|
||||
- name: Get docker downloads
|
||||
run: pnpm --filter @verdaccio/local-scripts run pull:docker
|
||||
- name: update contributors
|
||||
run: pnpm run contributors
|
||||
env:
|
||||
|
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
- name: Build Translations percentage
|
||||
run: pnpm --filter @verdaccio/crowdin-translations build
|
||||
run: pnpm --filter @verdaccio/local-scripts build
|
||||
- name: Cache Docusaurus Build
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
with:
|
||||
|
@ -84,7 +84,7 @@
|
||||
"@types/yeoman-test": "4.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "6.21.0",
|
||||
"@typescript-eslint/parser": "6.21.0",
|
||||
"@verdaccio/crowdin-translations": "workspace:*",
|
||||
"@verdaccio/local-scripts": "workspace:*",
|
||||
"@verdaccio/eslint-config": "workspace:*",
|
||||
"@verdaccio/types": "workspace:*",
|
||||
"@verdaccio/ui-theme": "workspace:*",
|
||||
@ -116,6 +116,7 @@
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.3.3",
|
||||
"undici-types": "5.28.2",
|
||||
"semver": "^7.6.3",
|
||||
"update-ts-references": "3.4.0",
|
||||
"verdaccio-audit": "workspace:*",
|
||||
"verdaccio-auth-memory": "workspace:*",
|
||||
|
@ -9,8 +9,8 @@
|
||||
"@docusaurus/utils": "2.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
|
31
packages/tools/docusaurus-plugin-downloads/package.json
Normal file
31
packages/tools/docusaurus-plugin-downloads/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "docusaurus-plugin-downloads",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"main": "./build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"dependencies": {
|
||||
"@docusaurus/types": "2.4.3",
|
||||
"@docusaurus/utils": "2.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
"build": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
5436
packages/tools/docusaurus-plugin-downloads/src/downloads.json
Normal file
5436
packages/tools/docusaurus-plugin-downloads/src/downloads.json
Normal file
File diff suppressed because it is too large
Load Diff
50
packages/tools/docusaurus-plugin-downloads/src/index.ts
Normal file
50
packages/tools/docusaurus-plugin-downloads/src/index.ts
Normal file
@ -0,0 +1,50 @@
|
||||
/* eslint-disable no-console */
|
||||
import { LoadContext, Plugin } from '@docusaurus/types';
|
||||
import { normalizeUrl } from '@docusaurus/utils';
|
||||
|
||||
export interface PluginOptions {
|
||||
debug?: boolean;
|
||||
pathFileName?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_OPTIONS: PluginOptions = {
|
||||
debug: false,
|
||||
};
|
||||
|
||||
export default function downloadsPlugin(
|
||||
context: LoadContext,
|
||||
opts: PluginOptions
|
||||
): Plugin<Record<string, unknown> | null> {
|
||||
const { baseUrl } = context.siteConfig;
|
||||
const options: PluginOptions = { ...DEFAULT_OPTIONS, ...opts };
|
||||
const { debug = true } = options;
|
||||
if (debug) {
|
||||
console.log('[DOWNLOADS_PLUGIN] Opts Input:', opts);
|
||||
console.log('[DOWNLOADS_PLUGIN] Options:', options);
|
||||
}
|
||||
return {
|
||||
name: 'docusaurus-plugin-downloads',
|
||||
async loadContent() {
|
||||
return {};
|
||||
},
|
||||
async contentLoaded({ content, actions }) {
|
||||
const { addRoute } = actions;
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
const routeOptions = {
|
||||
path: normalizeUrl([baseUrl, 'downloads']),
|
||||
component: '@site/src/components/Downloads.tsx',
|
||||
modules: {
|
||||
data: [],
|
||||
},
|
||||
exact: true,
|
||||
};
|
||||
if (debug) {
|
||||
console.error('[DOWNLOADS_PLUGIN] Route:', routeOptions);
|
||||
}
|
||||
// @ts-ignore
|
||||
addRoute(routeOptions);
|
||||
},
|
||||
};
|
||||
}
|
9
packages/tools/docusaurus-plugin-downloads/tsconfig.json
Normal file
9
packages/tools/docusaurus-plugin-downloads/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.reference.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./build"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
3
packages/tools/local-scripts/.babelrc
Normal file
3
packages/tools/local-scripts/.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../../.babelrc"
|
||||
}
|
1
packages/tools/local-scripts/index.js
Executable file
1
packages/tools/local-scripts/index.js
Executable file
@ -0,0 +1 @@
|
||||
require('./build/run.js');
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@verdaccio/crowdin-translations",
|
||||
"name": "@verdaccio/local-scripts",
|
||||
"version": "1.0.0",
|
||||
"bin": {
|
||||
"local-crowdin-api": "./index.js"
|
||||
@ -9,16 +9,18 @@
|
||||
"main": "./build/index.js",
|
||||
"scripts": {
|
||||
"build": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
||||
"start": "ts-node src/index.ts"
|
||||
"start": "node build/index.js",
|
||||
"translations": "node build/run.js translations",
|
||||
"downloads:npmjs": "node build/run.js npmjs-api-download",
|
||||
"pull:docker": "node build/run.js docker-pull-api-download"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Juan Picado <juanpicado19@gmail.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@crowdin/crowdin-api-client": "^1.41.0",
|
||||
"clipanion": "4.0.0-rc.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@crowdin/crowdin-api-client": "^1.41.0",
|
||||
"clipanion": "4.0.0-rc.4",
|
||||
"got": "11.8.6",
|
||||
"ts-node": "10.9.2"
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
import { Command } from 'clipanion';
|
||||
|
||||
import runApi from './run';
|
||||
import { dockerPullWeekly } from './utils';
|
||||
|
||||
export class ApiCommand extends Command {
|
||||
public static paths = [['translations']];
|
||||
export class DockerPullCommand extends Command {
|
||||
public static paths = [['docker-pull-api-download']];
|
||||
|
||||
public async execute() {
|
||||
try {
|
||||
await runApi();
|
||||
await dockerPullWeekly();
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
@ -0,0 +1,17 @@
|
||||
import { Command } from 'clipanion';
|
||||
|
||||
import { fetchNpmjsApiDownloadsWeekly } from './utils';
|
||||
|
||||
export class NpmjsApiDownloadCommand extends Command {
|
||||
public static paths = [['npmjs-api-download']];
|
||||
|
||||
public async execute() {
|
||||
try {
|
||||
await fetchNpmjsApiDownloadsWeekly();
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
21
packages/tools/local-scripts/src/api/translationsCommand.ts
Normal file
21
packages/tools/local-scripts/src/api/translationsCommand.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Command } from 'clipanion';
|
||||
|
||||
import { fetchTranslationsAPI } from './utils';
|
||||
|
||||
export class TranslationsApiCommand extends Command {
|
||||
public static paths = [['translations']];
|
||||
|
||||
public async execute() {
|
||||
try {
|
||||
// fetch translations api and write to file
|
||||
await fetchTranslationsAPI();
|
||||
// fetch npmjs downloads api and write to file
|
||||
|
||||
// fetch docker downloads api and write to file
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
99
packages/tools/local-scripts/src/api/utils.ts
Normal file
99
packages/tools/local-scripts/src/api/utils.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import { Credentials, TranslationStatus } from '@crowdin/crowdin-api-client';
|
||||
import fs from 'fs/promises';
|
||||
import got from 'got';
|
||||
import path from 'path';
|
||||
|
||||
const debug = require('debug')('verdaccio:local-scripts');
|
||||
|
||||
const token = process.env.TOKEN || '';
|
||||
|
||||
const getISODateOnly = () => {
|
||||
const now = new Date();
|
||||
return now.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
export async function fetchNpmjsApiDownloadsWeekly() {
|
||||
try {
|
||||
const npmjsFile = path.join(__dirname, '../../src/npmjs_downloads.json');
|
||||
const currentDate = getISODateOnly();
|
||||
debug('current date %s', currentDate);
|
||||
const npmjsDownloads = JSON.parse(await fs.readFile(npmjsFile, 'utf8'));
|
||||
if (npmjsDownloads[currentDate]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info('already fetched for today');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await got('https://api.npmjs.org/versions/verdaccio/last-week', {
|
||||
responseType: 'json',
|
||||
});
|
||||
|
||||
npmjsDownloads[currentDate] = response.body.downloads;
|
||||
|
||||
await fs.writeFile(npmjsFile, npmjsDownloads);
|
||||
debug('npmjs downloads written at %s ends', npmjsFile);
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`error on process npmjs downloads run`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export async function dockerPullWeekly() {
|
||||
try {
|
||||
const npmjsFile = path.join(__dirname, '../../src/docker_pull.json');
|
||||
const currentDate = getISODateOnly();
|
||||
debug('current date %s', currentDate);
|
||||
const pullCounts = JSON.parse(await fs.readFile(npmjsFile, 'utf8'));
|
||||
|
||||
const response = await got(
|
||||
'https://hub.docker.com/api/publisher/proxylytics/v1/repos/pulls?repos=verdaccio/verdaccio',
|
||||
{
|
||||
responseType: 'json',
|
||||
}
|
||||
);
|
||||
const currentPulls = response.body.repos['verdaccio/verdaccio'].pulls;
|
||||
currentPulls.forEach(({ end, pullCount, ipCount }) => {
|
||||
if (pullCounts[end]) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info(`docker ${end} already fetched`);
|
||||
return;
|
||||
}
|
||||
pullCounts[end] = {
|
||||
pullCount,
|
||||
ipCount,
|
||||
};
|
||||
});
|
||||
await fs.writeFile(npmjsFile, JSON.stringify(pullCounts, null, 4));
|
||||
debug('npmjs downloads written at %s ends', npmjsFile);
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`error on process npmjs downloads run`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchTranslationsAPI() {
|
||||
try {
|
||||
debug('api report start');
|
||||
const credentials: Credentials = {
|
||||
token,
|
||||
};
|
||||
const api: TranslationStatus = new TranslationStatus(credentials);
|
||||
const progress = await api.getProjectProgress(295539, { limit: 100 });
|
||||
const final = progress.data.reduce((acc, item) => {
|
||||
const { languageId, translationProgress, approvalProgress } = item.data;
|
||||
// @ts-ignore
|
||||
acc[languageId] = { translationProgress, approvalProgress };
|
||||
return acc;
|
||||
}, {});
|
||||
const location = path.join(__dirname, '../../src/progress_lang.json');
|
||||
await fs.writeFile(location, JSON.stringify(final, null, 4));
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('translations written at %s ends', location);
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`error on process crowdin translations run`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
38
packages/tools/local-scripts/src/docker_pull.json
Normal file
38
packages/tools/local-scripts/src/docker_pull.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"2024-11-03T00:00:00Z": {
|
||||
"pullCount": 151846,
|
||||
"ipCount": 5452
|
||||
},
|
||||
"2024-11-10T00:00:00Z": {
|
||||
"pullCount": 146828,
|
||||
"ipCount": 5487
|
||||
},
|
||||
"2024-11-17T00:00:00Z": {
|
||||
"pullCount": 152911,
|
||||
"ipCount": 5372
|
||||
},
|
||||
"2024-11-24T00:00:00Z": {
|
||||
"pullCount": 117793,
|
||||
"ipCount": 5612
|
||||
},
|
||||
"2024-12-01T00:00:00Z": {
|
||||
"pullCount": 90029,
|
||||
"ipCount": 5302
|
||||
},
|
||||
"2024-12-08T00:00:00Z": {
|
||||
"pullCount": 70264,
|
||||
"ipCount": 5341
|
||||
},
|
||||
"2024-12-15T00:00:00Z": {
|
||||
"pullCount": 77951,
|
||||
"ipCount": 5581
|
||||
},
|
||||
"2024-12-22T00:00:00Z": {
|
||||
"pullCount": 77626,
|
||||
"ipCount": 5526
|
||||
},
|
||||
"2024-12-29T00:00:00Z": {
|
||||
"pullCount": 56060,
|
||||
"ipCount": 4335
|
||||
}
|
||||
}
|
6
packages/tools/local-scripts/src/index.ts
Normal file
6
packages/tools/local-scripts/src/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
const data = require('./progress_lang.json');
|
||||
const translationsData = data;
|
||||
const npmjsDownloads = require('./npmjs_downloads.json');
|
||||
const dockerPulls = require('./docker_pull.json');
|
||||
|
||||
export { data, npmjsDownloads, dockerPulls, translationsData };
|
216
packages/tools/local-scripts/src/npmjs_downloads.json
Normal file
216
packages/tools/local-scripts/src/npmjs_downloads.json
Normal file
@ -0,0 +1,216 @@
|
||||
{
|
||||
"2025-01-04": {
|
||||
"6.0.0-6-next.67": 122,
|
||||
"5.2.0": 4,
|
||||
"5.5.2": 83,
|
||||
"6.0.0-6-next.47": 1,
|
||||
"5.1.6": 195,
|
||||
"5.3.0": 3,
|
||||
"2.6.4": 1,
|
||||
"5.27.1": 21,
|
||||
"3.11.1": 2,
|
||||
"2.2.0": 4,
|
||||
"3.6.0": 1,
|
||||
"6.0.3": 15,
|
||||
"6.0.0-beta.1": 1792,
|
||||
"6.0.4": 313,
|
||||
"2.3.5": 3,
|
||||
"4.13.0": 8,
|
||||
"5.16.3": 2457,
|
||||
"5.10.2": 15,
|
||||
"2.3.3": 1,
|
||||
"6.0.0-6-next.31": 3,
|
||||
"5.29.1": 95,
|
||||
"5.5.0": 4,
|
||||
"5.15.3": 122,
|
||||
"5.4.0": 51,
|
||||
"3.10.0": 1,
|
||||
"3.5.1": 1,
|
||||
"5.30.3": 3260,
|
||||
"3.0.0-beta.5": 1,
|
||||
"6.0.0-6-next.76": 6163,
|
||||
"5.13.3": 365,
|
||||
"5.26.1": 147,
|
||||
"5.12.0": 1,
|
||||
"5.18.0": 296,
|
||||
"5.32.1": 6158,
|
||||
"2.1.6": 2,
|
||||
"5.24.1": 141,
|
||||
"5.29.2": 435,
|
||||
"5.1.1": 202,
|
||||
"5.7.1": 11,
|
||||
"5.19.1": 66,
|
||||
"4.3.3": 11,
|
||||
"4.9.0": 4,
|
||||
"5.20.1": 682,
|
||||
"5.0.4": 1051,
|
||||
"5.13.0": 546,
|
||||
"8.0.0-next-8.3": 1,
|
||||
"4.6.2": 58,
|
||||
"3.7.0": 4,
|
||||
"3.8.6": 2,
|
||||
"3.8.0": 1,
|
||||
"5.7.0": 9,
|
||||
"5.3.2": 4,
|
||||
"2.1.7": 1,
|
||||
"5.1.2": 8634,
|
||||
"6.0.0-6-next.49": 4,
|
||||
"5.22.1": 114,
|
||||
"2.3.4": 2,
|
||||
"5.21.2": 73,
|
||||
"6.0.0-rc.1": 1,
|
||||
"4.0.4": 5,
|
||||
"4.0.0-alpha.0": 3,
|
||||
"5.32.2": 9963,
|
||||
"0.1.7": 277,
|
||||
"2.1.4": 1,
|
||||
"2.6.0": 4,
|
||||
"5.28.0": 7,
|
||||
"8.0.0-next-8.6": 4,
|
||||
"5.10.0": 1,
|
||||
"2.7.0": 4,
|
||||
"3.10.2": 3,
|
||||
"5.29.0": 1617,
|
||||
"3.8.3": 1,
|
||||
"6.0.5": 7320,
|
||||
"5.11.0": 30,
|
||||
"4.11.0": 263,
|
||||
"5.9.0": 85,
|
||||
"5.1.4": 3,
|
||||
"5.26.2": 697,
|
||||
"4.8.1": 95,
|
||||
"4.12.0": 30,
|
||||
"4.6.1": 9,
|
||||
"3.0.0": 2,
|
||||
"4.5.1": 305,
|
||||
"3.11.2": 1,
|
||||
"2.2.5": 1,
|
||||
"4.2.1": 2,
|
||||
"3.12.0": 17,
|
||||
"4.7.2": 4,
|
||||
"5.2.2": 45,
|
||||
"4.9.1": 3,
|
||||
"5.30.0": 14,
|
||||
"5.15.4": 140,
|
||||
"3.11.3": 2,
|
||||
"3.11.6": 2,
|
||||
"6.0.2": 3310,
|
||||
"5.33.0": 13649,
|
||||
"5.23.2": 1128,
|
||||
"5.8.0": 14,
|
||||
"7.0.0-next-7.16": 1,
|
||||
"4.3.4": 4,
|
||||
"5.27.0": 281,
|
||||
"5.14.0": 544,
|
||||
"4.12.2": 812,
|
||||
"4.0.0": 14,
|
||||
"3.0.0-beta.9": 1,
|
||||
"5.6.0": 3,
|
||||
"5.21.1": 1853,
|
||||
"2.6.3": 1,
|
||||
"5.30.2": 269,
|
||||
"6.0.0": 24953,
|
||||
"7.0.0-next-8.21": 1,
|
||||
"5.0.0": 27,
|
||||
"6.0.0-6-next.25": 1,
|
||||
"3.13.1": 4,
|
||||
"5.26.3": 673,
|
||||
"4.10.0": 3,
|
||||
"6.0.1": 484,
|
||||
"5.15.2": 7,
|
||||
"3.8.1": 2,
|
||||
"8.0.0-next-8.7": 9,
|
||||
"4.7.0": 2,
|
||||
"3.11.0": 2,
|
||||
"6.0.0-6-next.24": 3,
|
||||
"3.8.2": 1,
|
||||
"7.0.0-next.3": 2,
|
||||
"2.2.2": 1,
|
||||
"2.1.3": 1,
|
||||
"5.21.0": 1,
|
||||
"7.0.0-next-7.17": 1,
|
||||
"4.11.3": 1,
|
||||
"8.0.0-next-8.4": 2,
|
||||
"2.7.4": 2,
|
||||
"2.5.0": 2,
|
||||
"8.0.0-next-8.5": 2,
|
||||
"5.32.0": 119,
|
||||
"3.0.0-alpha.7": 1,
|
||||
"4.11.1": 2,
|
||||
"3.1.1": 1,
|
||||
"5.10.1": 2,
|
||||
"5.17.0": 14,
|
||||
"3.11.7": 1,
|
||||
"4.3.5": 14,
|
||||
"3.0.1": 2,
|
||||
"3.2.0": 1,
|
||||
"4.0.3": 6,
|
||||
"3.3.0": 1,
|
||||
"4.3.1": 1,
|
||||
"2.3.6": 2,
|
||||
"5.2.1": 1,
|
||||
"4.13.2": 3767,
|
||||
"5.3.1": 7,
|
||||
"5.31.0": 2047,
|
||||
"5.5.1": 1,
|
||||
"2.7.1": 1,
|
||||
"5.19.0": 1,
|
||||
"4.11.2": 1,
|
||||
"3.1.0": 1,
|
||||
"5.13.1": 1,
|
||||
"6.0.0-6-next.41": 1,
|
||||
"4.4.1": 1,
|
||||
"4.4.3": 2,
|
||||
"4.0.0-beta.4": 1,
|
||||
"3.0.0-test.1": 1,
|
||||
"2.7.2": 1,
|
||||
"5.31.1": 8657,
|
||||
"4.1.0": 3,
|
||||
"5.25.0": 9484,
|
||||
"5.22.0": 1,
|
||||
"6.0.0-6-next.37": 2,
|
||||
"2.7.3": 2,
|
||||
"4.4.2": 4,
|
||||
"6.0.0-6-next.42": 1,
|
||||
"6.0.0-6-next.53": 1,
|
||||
"6.0.0-6-next.46": 2,
|
||||
"8.0.0-next-8.1": 1,
|
||||
"6.0.0-6-next.22": 3,
|
||||
"4.4.0": 5,
|
||||
"3.0.0-beta.12": 2,
|
||||
"6.0.0-6-next.50": 1,
|
||||
"3.0.0-beta.7": 1,
|
||||
"5.26.0": 35,
|
||||
"7.0.0-next.2": 1,
|
||||
"4.0.0-beta.10": 2,
|
||||
"2.1.1": 2,
|
||||
"3.5.0": 1,
|
||||
"6.0.0-6-next.69": 1,
|
||||
"4.0.0-beta.2": 1,
|
||||
"3.8.4": 1,
|
||||
"4.5.0": 1,
|
||||
"3.4.0": 1,
|
||||
"7.0.0-next-7.14": 1,
|
||||
"5.24.0": 1,
|
||||
"4.3.2": 1,
|
||||
"2.2.6": 1,
|
||||
"5.0.3": 1,
|
||||
"5.23.1": 1,
|
||||
"3.4.1": 1,
|
||||
"4.0.0-beta.3": 1,
|
||||
"4.0.1": 1,
|
||||
"6.0.0-6-next.44": 1,
|
||||
"4.2.0": 1,
|
||||
"3.0.0-alpha.1": 1,
|
||||
"5.0.0-alpha.4": 3,
|
||||
"2.1.2": 1,
|
||||
"3.11.5": 1,
|
||||
"4.3.0": 1,
|
||||
"6.0.0-6-next.43": 1,
|
||||
"7.0.0-next-7.15": 1,
|
||||
"2.3.0": 1,
|
||||
"2.6.6": 1,
|
||||
"3.10.1": 1,
|
||||
"4.0.0-beta.8": 2
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import { Cli } from 'clipanion';
|
||||
|
||||
import { ApiCommand } from './api';
|
||||
import { DockerPullCommand } from './api/dockerPullCommand';
|
||||
import { NpmjsApiDownloadCommand } from './api/npmjsApiDownloadCommand';
|
||||
import { TranslationsApiCommand } from './api/translationsCommand';
|
||||
|
||||
const [node, app, ...args] = process.argv;
|
||||
|
||||
@ -10,7 +12,9 @@ const cli = new Cli({
|
||||
binaryVersion: require('../package.json').version,
|
||||
});
|
||||
|
||||
cli.register(ApiCommand);
|
||||
cli.register(TranslationsApiCommand);
|
||||
cli.register(NpmjsApiDownloadCommand);
|
||||
cli.register(DockerPullCommand);
|
||||
cli.runExit(args, Cli.defaultContext);
|
||||
|
||||
process.on('uncaughtException', function (err) {
|
||||
@ -21,7 +25,3 @@ process.on('uncaughtException', function (err) {
|
||||
);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
const data = require('./progress_lang.json');
|
||||
|
||||
export { data };
|
9
packages/tools/local-scripts/tsconfig.build.json
Normal file
9
packages/tools/local-scripts/tsconfig.build.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./build"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["src/**/*.test.ts"]
|
||||
}
|
@ -1 +0,0 @@
|
||||
require('./build/index.js');
|
@ -1,32 +0,0 @@
|
||||
import { Credentials, TranslationStatus } from '@crowdin/crowdin-api-client';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
const debug = require('debug')('verdaccio:website');
|
||||
|
||||
const token = process.env.TOKEN || '';
|
||||
|
||||
export default async function run() {
|
||||
try {
|
||||
debug('api report start');
|
||||
const credentials: Credentials = {
|
||||
token,
|
||||
};
|
||||
const api: TranslationStatus = new TranslationStatus(credentials);
|
||||
const progress = await api.getProjectProgress(295539, { limit: 100 });
|
||||
const final = progress.data.reduce((acc, item) => {
|
||||
const { languageId, translationProgress, approvalProgress } = item.data;
|
||||
// @ts-ignore
|
||||
acc[languageId] = { translationProgress, approvalProgress };
|
||||
return acc;
|
||||
}, {});
|
||||
const location = path.join(__dirname, '../../src/progress_lang.json');
|
||||
fs.writeFile(location, JSON.stringify(final, null, 4));
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('translations written at %s ends', location);
|
||||
} catch (err: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`error on process crowdin translations run`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
207
pnpm-lock.yaml
generated
207
pnpm-lock.yaml
generated
@ -215,12 +215,12 @@ importers:
|
||||
'@typescript-eslint/parser':
|
||||
specifier: 6.21.0
|
||||
version: 6.21.0(eslint@8.57.1)(typescript@5.3.3)
|
||||
'@verdaccio/crowdin-translations':
|
||||
specifier: workspace:*
|
||||
version: link:packages/tools/translations
|
||||
'@verdaccio/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:packages/tools/eslint
|
||||
'@verdaccio/local-scripts':
|
||||
specifier: workspace:*
|
||||
version: link:packages/tools/local-scripts
|
||||
'@verdaccio/types':
|
||||
specifier: workspace:*
|
||||
version: link:packages/core/types
|
||||
@ -299,6 +299,9 @@ importers:
|
||||
selfsigned:
|
||||
specifier: 2.4.1
|
||||
version: 2.4.1
|
||||
semver:
|
||||
specifier: ^7.6.3
|
||||
version: 7.6.3
|
||||
supertest:
|
||||
specifier: 7.0.0
|
||||
version: 7.0.0
|
||||
@ -1731,17 +1734,33 @@ importers:
|
||||
dependencies:
|
||||
'@docusaurus/types':
|
||||
specifier: 2.4.3
|
||||
version: 2.4.3(react-dom@17.0.2)(react@17.0.2)
|
||||
version: 2.4.3(react-dom@18.3.1)(react@18.3.1)
|
||||
'@docusaurus/utils':
|
||||
specifier: 2.4.3
|
||||
version: 2.4.3(@docusaurus/types@2.4.3)
|
||||
devDependencies:
|
||||
react:
|
||||
specifier: 17.0.2
|
||||
version: 17.0.2
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1
|
||||
react-dom:
|
||||
specifier: 17.0.2
|
||||
version: 17.0.2(react@17.0.2)
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1(react@18.3.1)
|
||||
|
||||
packages/tools/docusaurus-plugin-downloads:
|
||||
dependencies:
|
||||
'@docusaurus/types':
|
||||
specifier: 2.4.3
|
||||
version: 2.4.3(react-dom@18.3.1)(react@18.3.1)
|
||||
'@docusaurus/utils':
|
||||
specifier: 2.4.3
|
||||
version: 2.4.3(@docusaurus/types@2.4.3)
|
||||
devDependencies:
|
||||
react:
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1
|
||||
react-dom:
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1(react@18.3.1)
|
||||
|
||||
packages/tools/eslint:
|
||||
dependencies:
|
||||
@ -1876,15 +1895,17 @@ importers:
|
||||
specifier: 8.0.0-next-8.7
|
||||
version: link:../../verdaccio
|
||||
|
||||
packages/tools/translations:
|
||||
dependencies:
|
||||
packages/tools/local-scripts:
|
||||
devDependencies:
|
||||
'@crowdin/crowdin-api-client':
|
||||
specifier: ^1.41.0
|
||||
version: 1.41.0(debug@4.4.0)
|
||||
clipanion:
|
||||
specifier: 4.0.0-rc.4
|
||||
version: 4.0.0-rc.4(typanion@3.14.0)
|
||||
devDependencies:
|
||||
got:
|
||||
specifier: 11.8.6
|
||||
version: 11.8.6
|
||||
ts-node:
|
||||
specifier: 10.9.2
|
||||
version: 10.9.2(@types/node@20.14.12)(typescript@5.3.3)
|
||||
@ -2292,6 +2313,9 @@ importers:
|
||||
'@verdaccio/ui-components':
|
||||
specifier: workspace:4.0.0-next-8.4
|
||||
version: link:../packages/ui-components
|
||||
chart.js:
|
||||
specifier: ^4.4.7
|
||||
version: 4.4.7
|
||||
classnames:
|
||||
specifier: 2.5.1
|
||||
version: 2.5.1
|
||||
@ -2302,8 +2326,11 @@ importers:
|
||||
specifier: 3.2.0
|
||||
version: 3.2.0
|
||||
docusaurus-plugin-contributors:
|
||||
specifier: workspace:2.0.0
|
||||
specifier: workspace:*
|
||||
version: link:../packages/tools/docusaurus-plugin-contributors
|
||||
docusaurus-plugin-downloads:
|
||||
specifier: workspace:*
|
||||
version: link:../packages/tools/docusaurus-plugin-downloads
|
||||
dompurify:
|
||||
specifier: 3.2.3
|
||||
version: 3.2.3
|
||||
@ -2313,6 +2340,9 @@ importers:
|
||||
react:
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1
|
||||
react-chartjs-2:
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0(chart.js@4.4.7)(react@18.3.1)
|
||||
react-dom:
|
||||
specifier: 18.3.1
|
||||
version: 18.3.1(react@18.3.1)
|
||||
@ -2338,9 +2368,9 @@ importers:
|
||||
'@tsconfig/docusaurus':
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3
|
||||
'@verdaccio/crowdin-translations':
|
||||
'@verdaccio/local-scripts':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/tools/translations
|
||||
version: link:../packages/tools/local-scripts
|
||||
docusaurus-plugin-sass:
|
||||
specifier: ^0.2.6
|
||||
version: 0.2.6(@docusaurus/core@3.6.3)(sass@1.83.0)(webpack@5.97.1)
|
||||
@ -5003,7 +5033,7 @@ packages:
|
||||
axios: 1.3.6(debug@4.4.0)
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
dev: true
|
||||
|
||||
/@cspotcode/source-map-support@0.8.1:
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
@ -6432,19 +6462,19 @@ packages:
|
||||
tslib: 2.6.3
|
||||
dev: false
|
||||
|
||||
/@docusaurus/types@2.4.3(react-dom@17.0.2)(react@17.0.2):
|
||||
/@docusaurus/types@2.4.3(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-W6zNLGQqfrp/EoPD0bhb9n7OobP+RHpmvVzpA+Z/IuU3Q63njJM24hmT0GYboovWcDtFmnIJC9wcyx4RVPQscw==}
|
||||
peerDependencies:
|
||||
react: ^16.8.4 || ^17.0.0
|
||||
react-dom: ^16.8.4 || ^17.0.0
|
||||
dependencies:
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.2.46
|
||||
'@types/react': 18.3.3
|
||||
commander: 5.1.0
|
||||
joi: 17.9.1
|
||||
react: 17.0.2
|
||||
react-dom: 17.0.2(react@17.0.2)
|
||||
react-helmet-async: 1.3.0(react-dom@17.0.2)(react@17.0.2)
|
||||
joi: 17.13.3
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-helmet-async: 1.3.0(react-dom@18.3.1)(react@18.3.1)
|
||||
utility-types: 3.10.0
|
||||
webpack: 5.97.1(webpack-cli@4.10.0)
|
||||
webpack-merge: 5.10.0
|
||||
@ -6528,7 +6558,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@docusaurus/logger': 2.4.3
|
||||
'@docusaurus/types': 2.4.3(react-dom@17.0.2)(react@17.0.2)
|
||||
'@docusaurus/types': 2.4.3(react-dom@18.3.1)(react@18.3.1)
|
||||
'@svgr/webpack': 6.5.1
|
||||
escape-string-regexp: 4.0.0
|
||||
file-loader: 6.2.0(webpack@5.97.1)
|
||||
@ -6538,10 +6568,10 @@ packages:
|
||||
gray-matter: 4.0.3
|
||||
js-yaml: 4.1.0
|
||||
lodash: 4.17.21
|
||||
micromatch: 4.0.5
|
||||
micromatch: 4.0.8
|
||||
resolve-pathname: 3.0.0
|
||||
shelljs: 0.8.5
|
||||
tslib: 2.6.2
|
||||
tslib: 2.6.3
|
||||
url-loader: 4.1.1(file-loader@6.2.0)(webpack@5.97.1)
|
||||
webpack: 5.97.1(webpack-cli@4.10.0)
|
||||
transitivePeerDependencies:
|
||||
@ -7768,6 +7798,10 @@ packages:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
dev: true
|
||||
|
||||
/@kurkle/color@0.3.4:
|
||||
resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==}
|
||||
dev: false
|
||||
|
||||
/@leichtgewicht/ip-codec@2.0.4:
|
||||
resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==}
|
||||
|
||||
@ -9210,12 +9244,6 @@ packages:
|
||||
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
|
||||
dev: false
|
||||
|
||||
/@sideway/address@4.1.4:
|
||||
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
|
||||
dependencies:
|
||||
'@hapi/hoek': 9.3.0
|
||||
dev: false
|
||||
|
||||
/@sideway/address@4.1.5:
|
||||
resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==}
|
||||
dependencies:
|
||||
@ -11221,7 +11249,7 @@ packages:
|
||||
/@types/cacheable-request@6.0.3:
|
||||
resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==}
|
||||
dependencies:
|
||||
'@types/http-cache-semantics': 4.0.1
|
||||
'@types/http-cache-semantics': 4.0.4
|
||||
'@types/keyv': 3.1.4
|
||||
'@types/node': 20.14.12
|
||||
'@types/responselike': 1.0.0
|
||||
@ -11548,10 +11576,6 @@ packages:
|
||||
/@types/html-minifier-terser@6.1.0:
|
||||
resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==}
|
||||
|
||||
/@types/http-cache-semantics@4.0.1:
|
||||
resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==}
|
||||
dev: true
|
||||
|
||||
/@types/http-cache-semantics@4.0.4:
|
||||
resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
|
||||
|
||||
@ -11823,14 +11847,6 @@ packages:
|
||||
'@types/scheduler': 0.16.3
|
||||
csstype: 3.1.3
|
||||
|
||||
/@types/react@18.2.46:
|
||||
resolution: {integrity: sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.11
|
||||
'@types/scheduler': 0.16.4
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@types/react@18.3.3:
|
||||
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
|
||||
dependencies:
|
||||
@ -11854,10 +11870,6 @@ packages:
|
||||
/@types/scheduler@0.16.3:
|
||||
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
|
||||
|
||||
/@types/scheduler@0.16.4:
|
||||
resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==}
|
||||
dev: false
|
||||
|
||||
/@types/semver@7.5.8:
|
||||
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
||||
|
||||
@ -12778,7 +12790,7 @@ packages:
|
||||
resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dependencies:
|
||||
acorn: 8.12.1
|
||||
acorn: 8.14.0
|
||||
|
||||
/acorn@6.4.2:
|
||||
resolution: {integrity: sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==}
|
||||
@ -13390,6 +13402,7 @@ packages:
|
||||
|
||||
/asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
dev: true
|
||||
|
||||
/at-least-node@1.0.0:
|
||||
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
|
||||
@ -13468,7 +13481,7 @@ packages:
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
dev: true
|
||||
|
||||
/axobject-query@4.1.0:
|
||||
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
|
||||
@ -14245,7 +14258,7 @@ packages:
|
||||
'@types/http-cache-semantics': 4.0.4
|
||||
get-stream: 6.0.1
|
||||
http-cache-semantics: 4.1.1
|
||||
keyv: 4.5.3
|
||||
keyv: 4.5.4
|
||||
mimic-response: 4.0.0
|
||||
normalize-url: 8.0.1
|
||||
responselike: 3.0.0
|
||||
@ -14457,6 +14470,13 @@ packages:
|
||||
/chardet@0.7.0:
|
||||
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
|
||||
|
||||
/chart.js@4.4.7:
|
||||
resolution: {integrity: sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==}
|
||||
engines: {pnpm: '>=8'}
|
||||
dependencies:
|
||||
'@kurkle/color': 0.3.4
|
||||
dev: false
|
||||
|
||||
/check-error@2.1.1:
|
||||
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
|
||||
engines: {node: '>= 16'}
|
||||
@ -14684,7 +14704,6 @@ packages:
|
||||
typanion: '*'
|
||||
dependencies:
|
||||
typanion: 3.14.0
|
||||
dev: false
|
||||
|
||||
/cliui@5.0.0:
|
||||
resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==}
|
||||
@ -14855,6 +14874,7 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
dev: true
|
||||
|
||||
/comma-separated-tokens@1.0.8:
|
||||
resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==}
|
||||
@ -16448,6 +16468,7 @@ packages:
|
||||
/delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/delegates@1.0.0:
|
||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||
@ -18201,7 +18222,7 @@ packages:
|
||||
engines: {node: '>=12.0.0'}
|
||||
dependencies:
|
||||
flatted: 3.2.9
|
||||
keyv: 4.5.3
|
||||
keyv: 4.5.4
|
||||
rimraf: 3.0.2
|
||||
|
||||
/flat@5.0.2:
|
||||
@ -18422,6 +18443,7 @@ packages:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: true
|
||||
|
||||
/format@0.2.2:
|
||||
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
|
||||
@ -18934,7 +18956,7 @@ packages:
|
||||
decompress-response: 6.0.0
|
||||
form-data-encoder: 2.1.4
|
||||
get-stream: 6.0.1
|
||||
http2-wrapper: 2.2.0
|
||||
http2-wrapper: 2.2.1
|
||||
lowercase-keys: 3.0.0
|
||||
p-cancelable: 3.0.0
|
||||
responselike: 3.0.0
|
||||
@ -19613,6 +19635,14 @@ packages:
|
||||
dependencies:
|
||||
quick-lru: 5.1.1
|
||||
resolve-alpn: 1.2.1
|
||||
dev: false
|
||||
|
||||
/http2-wrapper@2.2.1:
|
||||
resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==}
|
||||
engines: {node: '>=10.19.0'}
|
||||
dependencies:
|
||||
quick-lru: 5.1.1
|
||||
resolve-alpn: 1.2.1
|
||||
|
||||
/https-browserify@1.0.0:
|
||||
resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==}
|
||||
@ -21119,16 +21149,6 @@ packages:
|
||||
'@sideway/formula': 3.0.1
|
||||
'@sideway/pinpoint': 2.0.0
|
||||
|
||||
/joi@17.9.1:
|
||||
resolution: {integrity: sha512-FariIi9j6QODKATGBrEX7HZcja8Bsh3rfdGYy/Sb65sGlZWK/QWesU1ghk7aJWDj95knjXlQfSmzFSPPkLVsfw==}
|
||||
dependencies:
|
||||
'@hapi/hoek': 9.3.0
|
||||
'@hapi/topo': 5.1.0
|
||||
'@sideway/address': 4.1.4
|
||||
'@sideway/formula': 3.0.1
|
||||
'@sideway/pinpoint': 2.0.0
|
||||
dev: false
|
||||
|
||||
/js-base64@3.7.7:
|
||||
resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==}
|
||||
|
||||
@ -21441,6 +21461,11 @@ packages:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
||||
/keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
||||
/khroma@2.1.0:
|
||||
resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
|
||||
dev: false
|
||||
@ -22891,6 +22916,7 @@ packages:
|
||||
dependencies:
|
||||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/micromatch@4.0.7:
|
||||
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
|
||||
@ -26523,7 +26549,7 @@ packages:
|
||||
|
||||
/proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: false
|
||||
dev: true
|
||||
|
||||
/prr@1.0.1:
|
||||
resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
|
||||
@ -26728,6 +26754,16 @@ packages:
|
||||
lodash.curry: 4.1.1
|
||||
dev: false
|
||||
|
||||
/react-chartjs-2@5.2.0(chart.js@4.4.7)(react@18.3.1):
|
||||
resolution: {integrity: sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==}
|
||||
peerDependencies:
|
||||
chart.js: ^4.1.1
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
chart.js: 4.4.7
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/react-dev-utils@12.0.1(eslint@8.57.1)(typescript@5.3.3)(webpack@5.97.1):
|
||||
resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==}
|
||||
engines: {node: '>=14'}
|
||||
@ -26796,16 +26832,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/react-dom@17.0.2(react@17.0.2):
|
||||
resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==}
|
||||
peerDependencies:
|
||||
react: 17.0.2
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
react: 17.0.2
|
||||
scheduler: 0.20.2
|
||||
|
||||
/react-dom@18.3.1(react@18.3.1):
|
||||
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
|
||||
peerDependencies:
|
||||
@ -26834,21 +26860,6 @@ packages:
|
||||
/react-fast-compare@3.2.1:
|
||||
resolution: {integrity: sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg==}
|
||||
|
||||
/react-helmet-async@1.3.0(react-dom@17.0.2)(react@17.0.2):
|
||||
resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==}
|
||||
peerDependencies:
|
||||
react: ^16.6.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.0
|
||||
invariant: 2.2.4
|
||||
prop-types: 15.8.1
|
||||
react: 17.0.2
|
||||
react-dom: 17.0.2(react@17.0.2)
|
||||
react-fast-compare: 3.2.1
|
||||
shallowequal: 1.1.0
|
||||
dev: false
|
||||
|
||||
/react-helmet-async@1.3.0(react-dom@18.3.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==}
|
||||
peerDependencies:
|
||||
@ -27194,13 +27205,6 @@ packages:
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-lifecycles-compat: 3.0.4
|
||||
|
||||
/react@17.0.2:
|
||||
resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
|
||||
/react@18.3.1:
|
||||
resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -28123,12 +28127,6 @@ packages:
|
||||
xmlchars: 2.2.0
|
||||
dev: true
|
||||
|
||||
/scheduler@0.20.2:
|
||||
resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==}
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
|
||||
/scheduler@0.23.2:
|
||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
||||
dependencies:
|
||||
@ -30088,10 +30086,6 @@ packages:
|
||||
/tslib@1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
|
||||
/tslib@2.6.2:
|
||||
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
||||
dev: false
|
||||
|
||||
/tslib@2.6.3:
|
||||
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
|
||||
|
||||
@ -30136,7 +30130,6 @@ packages:
|
||||
|
||||
/typanion@3.14.0:
|
||||
resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==}
|
||||
dev: false
|
||||
|
||||
/type-check@0.3.2:
|
||||
resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// @ts-check
|
||||
|
||||
const translations = require('@verdaccio/crowdin-translations/build/progress_lang.json');
|
||||
const { translationsData } = require('@verdaccio/local-scripts');
|
||||
const translations = translationsData;
|
||||
|
||||
const lgnMapping = {
|
||||
'de-DE': 'de',
|
||||
@ -109,6 +110,7 @@ module.exports = {
|
||||
plugins: [
|
||||
'docusaurus-plugin-sass',
|
||||
'docusaurus-plugin-contributors',
|
||||
'docusaurus-plugin-downloads',
|
||||
[
|
||||
'content-docs',
|
||||
{
|
||||
@ -227,10 +229,10 @@ module.exports = {
|
||||
'aria-label': 'GitHub repository',
|
||||
},
|
||||
{
|
||||
href: 'https://fosstodon.org/@verdaccio',
|
||||
href: 'https://bsky.app/profile/verdaccio.org',
|
||||
position: 'right',
|
||||
className: 'header-mastodon-link',
|
||||
'aria-label': 'Follow us at Fosstodon',
|
||||
className: 'header-bluesky-link',
|
||||
'aria-label': 'Follow us at Bluesky',
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -271,8 +273,8 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
html: `
|
||||
<a href="https://fosstodon.org/@verdaccio" rel="me">
|
||||
Mastodon
|
||||
<a href="https://bsky.app/profile/verdaccio.org" rel="me">
|
||||
Blyesky
|
||||
</a>
|
||||
`,
|
||||
},
|
||||
@ -290,8 +292,8 @@ module.exports = {
|
||||
href: 'https://github.com/verdaccio/verdaccio',
|
||||
},
|
||||
{
|
||||
label: 'Mastodon',
|
||||
href: 'https://fosstodon.org/@verdaccio',
|
||||
label: 'Bluesky',
|
||||
href: 'https://bsky.app/profile/verdaccio.org',
|
||||
},
|
||||
{
|
||||
html: `
|
||||
|
@ -39,12 +39,15 @@
|
||||
"classnames": "2.5.1",
|
||||
"clsx": "2.1.1",
|
||||
"copy-text-to-clipboard": "3.2.0",
|
||||
"docusaurus-plugin-contributors": "workspace:2.0.0",
|
||||
"docusaurus-plugin-contributors": "workspace:*",
|
||||
"docusaurus-plugin-downloads": "workspace:*",
|
||||
"dompurify": "3.2.3",
|
||||
"p-cancelable": "4.0.1",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-iframe": "1.8.5",
|
||||
"chart.js": "^4.4.7",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-player": "2.14.1",
|
||||
"react-twitter-widgets": "^1.10.0",
|
||||
"use-is-in-viewport": "1.0.9",
|
||||
@ -65,7 +68,7 @@
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.6.3",
|
||||
"@tsconfig/docusaurus": "^2.0.3",
|
||||
"@verdaccio/crowdin-translations": "workspace:*",
|
||||
"@verdaccio/local-scripts": "workspace:*",
|
||||
"docusaurus-plugin-sass": "^0.2.6",
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"sass": "1.83.0",
|
||||
|
66
website/src/components/Chart/DockerPullChart.tsx
Normal file
66
website/src/components/Chart/DockerPullChart.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
import {
|
||||
CategoryScale,
|
||||
Chart as ChartJS,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
} from 'chart.js';
|
||||
import React from 'react';
|
||||
import { Line } from 'react-chartjs-2';
|
||||
|
||||
import { dockerPulls } from '@verdaccio/local-scripts';
|
||||
|
||||
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);
|
||||
|
||||
const DockerPullChart = () => {
|
||||
const labels = Object.keys(dockerPulls).map((date) => new Date(date).toLocaleDateString('en-US')); // Format dates for display
|
||||
const pullCounts = Object.values(dockerPulls).map((data) => data.pullCount);
|
||||
|
||||
const data = {
|
||||
labels,
|
||||
datasets: [
|
||||
{
|
||||
label: 'docker pull',
|
||||
data: pullCounts,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
tension: 0.4,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const options = {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Weekly Docker Pulls',
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Date',
|
||||
},
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Count',
|
||||
},
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return <Line data={data} options={options} />;
|
||||
};
|
||||
|
||||
export default DockerPullChart;
|
76
website/src/components/Chart/DockerTotalPull.tsx
Normal file
76
website/src/components/Chart/DockerTotalPull.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import {
|
||||
BarElement,
|
||||
CategoryScale,
|
||||
Chart as ChartJS,
|
||||
Legend,
|
||||
LinearScale,
|
||||
Title,
|
||||
Tooltip,
|
||||
} from 'chart.js';
|
||||
import React from 'react';
|
||||
import { Bar } from 'react-chartjs-2';
|
||||
|
||||
import { dockerPulls } from '@verdaccio/local-scripts';
|
||||
|
||||
ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
|
||||
|
||||
const DockerTotalPull = () => {
|
||||
const monthlyData = {};
|
||||
Object.entries(dockerPulls).forEach(([date, { pullCount }]) => {
|
||||
const d = new Date(date);
|
||||
const yearMonth = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; // Format: YYYY-MM
|
||||
if (!monthlyData[yearMonth]) {
|
||||
monthlyData[yearMonth] = 0;
|
||||
}
|
||||
monthlyData[yearMonth] += pullCount;
|
||||
});
|
||||
|
||||
// Prepare data for the chart
|
||||
const labels = Object.keys(monthlyData); // Months in YYYY-MM format
|
||||
const pullCounts = Object.values(monthlyData);
|
||||
|
||||
const data = {
|
||||
labels,
|
||||
datasets: [
|
||||
{
|
||||
label: 'Total Pulls',
|
||||
data: pullCounts, // y-axis data
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.5)',
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const options = {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Monthly Total Pulls by Year',
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Month (Year-Month)',
|
||||
},
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Total Pulls',
|
||||
},
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return <Bar data={data} options={options} />;
|
||||
};
|
||||
|
||||
export default DockerTotalPull;
|
125
website/src/components/Chart/NpmjsVersionsChart.tsx
Normal file
125
website/src/components/Chart/NpmjsVersionsChart.tsx
Normal file
@ -0,0 +1,125 @@
|
||||
import {
|
||||
CategoryScale,
|
||||
Chart as ChartJS,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
} from 'chart.js';
|
||||
import React from 'react';
|
||||
import { Line } from 'react-chartjs-2';
|
||||
|
||||
import { npmjsDownloads } from '@verdaccio/local-scripts';
|
||||
|
||||
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);
|
||||
|
||||
const processData = (data) => {
|
||||
const labels = [];
|
||||
const datasets = {};
|
||||
|
||||
Object.keys(data).forEach((date) => {
|
||||
const downloads = data[date];
|
||||
|
||||
labels.push(date);
|
||||
|
||||
Object.keys(downloads).forEach((version) => {
|
||||
if (!datasets[version]) {
|
||||
datasets[version] = {
|
||||
label: version,
|
||||
data: Array(labels.length - 1).fill(0),
|
||||
borderColor: getRandomColor(),
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: false,
|
||||
tension: 0.1,
|
||||
};
|
||||
}
|
||||
|
||||
while (datasets[version].data.length < labels.length - 1) {
|
||||
datasets[version].data.push(0);
|
||||
}
|
||||
|
||||
datasets[version].data.push(downloads[version] || 0);
|
||||
});
|
||||
});
|
||||
|
||||
Object.values(datasets).forEach((dataset) => {
|
||||
while (dataset.data.length < labels.length) {
|
||||
dataset.data.push(0);
|
||||
}
|
||||
});
|
||||
|
||||
const totalDownloads = Object.entries(datasets).map(([version, dataset]) => {
|
||||
const total = dataset.data.reduce((sum, count) => sum + count, 0);
|
||||
return { version, total };
|
||||
});
|
||||
|
||||
const groupedByMajor = {};
|
||||
totalDownloads.forEach(({ version, total }) => {
|
||||
const majorVersion = version.split('.')[0];
|
||||
if (!groupedByMajor[majorVersion]) {
|
||||
groupedByMajor[majorVersion] = [];
|
||||
}
|
||||
groupedByMajor[majorVersion].push({ version, total });
|
||||
});
|
||||
|
||||
const topVersions = [];
|
||||
Object.values(groupedByMajor).forEach((versions) => {
|
||||
versions
|
||||
.sort((a, b) => b.total - a.total)
|
||||
.slice(0, 2)
|
||||
.forEach(({ version }) => topVersions.push(version));
|
||||
});
|
||||
|
||||
const filteredDatasets = topVersions.map((version) => datasets[version]);
|
||||
filteredDatasets.sort((a, b) => semverCompare(a.label, b.label));
|
||||
return { labels, datasetArray: filteredDatasets };
|
||||
};
|
||||
|
||||
const semverCompare = (v1, v2) => {
|
||||
const parse = (v) => v.split('.').map(Number);
|
||||
const [v1Major, v1Minor, v1Patch] = parse(v1);
|
||||
const [v2Major, v2Minor, v2Patch] = parse(v2);
|
||||
|
||||
if (v1Major !== v2Major) return v1Major - v2Major;
|
||||
if (v1Minor !== v2Minor) return v1Minor - v2Minor;
|
||||
return v1Patch - v2Patch;
|
||||
};
|
||||
const getRandomColor = () => {
|
||||
const letters = '0123456789ABCDEF';
|
||||
let color = '#';
|
||||
for (let i = 0; i < 6; i++) {
|
||||
color += letters[Math.floor(Math.random() * 16)];
|
||||
}
|
||||
return color;
|
||||
};
|
||||
|
||||
const NpmjsVersionsChart = () => {
|
||||
const { labels, datasetArray } = processData(npmjsDownloads);
|
||||
const chartData = {
|
||||
labels: labels,
|
||||
datasets: datasetArray,
|
||||
};
|
||||
|
||||
const options = {
|
||||
responsive: true,
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Date',
|
||||
},
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Downloads',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return <Line data={chartData} options={options} />;
|
||||
};
|
||||
|
||||
export default NpmjsVersionsChart;
|
94
website/src/components/Chart/VersionDownloadsChart.tsx
Normal file
94
website/src/components/Chart/VersionDownloadsChart.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import { BarElement, CategoryScale, Chart as ChartJS, LinearScale, Title, Tooltip } from 'chart.js';
|
||||
import React from 'react';
|
||||
import { Bar } from 'react-chartjs-2';
|
||||
|
||||
import { npmjsDownloads } from '@verdaccio/local-scripts';
|
||||
|
||||
ChartJS.register(BarElement, CategoryScale, LinearScale, Title, Tooltip);
|
||||
|
||||
// @ts-ignore
|
||||
const dates = [...Object.keys(npmjsDownloads)].sort((a, b) => new Date(b) - new Date(a));
|
||||
const lastDate = dates[0];
|
||||
const data = npmjsDownloads[lastDate];
|
||||
|
||||
function reduceDownloads(downloads) {
|
||||
const result = {};
|
||||
Object.entries(downloads).forEach(([version, count]) => {
|
||||
if (/(alpha|beta|next)/i.test(version)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const majorVersion = version.split('.')[0];
|
||||
|
||||
result[majorVersion] = (result[majorVersion] || 0) + count;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const VersionDownloadsChart = () => {
|
||||
const processedData = reduceDownloads(data);
|
||||
|
||||
const labels = Object.keys(processedData).map((version) => `v${version}`);
|
||||
const dataPoints = Object.values(processedData);
|
||||
const chartData = {
|
||||
labels,
|
||||
datasets: [
|
||||
{
|
||||
label: 'v6',
|
||||
data: dataPoints,
|
||||
backgroundColor: [
|
||||
'rgba(75, 192, 192, 0.6)',
|
||||
'rgba(54, 162, 235, 0.6)',
|
||||
'rgba(255, 206, 86, 0.6)',
|
||||
'rgba(153, 102, 255, 0.6)',
|
||||
'rgba(255, 99, 132, 0.6)',
|
||||
],
|
||||
borderColor: [
|
||||
'rgba(75, 192, 192, 1)',
|
||||
'rgba(54, 162, 235, 1)',
|
||||
'rgba(255, 206, 86, 1)',
|
||||
'rgba(153, 102, 255, 1)',
|
||||
'rgba(255, 99, 132, 1)',
|
||||
],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const options = {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: `Downloads by Major Version ${lastDate}`,
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Version',
|
||||
},
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Downloads',
|
||||
},
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ width: '80%', margin: '0 auto' }}>
|
||||
<Bar data={chartData} options={options} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VersionDownloadsChart;
|
64
website/src/components/Downloads.tsx
Normal file
64
website/src/components/Downloads.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import Translate from '@docusaurus/Translate';
|
||||
import { createTheme } from '@mui/material/styles';
|
||||
import { ThemeProvider } from '@mui/styles';
|
||||
import { makeStyles, withStyles } from '@mui/styles';
|
||||
import Layout from '@theme/Layout';
|
||||
import React from 'react';
|
||||
|
||||
import DockerPullChart from './Chart/DockerPullChart';
|
||||
import DockerTotalPull from './Chart/DockerTotalPull';
|
||||
import NpmjsVersionsChart from './Chart/NpmjsVersionsChart';
|
||||
import VersionDownloadsChart from './Chart/VersionDownloadsChart';
|
||||
|
||||
const theme = createTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#4B5E40',
|
||||
},
|
||||
secondary: {
|
||||
main: '#808a79',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const useStyles = makeStyles(({ theme }: { theme: any }) => ({
|
||||
'@global': {},
|
||||
}));
|
||||
|
||||
const Downloads: React.FC<{}> = (): React.ReactElement => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<Layout title="Downloads" description="Verdaccio Downloads">
|
||||
<ThemeProvider theme={theme}>
|
||||
<div style={{ display: 'flex', width: '80%', flexFlow: 'wrap', margin: '1rem auto' }}>
|
||||
<header>
|
||||
<h1>
|
||||
<Translate>Download Metrics</Translate>
|
||||
</h1>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', width: '80%', flexFlow: 'wrap', margin: '1rem auto' }}>
|
||||
<div style={{ width: '80%', margin: '0 auto' }}>
|
||||
<VersionDownloadsChart />
|
||||
</div>
|
||||
|
||||
<div style={{ width: '80%', margin: '0 auto' }}>
|
||||
<DockerPullChart />
|
||||
</div>
|
||||
|
||||
<div style={{ width: '80%', margin: '0 auto' }}>
|
||||
<DockerTotalPull />
|
||||
</div>
|
||||
<div style={{ width: '80%', margin: '0 auto' }}>
|
||||
<NpmjsVersionsChart />
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Downloads;
|
Loading…
Reference in New Issue
Block a user