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

@@ -0,0 +1,31 @@
import type { ScriptCode } from './ScriptCode';
export class DistinctReversibleScriptCode implements ScriptCode {
constructor(
public readonly execute: string,
public readonly revert: string | undefined,
) {
validateCode(execute);
validateRevertCode(revert, execute);
}
}
function validateRevertCode(revertCode: string | undefined, execute: string) {
if (!revertCode) {
return;
}
try {
validateCode(revertCode);
if (execute === revertCode) {
throw new Error('Code itself and its reverting code cannot be the same');
}
} catch (err) {
throw Error(`(revert): ${err.message}`);
}
}
function validateCode(code: string): void {
if (code.length === 0) {
throw new Error('missing code');
}
}

View File

@@ -0,0 +1,4 @@
export interface ScriptCode {
readonly execute: string;
readonly revert?: string;
}

View File

@@ -0,0 +1,12 @@
import { DistinctReversibleScriptCode } from './DistinctReversibleScriptCode';
import type { ScriptCode } from './ScriptCode';
export interface ScriptCodeFactory {
(
...args: ConstructorParameters<typeof DistinctReversibleScriptCode>
): ScriptCode;
}
export const createScriptCode: ScriptCodeFactory = (
...args
) => new DistinctReversibleScriptCode(...args);

View File

@@ -0,0 +1,40 @@
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
import { RecommendationLevel } from './RecommendationLevel';
import type { Script } from './Script';
import type { ScriptCode } from './Code/ScriptCode';
export class CollectionScript extends BaseEntity<string> implements Script {
public readonly name: string;
public readonly code: ScriptCode;
public readonly docs: ReadonlyArray<string>;
public readonly level?: RecommendationLevel;
constructor(parameters: ScriptInitParameters) {
super(parameters.name);
this.name = parameters.name;
this.code = parameters.code;
this.docs = parameters.docs;
this.level = parameters.level;
validateLevel(parameters.level);
}
public canRevert(): boolean {
return Boolean(this.code.revert);
}
}
export interface ScriptInitParameters {
readonly name: string;
readonly code: ScriptCode;
readonly docs: ReadonlyArray<string>;
readonly level?: RecommendationLevel;
}
function validateLevel(level?: RecommendationLevel) {
if (level !== undefined && !(level in RecommendationLevel)) {
throw new Error(`invalid level: ${level}`);
}
}

View File

@@ -0,0 +1,4 @@
export enum RecommendationLevel {
Standard = 0,
Strict = 1,
}

View File

@@ -0,0 +1,11 @@
import { RecommendationLevel } from './RecommendationLevel';
import type { Executable } from '../Executable';
import type { Documentable } from '../Documentable';
import type { ScriptCode } from './Code/ScriptCode';
export interface Script extends Executable<string>, Documentable {
readonly name: string;
readonly level?: RecommendationLevel;
readonly code: ScriptCode;
canRevert(): boolean;
}