add support for shared functions #41
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { IEntity } from '../infrastructure/Entity/IEntity';
|
||||
import { IDocumentable } from './IDocumentable';
|
||||
import { RecommendationLevel } from './RecommendationLevel';
|
||||
import { IScriptCode } from './IScriptCode';
|
||||
|
||||
export interface IScript extends IEntity<string>, IDocumentable {
|
||||
readonly name: string;
|
||||
readonly level?: RecommendationLevel;
|
||||
readonly documentationUrls: ReadonlyArray<string>;
|
||||
readonly code: string;
|
||||
readonly revertCode: string;
|
||||
readonly code: IScriptCode;
|
||||
canRevert(): boolean;
|
||||
}
|
||||
|
||||
4
src/domain/IScriptCode.ts
Normal file
4
src/domain/IScriptCode.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface IScriptCode {
|
||||
readonly execute: string;
|
||||
readonly revert: string;
|
||||
}
|
||||
@@ -1,26 +1,22 @@
|
||||
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
|
||||
import { IScript } from './IScript';
|
||||
import { RecommendationLevel } from './RecommendationLevel';
|
||||
import { IScriptCode } from './IScriptCode';
|
||||
|
||||
export class Script extends BaseEntity<string> implements IScript {
|
||||
constructor(
|
||||
public readonly name: string,
|
||||
public readonly code: string,
|
||||
public readonly revertCode: string,
|
||||
public readonly code: IScriptCode,
|
||||
public readonly documentationUrls: ReadonlyArray<string>,
|
||||
public readonly level?: RecommendationLevel) {
|
||||
super(name);
|
||||
validateCode(name, code);
|
||||
validateLevel(level);
|
||||
if (revertCode) {
|
||||
validateCode(name, revertCode);
|
||||
if (code === revertCode) {
|
||||
throw new Error(`${name}: Code itself and its reverting code cannot be the same`);
|
||||
}
|
||||
if (!code) {
|
||||
throw new Error(`undefined code (script: ${name})`);
|
||||
}
|
||||
validateLevel(level);
|
||||
}
|
||||
public canRevert(): boolean {
|
||||
return Boolean(this.revertCode);
|
||||
return Boolean(this.code.revert);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,40 +25,3 @@ function validateLevel(level?: RecommendationLevel) {
|
||||
throw new Error(`invalid level: ${level}`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateCode(name: string, code: string): void {
|
||||
if (!code || code.length === 0) {
|
||||
throw new Error(`Code of ${name} is empty or null`);
|
||||
}
|
||||
ensureCodeHasUniqueLines(name, code);
|
||||
ensureNoEmptyLines(name, code);
|
||||
}
|
||||
|
||||
function ensureNoEmptyLines(name: string, code: string): void {
|
||||
if (code.split('\n').some((line) => line.trim().length === 0)) {
|
||||
throw Error(`Script has empty lines "${name}"`);
|
||||
}
|
||||
}
|
||||
|
||||
function mayBeUniqueLine(codeLine: string): boolean {
|
||||
const trimmed = codeLine.trim();
|
||||
if (trimmed === ')' || trimmed === '(') { // "(" and ")" are used often in batch code
|
||||
return false;
|
||||
}
|
||||
if (codeLine.startsWith(':: ') || codeLine.startsWith('REM ')) { // Is comment?
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function ensureCodeHasUniqueLines(name: string, code: string): void {
|
||||
const lines = code.split('\n')
|
||||
.filter((line) => mayBeUniqueLine(line));
|
||||
if (lines.length === 0) {
|
||||
return;
|
||||
}
|
||||
const duplicateLines = lines.filter((e, i, a) => a.indexOf(e) !== i);
|
||||
if (duplicateLines.length !== 0) {
|
||||
throw Error(`Duplicates detected in script "${name}":\n ${duplicateLines.join('\n')}`);
|
||||
}
|
||||
}
|
||||
|
||||
57
src/domain/ScriptCode.ts
Normal file
57
src/domain/ScriptCode.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { IScriptCode } from './IScriptCode';
|
||||
|
||||
export class ScriptCode implements IScriptCode {
|
||||
constructor(
|
||||
scriptName: string,
|
||||
public readonly execute: string,
|
||||
public readonly revert: string) {
|
||||
if (!scriptName) {
|
||||
throw new Error('script name is undefined');
|
||||
}
|
||||
validateCode(scriptName, execute);
|
||||
if (revert) {
|
||||
scriptName = `${scriptName} (revert)`;
|
||||
validateCode(scriptName, revert);
|
||||
if (execute === revert) {
|
||||
throw new Error(`${scriptName}: Code itself and its reverting code cannot be the same`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateCode(name: string, code: string): void {
|
||||
if (!code || code.length === 0) {
|
||||
throw new Error(`code of ${name} is empty or undefined`);
|
||||
}
|
||||
ensureCodeHasUniqueLines(name, code);
|
||||
ensureNoEmptyLines(name, code);
|
||||
}
|
||||
|
||||
function ensureNoEmptyLines(name: string, code: string): void {
|
||||
if (code.split('\n').some((line) => line.trim().length === 0)) {
|
||||
throw Error(`Script has empty lines "${name}"`);
|
||||
}
|
||||
}
|
||||
|
||||
function ensureCodeHasUniqueLines(name: string, code: string): void {
|
||||
const lines = code.split('\n')
|
||||
.filter((line) => mayBeUniqueLine(line));
|
||||
if (lines.length === 0) {
|
||||
return;
|
||||
}
|
||||
const duplicateLines = lines.filter((e, i, a) => a.indexOf(e) !== i);
|
||||
if (duplicateLines.length !== 0) {
|
||||
throw Error(`Duplicates detected in script "${name}":\n ${duplicateLines.join('\n')}`);
|
||||
}
|
||||
}
|
||||
|
||||
function mayBeUniqueLine(codeLine: string): boolean {
|
||||
const trimmed = codeLine.trim();
|
||||
if (trimmed === ')' || trimmed === '(') { // "(" and ")" are used often in batch code
|
||||
return false;
|
||||
}
|
||||
if (codeLine.startsWith(':: ') || codeLine.startsWith('REM ')) { // Is comment?
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user