Skip to content

Commit

Permalink
Bump to TypeScript 5.5 with noImplicitAny (TODO: Test autoupdates)
Browse files Browse the repository at this point in the history
Changes:

- Update TypeScript to 5.5
- Refactor code to comply with `noImplicitAny`
- Add missing types for `electron-progressbar`
- Refactor progress bar handling for type safety
- Drop 'I' prefix from interfaces to align with new code convention
- Update TypeScript target from `ES2017` and `ES2018`.
  This allows named capturing groups. Otherwise, new TypeScript compiler
  does not compile the project and shows the following error:
  ```
  ...
  TimestampedFilenameGenerator.spec.ts:105:23 - error TS1503: Named capturing groups are only available when targeting 'ES2018' or later
  const pattern = /^(?<timestamp>\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})-(?<scriptName>[^.]+?)(?:\.(?<extension>[^.]+))?$/;// timestamp-scriptName.extension
  ...
  ```
  • Loading branch information
undergroundwires committed Sep 19, 2024
1 parent 1e1f581 commit 4dfecda
Show file tree
Hide file tree
Showing 75 changed files with 12,782 additions and 11,792 deletions.
23,847 changes: 12,310 additions & 11,537 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "privacy.sexy",
"version": "0.13.6",
"version": "0.13.3",
"private": true,
"slogan": "Privacy is sexy",
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy.",
Expand Down Expand Up @@ -48,6 +48,7 @@
"@modyfi/vite-plugin-yaml": "^1.1.0",
"@rushstack/eslint-patch": "^1.10.3",
"@types/ace": "^0.0.52",
"@types/electron-progressbar": "^1.2.7",
"@types/file-saver": "^2.0.7",
"@types/markdown-it": "^14.1.1",
"@typescript-eslint/eslint-plugin": "6.21.0",
Expand Down Expand Up @@ -78,7 +79,7 @@
"start-server-and-test": "^2.0.4",
"terser": "^5.31.3",
"tslib": "^2.6.3",
"typescript": "^5.4.5",
"typescript": "^5.5.4",
"vite": "^5.3.4",
"vitest": "^2.0.3",
"vue-tsc": "^2.0.26",
Expand Down
10 changes: 6 additions & 4 deletions src/application/Common/Enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,25 @@ function parseEnumValue<T extends EnumType, TEnumValue extends EnumType>(
if (!casedValue) {
throw new Error(`unknown ${enumName}: "${value}"`);
}
return enumVariable[casedValue as keyof typeof enumVariable];
return enumVariable[casedValue as keyof EnumVariable<T, TEnumValue>];
}

export function getEnumNames
<T extends EnumType, TEnumValue extends EnumType>(
enumVariable: EnumVariable<T, TEnumValue>,
): string[] {
): (string & keyof EnumVariable<T, TEnumValue>)[] {
return Object
.values(enumVariable)
.filter((enumMember): enumMember is string => isString(enumMember));
.filter((
enumMember,
): enumMember is string & (keyof EnumVariable<T, TEnumValue>) => isString(enumMember));
}

export function getEnumValues<T extends EnumType, TEnumValue extends EnumType>(
enumVariable: EnumVariable<T, TEnumValue>,
): TEnumValue[] {
return getEnumNames(enumVariable)
.map((level) => enumVariable[level]) as TEnumValue[];
.map((name) => enumVariable[name]) as TEnumValue[];
}

