From f52cc75ed766e47e1d9f82fda1560e0085b3c02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Chalk?= Date: Mon, 2 Oct 2023 16:36:42 +0200 Subject: [PATCH] feat(models): validate plugin icons using portal-client package --- esbuild.config.js | 10 ++- package-lock.json | 67 +++++++++++++++++-- package.json | 1 + packages/cli/src/lib/cli.spec.ts | 6 +- .../implementation/mock/cli-config.mock.js | 1 + .../mock/config-middleware-config.mock.cjs | 2 +- .../mock/config-middleware-config.mock.mjs | 2 +- packages/core/src/lib/execute-plugin.ts | 5 +- packages/core/src/lib/index.spec.ts | 1 - packages/models/package.json | 1 + packages/models/src/lib/plugin-config.ts | 10 ++- packages/models/test/schema.mock.ts | 5 +- .../config-and-report-lighthouse.mock.ts | 1 + .../config-and-report-nx-validators.mock.ts | 1 + .../plugin-eslint/src/lib/eslint-plugin.ts | 1 + .../src/lib/lighthouse-plugin.ts | 1 + .../implementation/mock/schema-helper.mock.ts | 2 +- 17 files changed, 95 insertions(+), 22 deletions(-) diff --git a/esbuild.config.js b/esbuild.config.js index 577349170..0d7a3e5cd 100644 --- a/esbuild.config.js +++ b/esbuild.config.js @@ -12,9 +12,13 @@ esbuild.build({ build.onEnd(result => { if (result.errors.length > 0) return; - execSync( - `tsc --emitDeclarationOnly --project packages/${project}/tsconfig.lib.json --outDir dist`, - ); + try { + execSync( + `tsc --emitDeclarationOnly --project packages/${project}/tsconfig.lib.json --outDir dist`, + ); + } catch (err) { + console.error(err); + } }); }, }, diff --git a/package-lock.json b/package-lock.json index a09e4a0df..a005a7612 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { + "@code-pushup/portal-client": "^0.1.2", "bundle-require": "^4.0.1", "chalk": "^5.3.0", "cliui": "^8.0.1", @@ -1903,6 +1904,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@code-pushup/portal-client": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@code-pushup/portal-client/-/portal-client-0.1.2.tgz", + "integrity": "sha512-BND3ss33poWuIycPCrt6m3tSJf13w4HliNc0XKqnPAqLswTMwdaearFeEoBRaMJ+eFCeqOqfAraClbks0c7dqw==", + "dependencies": { + "graphql-request": "^6.1.0", + "graphql-tag": "^2.12.6", + "tslib": "^2.3.0" + } + }, "node_modules/@commitlint/cli": { "version": "17.7.1", "dev": true, @@ -2512,6 +2523,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.11", "dev": true, @@ -8609,6 +8628,49 @@ "dev": true, "license": "MIT" }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/graphql-request/node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, "node_modules/handlebars": { "version": "4.7.7", "dev": true, @@ -11523,7 +11585,6 @@ }, "node_modules/node-fetch": { "version": "2.7.0", - "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -13869,7 +13930,6 @@ }, "node_modules/tr46": { "version": "0.0.3", - "dev": true, "license": "MIT" }, "node_modules/trim-newlines": { @@ -13945,7 +14005,6 @@ }, "node_modules/tslib": { "version": "2.6.2", - "dev": true, "license": "0BSD" }, "node_modules/tsscmp": { @@ -14593,12 +14652,10 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", - "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", diff --git a/package.json b/package.json index 33e97dfb3..0150c21b1 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "node": ">=18.16" }, "dependencies": { + "@code-pushup/portal-client": "^0.1.2", "bundle-require": "^4.0.1", "chalk": "^5.3.0", "cliui": "^8.0.1", diff --git a/packages/cli/src/lib/cli.spec.ts b/packages/cli/src/lib/cli.spec.ts index 242363c85..91e2e9aa7 100644 --- a/packages/cli/src/lib/cli.spec.ts +++ b/packages/cli/src/lib/cli.spec.ts @@ -1,11 +1,11 @@ +import { CollectOptions } from '@quality-metrics/utils'; import { join } from 'path'; import { describe, expect, it } from 'vitest'; import { yargsCli } from './cli'; -import { middlewares } from './middlewares'; -import { options as defaultOptions } from './options'; -import { CollectOptions } from '@quality-metrics/core'; import { getDirname } from './implementation/helper.mock'; +import { middlewares } from './middlewares'; import { GlobalOptions } from './model'; +import { options as defaultOptions } from './options'; const __dirname = getDirname(import.meta.url); const withDirName = (path: string) => join(__dirname, path); diff --git a/packages/cli/src/lib/implementation/mock/cli-config.mock.js b/packages/cli/src/lib/implementation/mock/cli-config.mock.js index 17bc82f30..3b3d09df8 100644 --- a/packages/cli/src/lib/implementation/mock/cli-config.mock.js +++ b/packages/cli/src/lib/implementation/mock/cli-config.mock.js @@ -16,6 +16,7 @@ module.exports = { }, slug: 'execute-plugin', title: 'execute plugin', + icon: 'javascript', }, ], }; diff --git a/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.cjs b/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.cjs index 7996446d2..819d538d3 100644 --- a/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.cjs +++ b/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.cjs @@ -1,5 +1,5 @@ module.exports = { - persist: { outputPath: 'cjs-out.json' }, + persist: { outputPath: 'tmp/cjs-out.json' }, plugins: [], categories: [], }; diff --git a/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.mjs b/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.mjs index b0a888628..f8cc5b082 100644 --- a/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.mjs +++ b/packages/cli/src/lib/implementation/mock/config-middleware-config.mock.mjs @@ -1,5 +1,5 @@ export default { - persist: { outputPath: 'mjs-out.json' }, + persist: { outputPath: 'tmp/mjs-out.json' }, plugins: [], categories: [], }; diff --git a/packages/core/src/lib/execute-plugin.ts b/packages/core/src/lib/execute-plugin.ts index 0067da88c..347f2c4b4 100644 --- a/packages/core/src/lib/execute-plugin.ts +++ b/packages/core/src/lib/execute-plugin.ts @@ -3,9 +3,9 @@ import { PluginOutput, auditOutputsSchema, } from '@quality-metrics/models'; +import { ProcessObserver, executeProcess } from '@quality-metrics/utils'; import { readFile } from 'fs/promises'; import { join } from 'path'; -import { executeProcess, ProcessObserver } from '@quality-metrics/utils'; /** * Error thrown when plugin output is invalid. @@ -48,7 +48,7 @@ export async function executePlugin( pluginConfig: PluginConfig, observer?: ProcessObserver, ): Promise { - const { slug, title, description, docsUrl, version, packageName } = + const { slug, title, icon, description, docsUrl, version, packageName } = pluginConfig; const { args, command } = pluginConfig.runner; @@ -73,6 +73,7 @@ export async function executePlugin( packageName, slug, title, + icon, description, docsUrl, date, diff --git a/packages/core/src/lib/index.spec.ts b/packages/core/src/lib/index.spec.ts index c1f886b64..c513dafe2 100644 --- a/packages/core/src/lib/index.spec.ts +++ b/packages/core/src/lib/index.spec.ts @@ -6,7 +6,6 @@ import { CollectOptions, collect } from './collect'; const baseOptions: CollectOptions = { ...mockCoreConfig(), configPath: '', - interactive: true, verbose: false, }; diff --git a/packages/models/package.json b/packages/models/package.json index 41cfc5c39..9fc47c7b3 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -2,6 +2,7 @@ "name": "@quality-metrics/models", "version": "0.0.1", "dependencies": { + "@code-pushup/portal-client": "^0.1.2", "zod": "^3.22.1" } } diff --git a/packages/models/src/lib/plugin-config.ts b/packages/models/src/lib/plugin-config.ts index 5d5f820e7..a3c2c8a41 100644 --- a/packages/models/src/lib/plugin-config.ts +++ b/packages/models/src/lib/plugin-config.ts @@ -1,3 +1,4 @@ +import { MATERIAL_ICONS, MaterialIcon } from '@code-pushup/portal-client'; import { z } from 'zod'; import { executionMetaSchema, @@ -17,6 +18,11 @@ import { hasMissingStrings, } from './implementation/utils'; +export const materialIconSchema = z.enum( + MATERIAL_ICONS as [MaterialIcon, MaterialIcon, ...MaterialIcon[]], + { description: 'Icon from VSCode Material Icons extension' }, +); + export const pluginSchema = packageVersionSchema({ optional: true, }) @@ -31,9 +37,7 @@ export const pluginSchema = packageVersionSchema({ .merge( z.object({ slug: slugSchema('References plugin. ID (unique within core config)'), - icon: z.union([z.unknown(), z.string()], { - description: 'Icon from VSCode Material Icons extension', - }), + icon: materialIconSchema, }), ); diff --git a/packages/models/test/schema.mock.ts b/packages/models/test/schema.mock.ts index 0a288ccbe..6e0eefe73 100644 --- a/packages/models/test/schema.mock.ts +++ b/packages/models/test/schema.mock.ts @@ -59,6 +59,7 @@ export function mockPluginConfig(opt?: { }, slug: pluginSlug, title: 'execute plugin', + icon: 'nrwl', description: 'Plugin description for ' + pluginSlug, docsUrl: 'https://my-plugin.docs.dev?' + pluginSlug, }; @@ -204,7 +205,7 @@ export function mockPluginReport(opt?: { title: 'Title of ' + pluginSlug, description: 'Plugin description of ' + pluginSlug, docsUrl: `http://plugin.io/docs/${pluginSlug}`, - icon: 'socket', + icon: 'nrwl', version: '0.0.1', packageName: '@' + pluginSlug, audits: Array.isArray(auditSlug) @@ -256,7 +257,7 @@ export function mockUploadConfig(opt?: Partial): UploadConfig { export function mockAuditOutputs(opt?: { auditSlug: string | string[]; -}): AuditOutputs { +}): AuditOutput[] { let { auditSlug } = opt || {}; auditSlug = auditSlug || 'mock-audit-output-slug'; return Array.isArray(auditSlug) diff --git a/packages/models/test/test-data/config-and-report-lighthouse.mock.ts b/packages/models/test/test-data/config-and-report-lighthouse.mock.ts index cb0ef1c6e..f886bcfb4 100644 --- a/packages/models/test/test-data/config-and-report-lighthouse.mock.ts +++ b/packages/models/test/test-data/config-and-report-lighthouse.mock.ts @@ -10,6 +10,7 @@ export const lighthousePlugin: () => PluginConfig = () => }, slug: 'lighthouse', title: 'lighthouse', + icon: 'lighthouse', description: '', docsUrl: `https://github.com/GoogleChrome/lighthouse/tree/main/README.md`, groups: [], diff --git a/packages/models/test/test-data/config-and-report-nx-validators.mock.ts b/packages/models/test/test-data/config-and-report-nx-validators.mock.ts index ab105ff56..bbd2dc9a6 100644 --- a/packages/models/test/test-data/config-and-report-nx-validators.mock.ts +++ b/packages/models/test/test-data/config-and-report-nx-validators.mock.ts @@ -10,6 +10,7 @@ export const nxValidatorsPlugin: () => PluginConfig = (): PluginConfig => }, slug: 'nx-validators', title: 'NxValidatorsPlugin', + icon: 'nrwl', docsUrl: `https://github.com/BioPhoton/nx-validators/tree/main/README.md`, groups: [ { diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.ts b/packages/plugin-eslint/src/lib/eslint-plugin.ts index be5c772d9..29dc0d4f3 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.ts @@ -33,5 +33,6 @@ export function eslintPlugin(_: ESLintPluginConfig): PluginConfig { }, slug: 'eslint', title: 'execute plugin', + icon: 'eslint', }; } diff --git a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts index 62d5888c7..8e2df961b 100644 --- a/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts +++ b/packages/plugin-lighthouse/src/lib/lighthouse-plugin.ts @@ -33,5 +33,6 @@ export function lighthousePlugin(_: LighthousePluginConfig): PluginConfig { }, slug: 'lighthouse', title: 'ChromeDevTools Lighthouse', + icon: 'lighthouse', }; } diff --git a/packages/utils/src/lib/collect/implementation/mock/schema-helper.mock.ts b/packages/utils/src/lib/collect/implementation/mock/schema-helper.mock.ts index f1119bb33..ec8909e06 100644 --- a/packages/utils/src/lib/collect/implementation/mock/schema-helper.mock.ts +++ b/packages/utils/src/lib/collect/implementation/mock/schema-helper.mock.ts @@ -178,7 +178,7 @@ export function mockPluginReport(opt?: { slug: pluginSlug, docsUrl: `http://plugin.io/docs/${pluginSlug}`, title: 'Mock plugin Name', - icon: 'socket', + icon: 'nrwl', audits: Array.isArray(auditSlug) ? auditSlug.map(a => mockAuditReport({ auditSlug: a })) : [mockAuditReport({ auditSlug })],