Skip to content

Commit

Permalink
Bump to TypeScript 5.5 and enable noImplicitAny
Browse files Browse the repository at this point in the history
This commit upgrades TypeScript from 5.4 to 5.5 and enables the
`noImplicitAny` option for stricter type checking. It refactors code to
comply with `noImplicitAny` and adapts to new TypeScript features and
limitations.

Key changes:

- Migrate from TypeScript 5.4 to 5.5
- Enable `noImplicitAny` for stricter type checking
- Refactor code to comply with new TypeScript features and limitations

Other supporting changes:

- 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
  ...
  ```
- Refactor usage of `electron-progressbar` for type safety and
  less complexity.
  • Loading branch information
undergroundwires committed Sep 26, 2024
1 parent a05a600 commit e17744f
Show file tree
Hide file tree
Showing 77 changed files with 656 additions and 332 deletions.
17 changes: 9 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,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;
}
Loading

0 comments on commit e17744f

Please sign in to comment.