export function assertInRange<T extends EnumType, TEnumValue extends EnumType>(
Expand Down
37 changes: 29 additions & 8 deletions src/application/Context/ApplicationContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class ApplicationContext implements IApplicationContext {
public currentOs: OperatingSystem;

public get state(): ICategoryCollectionState {
return this.states[this.collection.os];
return this.getState(this.collection.os);
}

private readonly states: StateMachine;
Expand All @@ -26,30 +26,51 @@ export class ApplicationContext implements IApplicationContext {
public readonly app: IApplication,
initialContext: OperatingSystem,
) {
this.setContext(initialContext);
this.states = initializeStates(app);
this.changeContext(initialContext);
}

public changeContext(os: OperatingSystem): void {
assertInRange(os, OperatingSystem);
if (this.currentOs === os) {
return;
}
const collection = this.app.getCollection(os);
this.collection = collection;
const event: IApplicationContextChangedEvent = {
newState: this.states[os],
oldState: this.states[this.currentOs],
newState: this.getState(os),
oldState: this.getState(this.currentOs),
};
this.setContext(os);
this.contextChanged.notify(event);
}

private setContext(os: OperatingSystem): void {
validateOperatingSystem(os, this.app);
this.collection = this.app.getCollection(os);
this.currentOs = os;
}

private getState(os: OperatingSystem): ICategoryCollectionState {
const state = this.states.get(os);
if (!state) {
throw new Error(`Operating system "${OperatingSystem[os]}" state is unknown.`);
}
return state;
}
}

function validateOperatingSystem(
os: OperatingSystem,
app: IApplication,
): void {
assertInRange(os, OperatingSystem);
if (!app.getSupportedOsList().includes(os)) {
throw new Error(`Operating system "${OperatingSystem[os]}" is not supported.`);
}
}

function initializeStates(app: IApplication): StateMachine {
const machine = new Map<OperatingSystem, ICategoryCollectionState>();
for (const collection of app.collections) {
machine[collection.os] = new CategoryCollectionState(collection);
machine.set(collection.os, new CategoryCollectionState(collection));
}
return machine;
}
2 changes: 1 addition & 1 deletion src/application/Parser/Executable/CategoryParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function ensureValidCategory(
});
validator.assertType((v) => v.assertObject({
value: category,
valueName: `Category '${category.category}'` ?? 'Category',
valueName: category.category ? `Category '${category.category}'` : 'Category',
allowedProperties: [
'docs', 'children', 'category',
],
Expand Down
2 changes: 1 addition & 1 deletion src/application/Parser/Executable/Script/ScriptParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function validateScript(
): asserts script is NonNullable<ScriptData> {
validator.assertType((v) => v.assertObject<CallScriptData & CodeScriptData>({
value: script,
valueName: `Script '${script.name}'` ?? 'Script',
valueName: script.name ? `Script '${script.name}'` : 'Script',
allowedProperties: [
'name', 'recommend', 'code', 'revertCode', 'call', 'docs',
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type DuplicateLinesAnalyzer = CodeValidationAnalyzer & {
export const analyzeDuplicateLines: DuplicateLinesAnalyzer = (
lines: readonly CodeLine[],
language: ScriptingLanguage,
syntaxFactory = createSyntax,
syntaxFactory: SyntaxFactory = createSyntax,
) => {
const syntax = syntaxFactory(language);
return lines
Expand Down
8 changes: 4 additions & 4 deletions src/infrastructure/RuntimeSanity/Common/FactoryValidator.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import type { ISanityValidator } from './ISanityValidator';
import type { ISanityCheckOptions } from './ISanityCheckOptions';
import type { SanityValidator } from './SanityValidator';
import type { SanityCheckOptions } from './SanityCheckOptions';

export type FactoryFunction<T> = () => T;

export abstract class FactoryValidator<T> implements ISanityValidator {
export abstract class FactoryValidator<T> implements SanityValidator {
private readonly factory: FactoryFunction<T>;

protected constructor(factory: FactoryFunction<T>) {
this.factory = factory;
}

public abstract shouldValidate(options: ISanityCheckOptions): boolean;
public abstract shouldValidate(options: SanityCheckOptions): boolean;

public abstract name: string;

Expand Down
7 changes: 0 additions & 7 deletions src/infrastructure/RuntimeSanity/Common/ISanityValidator.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export interface ISanityCheckOptions {
export interface SanityCheckOptions {
readonly validateEnvironmentVariables: boolean;
readonly validateWindowVariables: boolean;
}
7 changes: 7 additions & 0 deletions src/infrastructure/RuntimeSanity/Common/SanityValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { SanityCheckOptions } from './SanityCheckOptions';

export interface SanityValidator {
readonly name: string;
shouldValidate(options: SanityCheckOptions): boolean;
collectErrors(): Iterable<string>;
}
25 changes: 16 additions & 9 deletions src/infrastructure/RuntimeSanity/SanityChecks.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { EnvironmentVariablesValidator } from './Validators/EnvironmentVariablesValidator';
import type { ISanityCheckOptions } from './Common/ISanityCheckOptions';
import type { ISanityValidator } from './Common/ISanityValidator';
import type { SanityCheckOptions } from './Common/SanityCheckOptions';
import type { SanityValidator } from './Common/SanityValidator';

const DefaultSanityValidators: ISanityValidator[] = [
const DefaultSanityValidators: SanityValidator[] = [
new EnvironmentVariablesValidator(),
];

export interface RuntimeSanityValidator {
(
options: SanityCheckOptions,
validators?: readonly SanityValidator[],
): void;
}

/* Helps to fail-fast on errors */
export function validateRuntimeSanity(
options: ISanityCheckOptions,
validators: readonly ISanityValidator[] = DefaultSanityValidators,
): void {
export const validateRuntimeSanity: RuntimeSanityValidator = (
options: SanityCheckOptions,
validators: readonly SanityValidator[] = DefaultSanityValidators,
) => {
if (!validators.length) {
throw new Error('missing validators');
}
Expand All @@ -26,9 +33,9 @@ export function validateRuntimeSanity(
if (errorMessages.length > 0) {
throw new Error(`Sanity check failed.\n${errorMessages.join('\n---\n')}`);
}
}
};

function getErrorMessage(validator: ISanityValidator): string | undefined {
function getErrorMessage(validator: SanityValidator): string | undefined {
const errorMessages = [...validator.collectErrors()];
if (!errorMessages.length) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { IEnvironmentVariables } from '@/infrastructure/EnvironmentVariables/IEnvironmentVariables';
import { EnvironmentVariablesFactory } from '@/infrastructure/EnvironmentVariables/EnvironmentVariablesFactory';
import { FactoryValidator, type FactoryFunction } from '../Common/FactoryValidator';
import type { ISanityCheckOptions } from '../Common/ISanityCheckOptions';
import type { SanityCheckOptions } from '../Common/SanityCheckOptions';

export class EnvironmentVariablesValidator extends FactoryValidator<IEnvironmentVariables> {
constructor(
Expand All @@ -14,7 +14,7 @@ export class EnvironmentVariablesValidator extends FactoryValidator<IEnvironment

public override name = 'environment variables';

public override shouldValidate(options: ISanityCheckOptions): boolean {
public override shouldValidate(options: SanityCheckOptions): boolean {
return options.validateEnvironmentVariables;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { WindowVariables } from '@/infrastructure/WindowVariables/WindowVariables';
import { FactoryValidator, type FactoryFunction } from '../Common/FactoryValidator';
import type { ISanityCheckOptions } from '../Common/ISanityCheckOptions';
import type { SanityCheckOptions } from '../Common/SanityCheckOptions';

export class WindowVariablesValidator extends FactoryValidator<WindowVariables> {
constructor(factory: FactoryFunction<WindowVariables> = () => window) {
Expand All @@ -9,7 +9,7 @@ export class WindowVariablesValidator extends FactoryValidator<WindowVariables>

public override name = 'window variables';

public override shouldValidate(options: ISanityCheckOptions): boolean {
public override shouldValidate(options: SanityCheckOptions): boolean {
return options.validateWindowVariables;
}
}
4 changes: 2 additions & 2 deletions src/presentation/bootstrapping/ApplicationBootstrapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RuntimeSanityValidator } from './Modules/RuntimeSanityValidator';
import { RuntimeSanityBootstrapper } from './Modules/RuntimeSanityBootstrapper';
import { AppInitializationLogger } from './Modules/AppInitializationLogger';
import { DependencyBootstrapper } from './Modules/DependencyBootstrapper';
import { MobileSafariActivePseudoClassEnabler } from './Modules/MobileSafariActivePseudoClassEnabler';
Expand All @@ -17,7 +17,7 @@ export class ApplicationBootstrapper implements Bootstrapper {

private static getAllBootstrappers(): Bootstrapper[] {
return [
new RuntimeSanityValidator(),
new RuntimeSanityBootstrapper(),
new DependencyBootstrapper(),
new AppInitializationLogger(),
new MobileSafariActivePseudoClassEnabler(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { validateRuntimeSanity, type RuntimeSanityValidator } from '@/infrastructure/RuntimeSanity/SanityChecks';
import type { Bootstrapper } from '../Bootstrapper';

export class RuntimeSanityBootstrapper implements Bootstrapper {
constructor(private readonly validator: RuntimeSanityValidator = validateRuntimeSanity) {

}

public async bootstrap(): Promise<void> {
this.validator({
validateEnvironmentVariables: true,
validateWindowVariables: true,
});
}
}
15 changes: 0 additions & 15 deletions src/presentation/bootstrapping/Modules/RuntimeSanityValidator.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
:tree-root="treeRoot"
:rendering-strategy="renderingStrategy"
>
<template #node-content="slotProps">
<template #node-content="slotProps: NodeMetadata">
<slot name="node-content" v-bind="slotProps" />
</template>
</HierarchicalTreeNode>
Expand All @@ -55,6 +55,7 @@ import { useCurrentTreeNodes } from '../UseCurrentTreeNodes';
import { useNodeState } from './UseNodeState';
import LeafTreeNode from './LeafTreeNode.vue';
import InteractableNode from './InteractableNode.vue';
import type { NodeMetadata } from '../../NodeContent/NodeMetadata';
import type { TreeRoot } from '../TreeRoot/TreeRoot';
import type { TreeNode, TreeNodeId } from './TreeNode';
import type { NodeRenderingStrategy } from '../Rendering/Scheduling/NodeRenderingStrategy';
Expand Down Expand Up @@ -107,6 +108,7 @@ export default defineComponent({
);
return {
NodeMetadata: Object as PropType<NodeMetadata>,
renderedNodeIds,
isExpanded,
toggleExpand,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ export class TreeRootManager implements TreeRoot {

constructor(
collection: TreeNodeCollection = new TreeNodeInitializerAndUpdater(),
createFocusManager: (
collection: TreeNodeCollection
) => SingleNodeFocusManager = (nodes) => new SingleNodeCollectionFocusManager(nodes),
createFocusManager: FocusManagerFactory = (
nodes,
) => new SingleNodeCollectionFocusManager(nodes),
) {
this.collection = collection;
this.focus = createFocusManager(this.collection);
}
}

export interface FocusManagerFactory {
(
collection: TreeNodeCollection
): SingleNodeFocusManager;
}
18 changes: 8 additions & 10 deletions src/presentation/components/Shared/TooltipWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,15 @@ function getArrowPositionStyles(
coordinations: Partial<Coords>,
placement: Placement,
): CSSProperties {
const style: CSSProperties = {};
style.position = 'absolute';
const { x, y } = coordinations;
if (x) {
style.left = `${x}px`;
} else if (y) { // either X or Y is calculated
style.top = `${y}px`;
}
const { x, y } = coordinations; // either X or Y is calculated
const oppositeSide = getCounterpartBoxOffsetProperty(placement);
style[oppositeSide.toString()] = `-${ARROW_SIZE_IN_PX}px`;
return style;
const newStyle: CSSProperties = {
[oppositeSide]: `-${ARROW_SIZE_IN_PX}px`,
position: 'absolute',
left: x ? `${x}px` : undefined,
top: y ? `${y}px` : undefined,
};
return newStyle;
}
function getCounterpartBoxOffsetProperty(placement: Placement): keyof CSSProperties {
Expand Down
3 changes: 2 additions & 1 deletion src/presentation/electron/main/IpcRegistration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export function registerAllIpcChannels(
};
Object.entries(ipcInstanceCreators).forEach(([name, instanceFactory]) => {
try {
const definition = IpcChannelDefinitions[name];
const definitionKey = name as keyof typeof IpcChannelDefinitions;
const definition = IpcChannelDefinitions[definitionKey] as IpcChannel<unknown>;
const instance = instanceFactory();
registrar(definition, instance);
} catch (err) {
Expand Down
Loading

0 comments on commit 4dfecda

Please sign in to comment.