mirror of
https://github.com/podman-desktop/podman-desktop
synced 2026-04-21 09:37:22 +00:00
chore: enable svelte-check (#992)
chore: enable svelte check on the repository on each PR allows to check if code is valid For now threshold is at error but it should be turned to hints Change-Id: Id1af31a438775f38c8cf37ad75552fea9f21fe3e Signed-off-by: Florent Benoit <fbenoit@redhat.com> Signed-off-by: Florent Benoit <fbenoit@redhat.com>
This commit is contained in:
parent
f71dd4b0be
commit
acbbfd0905
6 changed files with 100 additions and 63 deletions
6
.github/workflows/pr-check.yaml
vendored
6
.github/workflows/pr-check.yaml
vendored
|
|
@ -202,3 +202,9 @@ jobs:
|
|||
|
||||
- name: Run unit tests
|
||||
run: yarn test
|
||||
|
||||
- name: Run generate-types (required to run svelte check)
|
||||
run: yarn generate-types
|
||||
|
||||
- name: Run svelte check
|
||||
run: yarn svelte:check
|
||||
|
|
|
|||
|
|
@ -43,10 +43,12 @@
|
|||
"test:renderer": "vitest run -r packages/renderer --passWithNoTests",
|
||||
"test:watch": "vitest watch",
|
||||
"watch": "node scripts/watch.js",
|
||||
"generate-types": "node scripts/watch.js --types-only",
|
||||
"format:check": "prettier --check '{extensions,packages,tests,types}/**/*.{ts,svelte}' 'extensions/*/scripts/build.js' 'website/*.js' 'website/src/**/*.{css,tsx}'",
|
||||
"format:fix": "prettier --write '{extensions,packages,tests,types}/**/*.{ts,svelte}' 'extensions/*/scripts/build.js' 'website/src/**/*.{css,tsx}'",
|
||||
"lint:check": "eslint . --ext js,ts,tsx",
|
||||
"lint:fix": "eslint . --fix --ext js,ts,tsx",
|
||||
"svelte:check": "svelte-check",
|
||||
"typecheck:main": "tsc --noEmit -p packages/main/tsconfig.json",
|
||||
"typecheck:preload": "tsc --noEmit -p packages/preload/tsconfig.json",
|
||||
"typecheck:renderer": "npm run build:preload:types",
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ const processPasswordElement = (node: HTMLInputElement, registry: Registry) => {
|
|||
<DropdownMenuItem
|
||||
title="Login"
|
||||
onClick="{() => markRegistryAsModified(registry)}"
|
||||
hidden="{registry.username && registry.secret}"
|
||||
hidden="{!!registry.username && !!registry.secret}"
|
||||
icon="{faUser}" />
|
||||
<DropdownMenuItem
|
||||
title="Edit password"
|
||||
|
|
|
|||
|
|
@ -25,15 +25,15 @@ beforeEach(() => {
|
|||
|
||||
test('Should expect invalid domain', async () => {
|
||||
const result = urlValidator()('my_invalid_domain');
|
||||
expect(result).toBe('Please enter a valid URL');
|
||||
expect(result[1]).toBe('Please enter a valid URL');
|
||||
});
|
||||
|
||||
test('Should expect valid domain', async () => {
|
||||
const result = urlValidator()('valid.com');
|
||||
expect(result).toBe(true);
|
||||
expect(result[0]).toBe(true);
|
||||
});
|
||||
|
||||
test('Should expect valid TLD domain with more than 3 char domains', async () => {
|
||||
const result = urlValidator()('foobar.mydomain.science');
|
||||
expect(result).toBe(true);
|
||||
expect(result[0]).toBe(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -25,52 +25,73 @@ interface Validation {
|
|||
message?: string;
|
||||
}
|
||||
|
||||
export function createFieldValidator(...validators) {
|
||||
const { subscribe, set } = writable({ dirty: false, valid: false, message: null } as Validation);
|
||||
export type UpdateAction = {
|
||||
update(value: string): void;
|
||||
};
|
||||
|
||||
export type ActivateFunction = {
|
||||
(_node: unknown, binding: unknown): UpdateAction;
|
||||
};
|
||||
|
||||
export function createFieldValidator(...validators): [SvelteStore<Validation>, ActivateFunction] {
|
||||
const validation: Validation = { dirty: false, valid: false, message: null };
|
||||
const writableObject = writable<Validation>(validation);
|
||||
const validator = buildValidator(validators);
|
||||
|
||||
function action(node, binding) {
|
||||
function validate(value, dirty) {
|
||||
function action(_node, binding): UpdateAction {
|
||||
function validate(value: string, dirty: boolean) {
|
||||
const result = validator(value, dirty);
|
||||
set(result);
|
||||
writableObject.set(result);
|
||||
}
|
||||
|
||||
validate(binding, false);
|
||||
|
||||
return {
|
||||
update(value) {
|
||||
update(value: string): void {
|
||||
validate(value, value !== undefined);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return [{ subscribe }, action];
|
||||
const store: SvelteStore<Validation> = writableObject;
|
||||
const tuple: [SvelteStore<Validation>, ActivateFunction] = [store, action];
|
||||
return tuple;
|
||||
}
|
||||
|
||||
function buildValidator(validators) {
|
||||
return function validate(value, dirty) {
|
||||
function buildValidator(
|
||||
validators: ((value: string) => [boolean, string])[],
|
||||
): (value: string, dirty: boolean) => Validation {
|
||||
return function validate(value: string, dirty: boolean): Validation {
|
||||
if (!validators || validators.length === 0) {
|
||||
return { dirty, valid: true };
|
||||
}
|
||||
|
||||
const failing = validators.find(v => v(value) !== true);
|
||||
const failing = validators.map(v => v(value)).find(value => value[0] !== true);
|
||||
|
||||
return {
|
||||
dirty,
|
||||
valid: !failing,
|
||||
message: failing && failing(value),
|
||||
} as Validation;
|
||||
if (!failing) {
|
||||
return { dirty, valid: true, message: '' };
|
||||
} else {
|
||||
return {
|
||||
dirty,
|
||||
valid: false,
|
||||
message: failing[1],
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function requiredValidator() {
|
||||
return function required(value) {
|
||||
return (value !== undefined && value !== '') || 'Field is required';
|
||||
export function requiredValidator(): (value: string) => [boolean, string] {
|
||||
return function required(value: string): [boolean, string] {
|
||||
const valid = value !== undefined && value !== '';
|
||||
const message = valid ? '' : 'Field is required';
|
||||
return [valid, message];
|
||||
};
|
||||
}
|
||||
|
||||
export function urlValidator() {
|
||||
return function url(value) {
|
||||
return validator.isURL(value) || 'Please enter a valid URL';
|
||||
export function urlValidator(): (value: string) => [boolean, string] {
|
||||
return function url(value: string): [boolean, string] {
|
||||
const valid = validator.isURL(value);
|
||||
const message = valid ? '' : 'Please enter a valid URL';
|
||||
return [valid, message];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const {createServer, build, createLogger} = require('vite');
|
||||
const { createServer, build, createLogger } = require('vite');
|
||||
const electronPath = require('electron');
|
||||
const {spawn} = require('child_process');
|
||||
const {generateAsync} = require('dts-for-context-bridge');
|
||||
const { spawn } = require('child_process');
|
||||
const { generateAsync } = require('dts-for-context-bridge');
|
||||
const path = require('path');
|
||||
|
||||
/** @type 'production' | 'development'' */
|
||||
const mode = process.env.MODE = process.env.MODE || 'development';
|
||||
|
||||
const mode = (process.env.MODE = process.env.MODE || 'development');
|
||||
|
||||
/** @type {import('vite').LogLevel} */
|
||||
const LOG_LEVEL = 'info';
|
||||
|
||||
|
||||
/** @type {import('vite').InlineConfig} */
|
||||
const sharedConfig = {
|
||||
mode,
|
||||
|
|
@ -34,20 +32,19 @@ const stderrFilterPatterns = [
|
|||
/**
|
||||
* @param {{name: string; configFile: string; writeBundle: import('rollup').OutputPlugin['writeBundle'] }} param0
|
||||
*/
|
||||
const getWatcher = ({name, configFile, writeBundle}) => {
|
||||
const getWatcher = ({ name, configFile, writeBundle }) => {
|
||||
return build({
|
||||
...sharedConfig,
|
||||
configFile,
|
||||
plugins: [{name, writeBundle}],
|
||||
plugins: [{ name, writeBundle }],
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Start or restart App when source files are changed
|
||||
* @param {{config: {server: import('vite').ResolvedServerOptions}}} ResolvedServerOptions
|
||||
*/
|
||||
const setupMainPackageWatcher = ({config: {server}}) => {
|
||||
const setupMainPackageWatcher = ({ config: { server } }) => {
|
||||
// Create VITE_DEV_SERVER_URL environment variable to pass it to the main process.
|
||||
{
|
||||
const protocol = server.https ? 'https:' : 'http:';
|
||||
|
|
@ -74,13 +71,13 @@ const setupMainPackageWatcher = ({config: {server}}) => {
|
|||
spawnProcess = null;
|
||||
}
|
||||
|
||||
spawnProcess = spawn(String(electronPath), ['.'], { env: {...process.env, ELECTRON_IS_DEV: 1} });
|
||||
spawnProcess = spawn(String(electronPath), ['.'], { env: { ...process.env, ELECTRON_IS_DEV: 1 } });
|
||||
|
||||
spawnProcess.stdout.on('data', d => d.toString().trim() && logger.warn(d.toString(), {timestamp: true}));
|
||||
spawnProcess.stdout.on('data', d => d.toString().trim() && logger.warn(d.toString(), { timestamp: true }));
|
||||
spawnProcess.stderr.on('data', d => {
|
||||
const data = d.toString().trim();
|
||||
if (!data) return;
|
||||
const mayIgnore = stderrFilterPatterns.some((r) => r.test(data));
|
||||
const mayIgnore = stderrFilterPatterns.some(r => r.test(data));
|
||||
if (mayIgnore) return;
|
||||
logger.error(data, { timestamp: true });
|
||||
});
|
||||
|
|
@ -91,12 +88,11 @@ const setupMainPackageWatcher = ({config: {server}}) => {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Start or restart App when source files are changed
|
||||
* @param {{ws: import('vite').WebSocketServer}} WebSocketServer
|
||||
*/
|
||||
const setupPreloadPackageWatcher = ({ws}) =>
|
||||
const setupPreloadPackageWatcher = ({ ws }) =>
|
||||
getWatcher({
|
||||
name: 'reload-page-on-preload-package-change',
|
||||
configFile: 'packages/preload/vite.config.js',
|
||||
|
|
@ -106,14 +102,15 @@ const setupPreloadPackageWatcher = ({ws}) =>
|
|||
input: 'packages/preload/tsconfig.json',
|
||||
output: 'packages/preload/exposedInMainWorld.d.ts',
|
||||
});
|
||||
|
||||
ws.send({
|
||||
type: 'full-reload',
|
||||
});
|
||||
if (ws) {
|
||||
ws.send({
|
||||
type: 'full-reload',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const setupPreloadDockerExtensionPackageWatcher = ({ws}) =>
|
||||
const setupPreloadDockerExtensionPackageWatcher = ({ ws }) =>
|
||||
getWatcher({
|
||||
name: 'reload-page-on-preload-docker-extension-package-change',
|
||||
configFile: 'packages/preload-docker-extension/vite.config.js',
|
||||
|
|
@ -124,37 +121,48 @@ const setupPreloadDockerExtensionPackageWatcher = ({ws}) =>
|
|||
output: 'packages/preload-docker-extension/exposedInDockerExtension.d.ts',
|
||||
});
|
||||
|
||||
ws.send({
|
||||
type: 'full-reload',
|
||||
});
|
||||
if (ws) {
|
||||
ws.send({
|
||||
type: 'full-reload',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Start or restart App when source files are changed
|
||||
* @param {{ws: import('vite').WebSocketServer}} WebSocketServer
|
||||
*/
|
||||
const setupExtensionApiWatcher = (name) =>{
|
||||
let spawnProcess;
|
||||
const folderName = path.resolve(__dirname, '../extensions/' + name);
|
||||
const setupExtensionApiWatcher = name => {
|
||||
let spawnProcess;
|
||||
const folderName = path.resolve(__dirname, '../extensions/' + name);
|
||||
|
||||
console.log('dirname is', folderName);
|
||||
spawnProcess = spawn('yarn', ['--cwd', folderName, 'watch'], { shell: process.platform === 'win32'} );
|
||||
spawnProcess = spawn('yarn', ['--cwd', folderName, 'watch'], { shell: process.platform === 'win32' });
|
||||
|
||||
spawnProcess.stdout.on('data', d => d.toString().trim() && console.warn(d.toString(), {timestamp: true}));
|
||||
spawnProcess.stderr.on('data', d => {
|
||||
const data = d.toString().trim();
|
||||
if (!data) return;
|
||||
console.error(data, { timestamp: true });
|
||||
});
|
||||
spawnProcess.stdout.on('data', d => d.toString().trim() && console.warn(d.toString(), { timestamp: true }));
|
||||
spawnProcess.stderr.on('data', d => {
|
||||
const data = d.toString().trim();
|
||||
if (!data) return;
|
||||
console.error(data, { timestamp: true });
|
||||
});
|
||||
|
||||
// Stops the watch script when the application has been quit
|
||||
spawnProcess.on('exit', process.exit);
|
||||
|
||||
};
|
||||
// Stops the watch script when the application has been quit
|
||||
spawnProcess.on('exit', process.exit);
|
||||
};
|
||||
|
||||
(async () => {
|
||||
// grab arguments
|
||||
const args = process.argv.slice(2);
|
||||
const generateTypesOnly = args.includes('--types-only');
|
||||
// If types-only is passed, we don't watch for changes but only do generation
|
||||
if (generateTypesOnly) {
|
||||
delete sharedConfig.build.watch;
|
||||
await setupPreloadPackageWatcher({ ws: undefined });
|
||||
await setupPreloadDockerExtensionPackageWatcher({ ws: undefined });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const viteDevServer = await createServer({
|
||||
...sharedConfig,
|
||||
|
|
|
|||
Loading…
Reference in a new issue