Refactor to unify scripts/categories as Executable

This commit consolidates scripts and categories under a unified
'Executable' concept. This simplifies the architecture and improves code
readability.

- Introduce subfolders within `src/domain` to segregate domain elements.
- Update class and interface names by removing the 'I' prefix in
  alignment with new coding standards.
- Replace 'Node' with 'Executable' to clarify usage; reserve 'Node'
  exclusively for the UI's tree component.
This commit is contained in:
undergroundwires
2024-06-12 12:36:40 +02:00
parent 8becc7dbc4
commit c138f74460
230 changed files with 1120 additions and 1039 deletions

View File

@@ -1,4 +1,4 @@
import type { IScript } from '@/domain/IScript';
import type { Script } from '@/domain/Executables/Script/Script';
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
import type { ICodeChangedEvent } from './ICodeChangedEvent';
@@ -6,13 +6,13 @@ import type { ICodeChangedEvent } from './ICodeChangedEvent';
export class CodeChangedEvent implements ICodeChangedEvent {
public readonly code: string;
public readonly addedScripts: ReadonlyArray<IScript>;
public readonly addedScripts: ReadonlyArray<Script>;
public readonly removedScripts: ReadonlyArray<IScript>;
public readonly removedScripts: ReadonlyArray<Script>;
public readonly changedScripts: ReadonlyArray<IScript>;
public readonly changedScripts: ReadonlyArray<Script>;
private readonly scripts: Map<IScript, ICodePosition>;
private readonly scripts: Map<Script, ICodePosition>;
constructor(
code: string,
@@ -25,7 +25,7 @@ export class CodeChangedEvent implements ICodeChangedEvent {
this.addedScripts = selectIfNotExists(newScripts, oldScripts);
this.removedScripts = selectIfNotExists(oldScripts, newScripts);
this.changedScripts = getChangedScripts(oldScripts, newScripts);
this.scripts = new Map<IScript, ICodePosition>();
this.scripts = new Map<Script, ICodePosition>();
scripts.forEach((position, selection) => {
this.scripts.set(selection.script, position);
});
@@ -35,7 +35,7 @@ export class CodeChangedEvent implements ICodeChangedEvent {
return this.scripts.size === 0;
}
public getScriptPositionInCode(script: IScript): ICodePosition {
public getScriptPositionInCode(script: Script): ICodePosition {
return this.getPositionById(script.id);
}
@@ -65,7 +65,7 @@ function ensureAllPositionsExist(script: string, positions: ReadonlyArray<ICodeP
function getChangedScripts(
oldScripts: ReadonlyArray<SelectedScript>,
newScripts: ReadonlyArray<SelectedScript>,
): ReadonlyArray<IScript> {
): ReadonlyArray<Script> {
return newScripts
.filter((newScript) => oldScripts.find((oldScript) => oldScript.id === newScript.id
&& oldScript.revert !== newScript.revert))

View File

@@ -1,11 +1,11 @@
import type { IScript } from '@/domain/IScript';
import type { Script } from '@/domain/Executables/Script/Script';
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
export interface ICodeChangedEvent {
readonly code: string;
readonly addedScripts: ReadonlyArray<IScript>;
readonly removedScripts: ReadonlyArray<IScript>;
readonly changedScripts: ReadonlyArray<IScript>;
readonly addedScripts: ReadonlyArray<Script>;
readonly removedScripts: ReadonlyArray<Script>;
readonly changedScripts: ReadonlyArray<Script>;
isEmpty(): boolean;
getScriptPositionInCode(script: IScript): ICodePosition;
getScriptPositionInCode(script: Script): ICodePosition;
}

View File

@@ -1,11 +1,11 @@
import type { IScript } from '@/domain/IScript';
import type { ICategory } from '@/domain/ICategory';
import type { Script } from '@/domain/Executables/Script/Script';
import type { Category } from '@/domain/Executables/Category/Category';
import type { FilterResult } from './FilterResult';
export class AppliedFilterResult implements FilterResult {
constructor(
public readonly scriptMatches: ReadonlyArray<IScript>,
public readonly categoryMatches: ReadonlyArray<ICategory>,
public readonly scriptMatches: ReadonlyArray<Script>,
public readonly categoryMatches: ReadonlyArray<Category>,
public readonly query: string,
) {
if (!query) { throw new Error('Query is empty or undefined'); }

View File

@@ -1,8 +1,9 @@
import type { IScript, ICategory } from '@/domain/ICategory';
import type { Category } from '@/domain/Executables/Category/Category';
import type { Script } from '@/domain/Executables/Script/Script';
export interface FilterResult {
readonly categoryMatches: ReadonlyArray<ICategory>;
readonly scriptMatches: ReadonlyArray<IScript>;
readonly categoryMatches: ReadonlyArray<Category>;
readonly scriptMatches: ReadonlyArray<Script>;
readonly query: string;
hasAnyMatches(): boolean;
}

View File

@@ -1,7 +1,8 @@
import type { ICategory, IScript } from '@/domain/ICategory';
import type { IScriptCode } from '@/domain/IScriptCode';
import type { IDocumentable } from '@/domain/IDocumentable';
import type { Category } from '@/domain/Executables/Category/Category';
import type { ScriptCode } from '@/domain/Executables/Script/Code/ScriptCode';
import type { Documentable } from '@/domain/Executables/Documentable';
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
import type { Script } from '@/domain/Executables/Script/Script';
import { AppliedFilterResult } from '../Result/AppliedFilterResult';
import type { FilterStrategy } from './FilterStrategy';
import type { FilterResult } from '../Result/FilterResult';
@@ -24,7 +25,7 @@ export class LinearFilterStrategy implements FilterStrategy {
}
function matchesCategory(
category: ICategory,
category: Category,
filterLowercase: string,
): boolean {
return matchesAny(
@@ -34,7 +35,7 @@ function matchesCategory(
}
function matchesScript(
script: IScript,
script: Script,
filterLowercase: string,
): boolean {
return matchesAny(
@@ -58,7 +59,7 @@ function matchName(
}
function matchCode(
code: IScriptCode,
code: ScriptCode,
filterLowercase: string,
): boolean {
if (code.execute.toLowerCase().includes(filterLowercase)) {
@@ -71,7 +72,7 @@ function matchCode(
}
function matchDocumentation(
documentable: IDocumentable,
documentable: Documentable,
filterLowercase: string,
): boolean {
return documentable.docs.some(

View File

@@ -1,9 +1,9 @@
import type { ICategory } from '@/domain/ICategory';
import type { Category } from '@/domain/Executables/Category/Category';
import type { CategorySelectionChangeCommand } from './CategorySelectionChange';
export interface ReadonlyCategorySelection {
areAllScriptsSelected(category: ICategory): boolean;
isAnyScriptSelected(category: ICategory): boolean;
areAllScriptsSelected(category: Category): boolean;
isAnyScriptSelected(category: Category): boolean;
}
export interface CategorySelection extends ReadonlyCategorySelection {

View File

@@ -1,4 +1,4 @@
import type { ICategory } from '@/domain/ICategory';
import type { Category } from '@/domain/Executables/Category/Category';
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
import type { CategorySelectionChange, CategorySelectionChangeCommand } from './CategorySelectionChange';
import type { CategorySelection } from './CategorySelection';
@@ -13,7 +13,7 @@ export class ScriptToCategorySelectionMapper implements CategorySelection {
}
public areAllScriptsSelected(category: ICategory): boolean {
public areAllScriptsSelected(category: Category): boolean {
const { selectedScripts } = this.scriptSelection;
if (selectedScripts.length === 0) {
return false;
@@ -27,7 +27,7 @@ export class ScriptToCategorySelectionMapper implements CategorySelection {
);
}
public isAnyScriptSelected(category: ICategory): boolean {
public isAnyScriptSelected(category: Category): boolean {
const { selectedScripts } = this.scriptSelection;
if (selectedScripts.length === 0) {
return false;

View File

@@ -1,5 +1,5 @@
import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryRepository';
import type { IScript } from '@/domain/IScript';
import type { Script } from '@/domain/Executables/Script/Script';
import { EventSource } from '@/infrastructure/Events/EventSource';
import type { ReadonlyRepository, Repository } from '@/application/Repository/Repository';
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
@@ -80,7 +80,7 @@ export class DebouncedScriptSelection implements ScriptSelection {
});
}
public selectOnly(scripts: readonly IScript[]): void {
public selectOnly(scripts: readonly Script[]): void {
assertNonEmptyScriptSelection(scripts);
this.processChanges({
changes: [
@@ -145,7 +145,7 @@ export class DebouncedScriptSelection implements ScriptSelection {
}
}
function assertNonEmptyScriptSelection(selectedItems: readonly IScript[]) {
function assertNonEmptyScriptSelection(selectedItems: readonly Script[]) {
if (selectedItems.length === 0) {
throw new Error('Provided script array is empty. To deselect all scripts, please use the deselectAll() method instead.');
}
@@ -153,7 +153,7 @@ function assertNonEmptyScriptSelection(selectedItems: readonly IScript[]) {
function getScriptIdsToBeSelected(
existingItems: ReadonlyRepository<string, SelectedScript>,
desiredScripts: readonly IScript[],
desiredScripts: readonly Script[],
): string[] {
return desiredScripts
.filter((script) => !existingItems.exists(script.id))
@@ -162,7 +162,7 @@ function getScriptIdsToBeSelected(
function getScriptIdsToBeDeselected(
existingItems: ReadonlyRepository<string, SelectedScript>,
desiredScripts: readonly IScript[],
desiredScripts: readonly Script[],
): string[] {
return existingItems
.getItems()

View File

@@ -1,5 +1,5 @@
import type { IEventSource } from '@/infrastructure/Events/IEventSource';
import type { IScript } from '@/domain/IScript';
import type { Script } from '@/domain/Executables/Script/Script';
import type { SelectedScript } from './SelectedScript';
import type { ScriptSelectionChangeCommand } from './ScriptSelectionChange';
@@ -10,7 +10,7 @@ export interface ReadonlyScriptSelection {
}
export interface ScriptSelection extends ReadonlyScriptSelection {
selectOnly(scripts: readonly IScript[]): void;
selectOnly(scripts: readonly Script[]): void;
selectAll(): void;
deselectAll(): void;
processChanges(action: ScriptSelectionChangeCommand): void;

View File

@@ -1,9 +1,9 @@
import type { IEntity } from '@/infrastructure/Entity/IEntity';
import type { IScript } from '@/domain/IScript';
import type { Script } from '@/domain/Executables/Script/Script';
type ScriptId = IScript['id'];
type ScriptId = Script['id'];
export interface SelectedScript extends IEntity<ScriptId> {
readonly script: IScript;
readonly script: Script;
readonly revert: boolean;
}

View File

@@ -1,12 +1,12 @@
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
import type { IScript } from '@/domain/IScript';
import type { Script } from '@/domain/Executables/Script/Script';
import type { SelectedScript } from './SelectedScript';
type SelectedScriptId = SelectedScript['id'];
export class UserSelectedScript extends BaseEntity<SelectedScriptId> {
constructor(
public readonly script: IScript,
public readonly script: Script,
public readonly revert: boolean,
) {
super(script.id);