Add type validation for parameters and fix types
This commit introduces type validation for parameter values within the parser/compiler, aligning with the YAML schema. It aims to eliminate dependencies on side effects in the collection files. This update changes the treatment of data types in the Windows collection, moving away from unintended type casting by the compiler. Previously, numeric and boolean values were used even though only string types were supported. This behavior was unstable and untested, and has now been adjusted to use strings exclusively. Changes ensure that parameter values are correctly validated as strings, enhancing stability and maintainability.
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
import type { PropertyKeys } from '@/TypeHelpers';
|
import type { PropertyKeys } from '@/TypeHelpers';
|
||||||
import { isNullOrUndefined, isArray, isPlainObject } from '@/TypeHelpers';
|
import {
|
||||||
|
isNullOrUndefined, isArray, isPlainObject, isString,
|
||||||
|
} from '@/TypeHelpers';
|
||||||
|
|
||||||
export interface TypeValidator {
|
export interface TypeValidator {
|
||||||
assertObject<T>(assertion: ObjectAssertion<T>): void;
|
assertObject<T>(assertion: ObjectAssertion<T>): void;
|
||||||
assertNonEmptyCollection(assertion: NonEmptyCollectionAssertion): void;
|
assertNonEmptyCollection(assertion: NonEmptyCollectionAssertion): void;
|
||||||
|
assertNonEmptyString(assertion: NonEmptyStringAssertion): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NonEmptyCollectionAssertion {
|
export interface NonEmptyCollectionAssertion {
|
||||||
@@ -11,6 +14,17 @@ export interface NonEmptyCollectionAssertion {
|
|||||||
readonly valueName: string;
|
readonly valueName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RegexValidationRule {
|
||||||
|
readonly expectedMatch: RegExp;
|
||||||
|
readonly errorMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NonEmptyStringAssertion {
|
||||||
|
readonly value: unknown;
|
||||||
|
readonly valueName: string;
|
||||||
|
readonly rule?: RegexValidationRule;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ObjectAssertion<T> {
|
export interface ObjectAssertion<T> {
|
||||||
readonly value: T | unknown;
|
readonly value: T | unknown;
|
||||||
readonly valueName: string;
|
readonly valueName: string;
|
||||||
@@ -33,6 +47,18 @@ export function createTypeValidator(): TypeValidator {
|
|||||||
assertArray(assertion.value, assertion.valueName);
|
assertArray(assertion.value, assertion.valueName);
|
||||||
assertNonEmpty(assertion.value, assertion.valueName);
|
assertNonEmpty(assertion.value, assertion.valueName);
|
||||||
},
|
},
|
||||||
|
assertNonEmptyString: (assertion) => {
|
||||||
|
assertDefined(assertion.value, assertion.valueName);
|
||||||
|
assertString(assertion.value, assertion.valueName);
|
||||||
|
if (assertion.value.length === 0) {
|
||||||
|
throw new Error(`'${assertion.valueName}' is missing.`);
|
||||||
|
}
|
||||||
|
if (assertion.rule) {
|
||||||
|
if (!assertion.value.match(assertion.rule.expectedMatch)) {
|
||||||
|
throw new Error(assertion.rule.errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +112,15 @@ function assertArray(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertString(
|
||||||
|
value: unknown,
|
||||||
|
valueName: string,
|
||||||
|
): asserts value is string {
|
||||||
|
if (!isString(value)) {
|
||||||
|
throw new Error(`'${valueName}' should be of type 'string', but is of type '${typeof value}'.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function assertNonEmpty(
|
function assertNonEmpty(
|
||||||
value: Array<unknown>,
|
value: Array<unknown>,
|
||||||
valueName: string,
|
valueName: string,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { createPositionFromRegexFullMatch, type ExpressionPositionFactory } from
|
|||||||
import { createFunctionParameterCollection, type FunctionParameterCollectionFactory } from '../../../Function/Parameter/FunctionParameterCollectionFactory';
|
import { createFunctionParameterCollection, type FunctionParameterCollectionFactory } from '../../../Function/Parameter/FunctionParameterCollectionFactory';
|
||||||
import type { IExpressionParser } from '../IExpressionParser';
|
import type { IExpressionParser } from '../IExpressionParser';
|
||||||
import type { IExpression } from '../../Expression/IExpression';
|
import type { IExpression } from '../../Expression/IExpression';
|
||||||
import type { IFunctionParameter } from '../../../Function/Parameter/IFunctionParameter';
|
import type { FunctionParameter } from '../../../Function/Parameter/FunctionParameter';
|
||||||
import type { IFunctionParameterCollection, IReadOnlyFunctionParameterCollection } from '../../../Function/Parameter/IFunctionParameterCollection';
|
import type { IFunctionParameterCollection, IReadOnlyFunctionParameterCollection } from '../../../Function/Parameter/IFunctionParameterCollection';
|
||||||
|
|
||||||
export interface RegexParserUtilities {
|
export interface RegexParserUtilities {
|
||||||
@@ -110,7 +110,7 @@ function createParameters(
|
|||||||
|
|
||||||
export interface PrimitiveExpression {
|
export interface PrimitiveExpression {
|
||||||
readonly evaluator: ExpressionEvaluator;
|
readonly evaluator: ExpressionEvaluator;
|
||||||
readonly parameters?: readonly IFunctionParameter[];
|
readonly parameters?: readonly FunctionParameter[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExpressionFactory {
|
export interface ExpressionFactory {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { FunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameter';
|
|
||||||
import { RegexParser, type PrimitiveExpression } from '../Parser/Regex/RegexParser';
|
import { RegexParser, type PrimitiveExpression } from '../Parser/Regex/RegexParser';
|
||||||
import { ExpressionRegexBuilder } from '../Parser/Regex/ExpressionRegexBuilder';
|
import { ExpressionRegexBuilder } from '../Parser/Regex/ExpressionRegexBuilder';
|
||||||
|
|
||||||
@@ -16,7 +15,10 @@ export class ParameterSubstitutionParser extends RegexParser {
|
|||||||
const parameterName = match[1];
|
const parameterName = match[1];
|
||||||
const pipeline = match[2];
|
const pipeline = match[2];
|
||||||
return {
|
return {
|
||||||
parameters: [new FunctionParameter(parameterName, false)],
|
parameters: [{
|
||||||
|
name: parameterName,
|
||||||
|
isOptional: false,
|
||||||
|
}],
|
||||||
evaluator: (context) => {
|
evaluator: (context) => {
|
||||||
const { argumentValue } = context.args.getArgument(parameterName);
|
const { argumentValue } = context.args.getArgument(parameterName);
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// eslint-disable-next-line max-classes-per-file
|
// eslint-disable-next-line max-classes-per-file
|
||||||
import type { IExpressionParser } from '@/application/Parser/Executable/Script/Compiler/Expressions/Parser/IExpressionParser';
|
import type { IExpressionParser } from '@/application/Parser/Executable/Script/Compiler/Expressions/Parser/IExpressionParser';
|
||||||
import { FunctionParameterCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterCollection';
|
import { FunctionParameterCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterCollection';
|
||||||
import { FunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameter';
|
|
||||||
import { ExpressionPosition } from '../Expression/ExpressionPosition';
|
import { ExpressionPosition } from '../Expression/ExpressionPosition';
|
||||||
import { ExpressionRegexBuilder } from '../Parser/Regex/ExpressionRegexBuilder';
|
import { ExpressionRegexBuilder } from '../Parser/Regex/ExpressionRegexBuilder';
|
||||||
import { createPositionFromRegexFullMatch } from '../Expression/ExpressionPositionFactory';
|
import { createPositionFromRegexFullMatch } from '../Expression/ExpressionPositionFactory';
|
||||||
@@ -84,7 +83,10 @@ class WithStatementBuilder {
|
|||||||
|
|
||||||
public buildExpression(endExpressionPosition: ExpressionPosition, input: string): IExpression {
|
public buildExpression(endExpressionPosition: ExpressionPosition, input: string): IExpression {
|
||||||
const parameters = new FunctionParameterCollection();
|
const parameters = new FunctionParameterCollection();
|
||||||
parameters.addParameter(new FunctionParameter(this.parameterName, true));
|
parameters.addParameter({
|
||||||
|
name: this.parameterName,
|
||||||
|
isOptional: true,
|
||||||
|
});
|
||||||
const position = new ExpressionPosition(
|
const position = new ExpressionPosition(
|
||||||
this.startExpressionPosition.start,
|
this.startExpressionPosition.start,
|
||||||
endExpressionPosition.end,
|
endExpressionPosition.end,
|
||||||
|
|||||||
@@ -1,14 +1,41 @@
|
|||||||
import { ensureValidParameterName } from '../../Shared/ParameterNameValidator';
|
import { createTypeValidator, type TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
||||||
import type { IFunctionCallArgument } from './IFunctionCallArgument';
|
import { validateParameterName, type ParameterNameValidator } from '@/application/Parser/Executable/Script/Compiler/Function/Shared/ParameterNameValidator';
|
||||||
|
|
||||||
export class FunctionCallArgument implements IFunctionCallArgument {
|
export interface FunctionCallArgument {
|
||||||
constructor(
|
readonly parameterName: string;
|
||||||
public readonly parameterName: string,
|
readonly argumentValue: string;
|
||||||
public readonly argumentValue: string,
|
|
||||||
) {
|
|
||||||
ensureValidParameterName(parameterName);
|
|
||||||
if (!argumentValue) {
|
|
||||||
throw new Error(`Missing argument value for the parameter "${parameterName}".`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FunctionCallArgumentFactory {
|
||||||
|
(
|
||||||
|
parameterName: string,
|
||||||
|
argumentValue: string,
|
||||||
|
utilities?: FunctionCallArgumentFactoryUtilities,
|
||||||
|
): FunctionCallArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createFunctionCallArgument: FunctionCallArgumentFactory = (
|
||||||
|
parameterName: string,
|
||||||
|
argumentValue: string,
|
||||||
|
utilities: FunctionCallArgumentFactoryUtilities = DefaultUtilities,
|
||||||
|
): FunctionCallArgument => {
|
||||||
|
utilities.validateParameterName(parameterName);
|
||||||
|
utilities.typeValidator.assertNonEmptyString({
|
||||||
|
value: argumentValue,
|
||||||
|
valueName: `Missing argument value for the parameter "${parameterName}".`,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
parameterName,
|
||||||
|
argumentValue,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
interface FunctionCallArgumentFactoryUtilities {
|
||||||
|
readonly typeValidator: TypeValidator;
|
||||||
|
readonly validateParameterName: ParameterNameValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DefaultUtilities: FunctionCallArgumentFactoryUtilities = {
|
||||||
|
typeValidator: createTypeValidator(),
|
||||||
|
validateParameterName,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { IFunctionCallArgument } from './IFunctionCallArgument';
|
import type { FunctionCallArgument } from './FunctionCallArgument';
|
||||||
import type { IFunctionCallArgumentCollection } from './IFunctionCallArgumentCollection';
|
import type { IFunctionCallArgumentCollection } from './IFunctionCallArgumentCollection';
|
||||||
|
|
||||||
export class FunctionCallArgumentCollection implements IFunctionCallArgumentCollection {
|
export class FunctionCallArgumentCollection implements IFunctionCallArgumentCollection {
|
||||||
private readonly arguments = new Map<string, IFunctionCallArgument>();
|
private readonly arguments = new Map<string, FunctionCallArgument>();
|
||||||
|
|
||||||
public addArgument(argument: IFunctionCallArgument): void {
|
public addArgument(argument: FunctionCallArgument): void {
|
||||||
if (this.hasArgument(argument.parameterName)) {
|
if (this.hasArgument(argument.parameterName)) {
|
||||||
throw new Error(`argument value for parameter ${argument.parameterName} is already provided`);
|
throw new Error(`argument value for parameter ${argument.parameterName} is already provided`);
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ export class FunctionCallArgumentCollection implements IFunctionCallArgumentColl
|
|||||||
return this.arguments.has(parameterName);
|
return this.arguments.has(parameterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getArgument(parameterName: string): IFunctionCallArgument {
|
public getArgument(parameterName: string): FunctionCallArgument {
|
||||||
if (!parameterName) {
|
if (!parameterName) {
|
||||||
throw new Error('missing parameter name');
|
throw new Error('missing parameter name');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface IFunctionCallArgument {
|
|
||||||
readonly parameterName: string;
|
|
||||||
readonly argumentValue: string;
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { IFunctionCallArgument } from './IFunctionCallArgument';
|
import type { FunctionCallArgument } from './FunctionCallArgument';
|
||||||
|
|
||||||
export interface IReadOnlyFunctionCallArgumentCollection {
|
export interface IReadOnlyFunctionCallArgumentCollection {
|
||||||
getArgument(parameterName: string): IFunctionCallArgument;
|
getArgument(parameterName: string): FunctionCallArgument;
|
||||||
getAllParameterNames(): string[];
|
getAllParameterNames(): string[];
|
||||||
hasArgument(parameterName: string): boolean;
|
hasArgument(parameterName: string): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFunctionCallArgumentCollection extends IReadOnlyFunctionCallArgumentCollection {
|
export interface IFunctionCallArgumentCollection extends IReadOnlyFunctionCallArgumentCollection {
|
||||||
addArgument(argument: IFunctionCallArgument): void;
|
addArgument(argument: FunctionCallArgument): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
|
import type { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||||
import { FunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
|
||||||
import { FunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
import { FunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
||||||
import { ExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/ExpressionsCompiler';
|
import { ExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/ExpressionsCompiler';
|
||||||
import type { IExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/IExpressionsCompiler';
|
import type { IExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||||
@@ -7,14 +6,11 @@ import type { FunctionCall } from '@/application/Parser/Executable/Script/Compil
|
|||||||
import type { FunctionCallCompilationContext } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
import type { FunctionCallCompilationContext } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Compiler/FunctionCallCompilationContext';
|
||||||
import { ParsedFunctionCall } from '@/application/Parser/Executable/Script/Compiler/Function/Call/ParsedFunctionCall';
|
import { ParsedFunctionCall } from '@/application/Parser/Executable/Script/Compiler/Function/Call/ParsedFunctionCall';
|
||||||
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||||
|
import { createFunctionCallArgument, type FunctionCallArgument, type FunctionCallArgumentFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
import type { ArgumentCompiler } from './ArgumentCompiler';
|
import type { ArgumentCompiler } from './ArgumentCompiler';
|
||||||
|
|
||||||
export class NestedFunctionArgumentCompiler implements ArgumentCompiler {
|
export class NestedFunctionArgumentCompiler implements ArgumentCompiler {
|
||||||
constructor(
|
constructor(private readonly utilities: ArgumentCompilationUtilities = DefaultUtilities) { }
|
||||||
private readonly expressionsCompiler: IExpressionsCompiler = new ExpressionsCompiler(),
|
|
||||||
private readonly wrapError: ErrorWithContextWrapper
|
|
||||||
= wrapErrorWithAdditionalContext,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
public createCompiledNestedCall(
|
public createCompiledNestedCall(
|
||||||
nestedFunction: FunctionCall,
|
nestedFunction: FunctionCall,
|
||||||
@@ -25,10 +21,7 @@ export class NestedFunctionArgumentCompiler implements ArgumentCompiler {
|
|||||||
nestedFunction,
|
nestedFunction,
|
||||||
parentFunction.args,
|
parentFunction.args,
|
||||||
context,
|
context,
|
||||||
{
|
this.utilities,
|
||||||
expressionsCompiler: this.expressionsCompiler,
|
|
||||||
wrapError: this.wrapError,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const compiledCall = new ParsedFunctionCall(nestedFunction.functionName, compiledArgs);
|
const compiledCall = new ParsedFunctionCall(nestedFunction.functionName, compiledArgs);
|
||||||
return compiledCall;
|
return compiledCall;
|
||||||
@@ -38,6 +31,7 @@ export class NestedFunctionArgumentCompiler implements ArgumentCompiler {
|
|||||||
interface ArgumentCompilationUtilities {
|
interface ArgumentCompilationUtilities {
|
||||||
readonly expressionsCompiler: IExpressionsCompiler,
|
readonly expressionsCompiler: IExpressionsCompiler,
|
||||||
readonly wrapError: ErrorWithContextWrapper;
|
readonly wrapError: ErrorWithContextWrapper;
|
||||||
|
readonly createCallArgument: FunctionCallArgumentFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileNestedFunctionArguments(
|
function compileNestedFunctionArguments(
|
||||||
@@ -78,7 +72,7 @@ function compileNestedFunctionArguments(
|
|||||||
.map(({
|
.map(({
|
||||||
parameterName,
|
parameterName,
|
||||||
compiledArgumentValue,
|
compiledArgumentValue,
|
||||||
}) => new FunctionCallArgument(parameterName, compiledArgumentValue));
|
}) => utilities.createCallArgument(parameterName, compiledArgumentValue));
|
||||||
return buildArgumentCollectionFromArguments(compiledArguments);
|
return buildArgumentCollectionFromArguments(compiledArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,3 +112,9 @@ function buildArgumentCollectionFromArguments(
|
|||||||
return compiledArgs;
|
return compiledArgs;
|
||||||
}, new FunctionCallArgumentCollection());
|
}, new FunctionCallArgumentCollection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DefaultUtilities: ArgumentCompilationUtilities = {
|
||||||
|
expressionsCompiler: new ExpressionsCompiler(),
|
||||||
|
wrapError: wrapErrorWithAdditionalContext,
|
||||||
|
createCallArgument: createFunctionCallArgument,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,24 +1,38 @@
|
|||||||
import type { FunctionCallData, FunctionCallsData, FunctionCallParametersData } from '@/application/collections/';
|
import type {
|
||||||
|
FunctionCallData,
|
||||||
|
FunctionCallsData,
|
||||||
|
FunctionCallParametersData,
|
||||||
|
} from '@/application/collections/';
|
||||||
import { isArray, isPlainObject } from '@/TypeHelpers';
|
import { isArray, isPlainObject } from '@/TypeHelpers';
|
||||||
import { createTypeValidator, type TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
import { createTypeValidator, type TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
||||||
import { FunctionCallArgumentCollection } from './Argument/FunctionCallArgumentCollection';
|
import { FunctionCallArgumentCollection } from './Argument/FunctionCallArgumentCollection';
|
||||||
import { FunctionCallArgument } from './Argument/FunctionCallArgument';
|
|
||||||
import { ParsedFunctionCall } from './ParsedFunctionCall';
|
import { ParsedFunctionCall } from './ParsedFunctionCall';
|
||||||
|
import { createFunctionCallArgument, type FunctionCallArgumentFactory } from './Argument/FunctionCallArgument';
|
||||||
import type { FunctionCall } from './FunctionCall';
|
import type { FunctionCall } from './FunctionCall';
|
||||||
|
|
||||||
export interface FunctionCallsParser {
|
export interface FunctionCallsParser {
|
||||||
(
|
(
|
||||||
calls: FunctionCallsData,
|
calls: FunctionCallsData,
|
||||||
validator?: TypeValidator,
|
utilities?: FunctionCallParsingUtilities,
|
||||||
): FunctionCall[];
|
): FunctionCall[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FunctionCallParsingUtilities {
|
||||||
|
readonly typeValidator: TypeValidator;
|
||||||
|
readonly createCallArgument: FunctionCallArgumentFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DefaultUtilities: FunctionCallParsingUtilities = {
|
||||||
|
typeValidator: createTypeValidator(),
|
||||||
|
createCallArgument: createFunctionCallArgument,
|
||||||
|
};
|
||||||
|
|
||||||
export const parseFunctionCalls: FunctionCallsParser = (
|
export const parseFunctionCalls: FunctionCallsParser = (
|
||||||
calls,
|
calls,
|
||||||
validator = createTypeValidator(),
|
utilities = DefaultUtilities,
|
||||||
) => {
|
) => {
|
||||||
const sequence = getCallSequence(calls, validator);
|
const sequence = getCallSequence(calls, utilities.typeValidator);
|
||||||
return sequence.map((call) => parseFunctionCall(call, validator));
|
return sequence.map((call) => parseFunctionCall(call, utilities));
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCallSequence(calls: FunctionCallsData, validator: TypeValidator): FunctionCallData[] {
|
function getCallSequence(calls: FunctionCallsData, validator: TypeValidator): FunctionCallData[] {
|
||||||
@@ -38,23 +52,27 @@ function getCallSequence(calls: FunctionCallsData, validator: TypeValidator): Fu
|
|||||||
|
|
||||||
function parseFunctionCall(
|
function parseFunctionCall(
|
||||||
call: FunctionCallData,
|
call: FunctionCallData,
|
||||||
validator: TypeValidator,
|
utilities: FunctionCallParsingUtilities,
|
||||||
): FunctionCall {
|
): FunctionCall {
|
||||||
validator.assertObject({
|
utilities.typeValidator.assertObject({
|
||||||
value: call,
|
value: call,
|
||||||
valueName: 'function call',
|
valueName: 'function call',
|
||||||
allowedProperties: ['function', 'parameters'],
|
allowedProperties: ['function', 'parameters'],
|
||||||
});
|
});
|
||||||
const callArgs = parseArgs(call.parameters);
|
const callArgs = parseArgs(call.parameters, utilities.createCallArgument);
|
||||||
return new ParsedFunctionCall(call.function, callArgs);
|
return new ParsedFunctionCall(call.function, callArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseArgs(
|
function parseArgs(
|
||||||
parameters: FunctionCallParametersData | undefined,
|
parameters: FunctionCallParametersData | undefined,
|
||||||
|
createArgument: FunctionCallArgumentFactory,
|
||||||
): FunctionCallArgumentCollection {
|
): FunctionCallArgumentCollection {
|
||||||
const parametersMap = parameters ?? {};
|
const parametersMap = parameters ?? {};
|
||||||
return Object.keys(parametersMap)
|
return Object.keys(parametersMap)
|
||||||
.map((parameterName) => new FunctionCallArgument(parameterName, parametersMap[parameterName]))
|
.map((parameterName) => {
|
||||||
|
const argumentValue = parametersMap[parameterName];
|
||||||
|
return createArgument(parameterName, argumentValue);
|
||||||
|
})
|
||||||
.reduce((args, arg) => {
|
.reduce((args, arg) => {
|
||||||
args.addArgument(arg);
|
args.addArgument(arg);
|
||||||
return args;
|
return args;
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import { ensureValidParameterName } from '../Shared/ParameterNameValidator';
|
export interface FunctionParameter {
|
||||||
import type { IFunctionParameter } from './IFunctionParameter';
|
readonly name: string;
|
||||||
|
readonly isOptional: boolean;
|
||||||
export class FunctionParameter implements IFunctionParameter {
|
|
||||||
constructor(
|
|
||||||
public readonly name: string,
|
|
||||||
public readonly isOptional: boolean,
|
|
||||||
) {
|
|
||||||
ensureValidParameterName(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import type { IFunctionParameterCollection } from './IFunctionParameterCollection';
|
import type { IFunctionParameterCollection } from './IFunctionParameterCollection';
|
||||||
import type { IFunctionParameter } from './IFunctionParameter';
|
import type { FunctionParameter } from './FunctionParameter';
|
||||||
|
|
||||||
export class FunctionParameterCollection implements IFunctionParameterCollection {
|
export class FunctionParameterCollection implements IFunctionParameterCollection {
|
||||||
private parameters = new Array<IFunctionParameter>();
|
private parameters = new Array<FunctionParameter>();
|
||||||
|
|
||||||
public get all(): readonly IFunctionParameter[] {
|
public get all(): readonly FunctionParameter[] {
|
||||||
return this.parameters;
|
return this.parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addParameter(parameter: IFunctionParameter) {
|
public addParameter(parameter: FunctionParameter) {
|
||||||
this.ensureValidParameter(parameter);
|
this.ensureValidParameter(parameter);
|
||||||
this.parameters.push(parameter);
|
this.parameters.push(parameter);
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ export class FunctionParameterCollection implements IFunctionParameterCollection
|
|||||||
return this.parameters.find((existingParameter) => existingParameter.name === name);
|
return this.parameters.find((existingParameter) => existingParameter.name === name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ensureValidParameter(parameter: IFunctionParameter) {
|
private ensureValidParameter(parameter: FunctionParameter) {
|
||||||
if (this.includesName(parameter.name)) {
|
if (this.includesName(parameter.name)) {
|
||||||
throw new Error(`duplicate parameter name: "${parameter.name}"`);
|
throw new Error(`duplicate parameter name: "${parameter.name}"`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import type { ParameterDefinitionData } from '@/application/collections/';
|
||||||
|
import { validateParameterName, type ParameterNameValidator } from '../Shared/ParameterNameValidator';
|
||||||
|
import type { FunctionParameter } from './FunctionParameter';
|
||||||
|
|
||||||
|
export interface FunctionParameterParser {
|
||||||
|
(
|
||||||
|
data: ParameterDefinitionData,
|
||||||
|
validator?: ParameterNameValidator,
|
||||||
|
): FunctionParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const parseFunctionParameter: FunctionParameterParser = (
|
||||||
|
data,
|
||||||
|
validator = validateParameterName,
|
||||||
|
) => {
|
||||||
|
validator(data.name);
|
||||||
|
return {
|
||||||
|
name: data.name,
|
||||||
|
isOptional: data.optional || false,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface IFunctionParameter {
|
|
||||||
readonly name: string;
|
|
||||||
readonly isOptional: boolean;
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { IFunctionParameter } from './IFunctionParameter';
|
import type { FunctionParameter } from './FunctionParameter';
|
||||||
|
|
||||||
export interface IReadOnlyFunctionParameterCollection {
|
export interface IReadOnlyFunctionParameterCollection {
|
||||||
readonly all: readonly IFunctionParameter[];
|
readonly all: readonly FunctionParameter[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFunctionParameterCollection extends IReadOnlyFunctionParameterCollection {
|
export interface IFunctionParameterCollection extends IReadOnlyFunctionParameterCollection {
|
||||||
addParameter(parameter: IFunctionParameter): void;
|
addParameter(parameter: FunctionParameter): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,22 @@
|
|||||||
export function ensureValidParameterName(parameterName: string) {
|
import { createTypeValidator, type TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
||||||
if (!parameterName) {
|
|
||||||
throw new Error('missing parameter name');
|
export interface ParameterNameValidator {
|
||||||
}
|
(
|
||||||
if (!parameterName.match(/^[0-9a-zA-Z]+$/)) {
|
parameterName: string,
|
||||||
throw new Error(`parameter name must be alphanumeric but it was "${parameterName}"`);
|
typeValidator?: TypeValidator,
|
||||||
}
|
): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const validateParameterName = (
|
||||||
|
parameterName: string,
|
||||||
|
typeValidator = createTypeValidator(),
|
||||||
|
) => {
|
||||||
|
typeValidator.assertNonEmptyString({
|
||||||
|
value: parameterName,
|
||||||
|
valueName: 'parameter name',
|
||||||
|
rule: {
|
||||||
|
expectedMatch: /^[0-9a-zA-Z]+$/,
|
||||||
|
errorMessage: `parameter name must be alphanumeric but it was "${parameterName}".`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ import { isArray, isNullOrUndefined, isPlainObject } from '@/TypeHelpers';
|
|||||||
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||||
import { createFunctionWithInlineCode, createCallerFunction } from './SharedFunction';
|
import { createFunctionWithInlineCode, createCallerFunction } from './SharedFunction';
|
||||||
import { SharedFunctionCollection } from './SharedFunctionCollection';
|
import { SharedFunctionCollection } from './SharedFunctionCollection';
|
||||||
import { FunctionParameter } from './Parameter/FunctionParameter';
|
|
||||||
import { parseFunctionCalls, type FunctionCallsParser } from './Call/FunctionCallsParser';
|
import { parseFunctionCalls, type FunctionCallsParser } from './Call/FunctionCallsParser';
|
||||||
import { createFunctionParameterCollection, type FunctionParameterCollectionFactory } from './Parameter/FunctionParameterCollectionFactory';
|
import { createFunctionParameterCollection, type FunctionParameterCollectionFactory } from './Parameter/FunctionParameterCollectionFactory';
|
||||||
|
import { parseFunctionParameter, type FunctionParameterParser } from './Parameter/FunctionParameterParser';
|
||||||
|
import type { FunctionParameter } from './Parameter/FunctionParameter';
|
||||||
import type { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
import type { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||||
import type { IReadOnlyFunctionParameterCollection } from './Parameter/IFunctionParameterCollection';
|
import type { IReadOnlyFunctionParameterCollection } from './Parameter/IFunctionParameterCollection';
|
||||||
import type { ISharedFunction } from './ISharedFunction';
|
import type { ISharedFunction } from './ISharedFunction';
|
||||||
@@ -46,7 +47,7 @@ export const parseSharedFunctions: SharedFunctionsParser = (
|
|||||||
|
|
||||||
const DefaultUtilities: SharedFunctionsParsingUtilities = {
|
const DefaultUtilities: SharedFunctionsParsingUtilities = {
|
||||||
wrapError: wrapErrorWithAdditionalContext,
|
wrapError: wrapErrorWithAdditionalContext,
|
||||||
createParameter: (...args) => new FunctionParameter(...args),
|
parseParameter: parseFunctionParameter,
|
||||||
codeValidator: CodeValidator.instance,
|
codeValidator: CodeValidator.instance,
|
||||||
createParameterCollection: createFunctionParameterCollection,
|
createParameterCollection: createFunctionParameterCollection,
|
||||||
parseFunctionCalls,
|
parseFunctionCalls,
|
||||||
@@ -54,16 +55,12 @@ const DefaultUtilities: SharedFunctionsParsingUtilities = {
|
|||||||
|
|
||||||
interface SharedFunctionsParsingUtilities {
|
interface SharedFunctionsParsingUtilities {
|
||||||
readonly wrapError: ErrorWithContextWrapper;
|
readonly wrapError: ErrorWithContextWrapper;
|
||||||
readonly createParameter: FunctionParameterFactory;
|
readonly parseParameter: FunctionParameterParser;
|
||||||
readonly codeValidator: ICodeValidator;
|
readonly codeValidator: ICodeValidator;
|
||||||
readonly createParameterCollection: FunctionParameterCollectionFactory;
|
readonly createParameterCollection: FunctionParameterCollectionFactory;
|
||||||
readonly parseFunctionCalls: FunctionCallsParser;
|
readonly parseFunctionCalls: FunctionCallsParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FunctionParameterFactory = (
|
|
||||||
...args: ConstructorParameters<typeof FunctionParameter>
|
|
||||||
) => FunctionParameter;
|
|
||||||
|
|
||||||
function parseFunction(
|
function parseFunction(
|
||||||
data: FunctionData,
|
data: FunctionData,
|
||||||
syntax: ILanguageSyntax,
|
syntax: ILanguageSyntax,
|
||||||
@@ -100,7 +97,7 @@ function parseParameters(
|
|||||||
utilities: SharedFunctionsParsingUtilities,
|
utilities: SharedFunctionsParsingUtilities,
|
||||||
): IReadOnlyFunctionParameterCollection {
|
): IReadOnlyFunctionParameterCollection {
|
||||||
return (data.parameters || [])
|
return (data.parameters || [])
|
||||||
.map((parameter) => createFunctionParameter(
|
.map((parameter) => parseParameterWithContextualError(
|
||||||
data.name,
|
data.name,
|
||||||
parameter,
|
parameter,
|
||||||
utilities,
|
utilities,
|
||||||
@@ -111,16 +108,13 @@ function parseParameters(
|
|||||||
}, utilities.createParameterCollection());
|
}, utilities.createParameterCollection());
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFunctionParameter(
|
function parseParameterWithContextualError(
|
||||||
functionName: string,
|
functionName: string,
|
||||||
parameterData: ParameterDefinitionData,
|
parameterData: ParameterDefinitionData,
|
||||||
utilities: SharedFunctionsParsingUtilities,
|
utilities: SharedFunctionsParsingUtilities,
|
||||||
): FunctionParameter {
|
): FunctionParameter {
|
||||||
try {
|
try {
|
||||||
return utilities.createParameter(
|
return utilities.parseParameter(parameterData);
|
||||||
parameterData.name,
|
|
||||||
parameterData.optional || false,
|
|
||||||
);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw utilities.wrapError(
|
throw utilities.wrapError(
|
||||||
err,
|
err,
|
||||||
|
|||||||
@@ -4,31 +4,33 @@ import { CompositeExpressionParser } from '@/application/Parser/Executable/Scrip
|
|||||||
import { ExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/ExpressionsCompiler';
|
import { ExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/ExpressionsCompiler';
|
||||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||||
import { FunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
import { FunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
||||||
import { FunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
|
||||||
import type { IExpressionParser } from '@/application/Parser/Executable/Script/Compiler/Expressions/Parser/IExpressionParser';
|
import type { IExpressionParser } from '@/application/Parser/Executable/Script/Compiler/Expressions/Parser/IExpressionParser';
|
||||||
import type { ICodeSubstituter } from './ICodeSubstituter';
|
import { createFunctionCallArgument, type FunctionCallArgumentFactory } from '../Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
|
||||||
export class CodeSubstituter implements ICodeSubstituter {
|
export interface CodeSubstituter {
|
||||||
constructor(
|
(
|
||||||
private readonly compiler: IExpressionsCompiler = createSubstituteCompiler(),
|
code: string,
|
||||||
private readonly date = new Date(),
|
projectDetails: ProjectDetails,
|
||||||
) {
|
utilities?: CodeSubstitutionUtilities,
|
||||||
|
): string;
|
||||||
}
|
|
||||||
|
|
||||||
public substitute(code: string, projectDetails: ProjectDetails): string {
|
|
||||||
if (!code) { throw new Error('missing code'); }
|
|
||||||
const args = new FunctionCallArgumentCollection();
|
|
||||||
const substitute = (name: string, value: string) => args
|
|
||||||
.addArgument(new FunctionCallArgument(name, value));
|
|
||||||
substitute('homepage', projectDetails.homepage);
|
|
||||||
substitute('version', projectDetails.version.toString());
|
|
||||||
substitute('date', this.date.toUTCString());
|
|
||||||
const compiledCode = this.compiler.compileExpressions(code, args);
|
|
||||||
return compiledCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const substituteCode: CodeSubstituter = (
|
||||||
|
code,
|
||||||
|
projectDetails,
|
||||||
|
utilities = DefaultUtilities,
|
||||||
|
) => {
|
||||||
|
if (!code) { throw new Error('missing code'); }
|
||||||
|
const args = new FunctionCallArgumentCollection();
|
||||||
|
const substitute = (name: string, value: string) => args
|
||||||
|
.addArgument(utilities.createCallArgument(name, value));
|
||||||
|
substitute('homepage', projectDetails.homepage);
|
||||||
|
substitute('version', projectDetails.version.toString());
|
||||||
|
substitute('date', utilities.provideDate().toUTCString());
|
||||||
|
const compiledCode = utilities.compiler.compileExpressions(code, args);
|
||||||
|
return compiledCode;
|
||||||
|
};
|
||||||
|
|
||||||
function createSubstituteCompiler(): IExpressionsCompiler {
|
function createSubstituteCompiler(): IExpressionsCompiler {
|
||||||
const parsers: readonly IExpressionParser[] = [
|
const parsers: readonly IExpressionParser[] = [
|
||||||
new ParameterSubstitutionParser(),
|
new ParameterSubstitutionParser(),
|
||||||
@@ -37,3 +39,15 @@ function createSubstituteCompiler(): IExpressionsCompiler {
|
|||||||
const expressionCompiler = new ExpressionsCompiler(parser);
|
const expressionCompiler = new ExpressionsCompiler(parser);
|
||||||
return expressionCompiler;
|
return expressionCompiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CodeSubstitutionUtilities {
|
||||||
|
readonly compiler: IExpressionsCompiler;
|
||||||
|
readonly provideDate: () => Date;
|
||||||
|
readonly createCallArgument: FunctionCallArgumentFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DefaultUtilities: CodeSubstitutionUtilities = {
|
||||||
|
compiler: createSubstituteCompiler(),
|
||||||
|
provideDate: () => new Date(),
|
||||||
|
createCallArgument: createFunctionCallArgument,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
|
||||||
|
|
||||||
export interface ICodeSubstituter {
|
|
||||||
substitute(code: string, projectDetails: ProjectDetails): string;
|
|
||||||
}
|
|
||||||
@@ -5,8 +5,7 @@ import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
|||||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||||
import { createEnumParser, type EnumParser } from '../../Common/Enum';
|
import { createEnumParser, type EnumParser } from '../../Common/Enum';
|
||||||
import { createTypeValidator, type TypeValidator } from '../Common/TypeValidator';
|
import { createTypeValidator, type TypeValidator } from '../Common/TypeValidator';
|
||||||
import { CodeSubstituter } from './CodeSubstituter';
|
import { type CodeSubstituter, substituteCode } from './CodeSubstituter';
|
||||||
import type { ICodeSubstituter } from './ICodeSubstituter';
|
|
||||||
|
|
||||||
export const parseScriptingDefinition: ScriptingDefinitionParser = (
|
export const parseScriptingDefinition: ScriptingDefinitionParser = (
|
||||||
definition,
|
definition,
|
||||||
@@ -15,8 +14,8 @@ export const parseScriptingDefinition: ScriptingDefinitionParser = (
|
|||||||
) => {
|
) => {
|
||||||
validateData(definition, utilities.validator);
|
validateData(definition, utilities.validator);
|
||||||
const language = utilities.languageParser.parseEnum(definition.language, 'language');
|
const language = utilities.languageParser.parseEnum(definition.language, 'language');
|
||||||
const startCode = utilities.codeSubstituter.substitute(definition.startCode, projectDetails);
|
const startCode = utilities.codeSubstituter(definition.startCode, projectDetails);
|
||||||
const endCode = utilities.codeSubstituter.substitute(definition.endCode, projectDetails);
|
const endCode = utilities.codeSubstituter(definition.endCode, projectDetails);
|
||||||
return new ScriptingDefinition(
|
return new ScriptingDefinition(
|
||||||
language,
|
language,
|
||||||
startCode,
|
startCode,
|
||||||
@@ -45,12 +44,12 @@ function validateData(
|
|||||||
|
|
||||||
interface ScriptingDefinitionParserUtilities {
|
interface ScriptingDefinitionParserUtilities {
|
||||||
readonly languageParser: EnumParser<ScriptingLanguage>;
|
readonly languageParser: EnumParser<ScriptingLanguage>;
|
||||||
readonly codeSubstituter: ICodeSubstituter;
|
readonly codeSubstituter: CodeSubstituter;
|
||||||
readonly validator: TypeValidator;
|
readonly validator: TypeValidator;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DefaultUtilities: ScriptingDefinitionParserUtilities = {
|
const DefaultUtilities: ScriptingDefinitionParserUtilities = {
|
||||||
languageParser: createEnumParser(ScriptingLanguage),
|
languageParser: createEnumParser(ScriptingLanguage),
|
||||||
codeSubstituter: new CodeSubstituter(),
|
codeSubstituter: substituteCode,
|
||||||
validator: createTypeValidator(),
|
validator: createTypeValidator(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ actions:
|
|||||||
function: ClearDirectoryContents
|
function: ClearDirectoryContents
|
||||||
parameters:
|
parameters:
|
||||||
directoryGlob: '%USERPROFILE%\Local Settings\Temporary Internet Files'
|
directoryGlob: '%USERPROFILE%\Local Settings\Temporary Internet Files'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 📂 Unprotected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 📂 Unprotected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
function: ClearDirectoryContents
|
function: ClearDirectoryContents
|
||||||
parameters:
|
parameters:
|
||||||
@@ -564,7 +564,7 @@ actions:
|
|||||||
# - C:\Users\undergroundwires\AppData\Local\Microsoft\Windows\Temporary Internet Files\Virtualized
|
# - C:\Users\undergroundwires\AppData\Local\Microsoft\Windows\Temporary Internet Files\Virtualized
|
||||||
# Since Windows 10 22H2 and Windows 11 22H2, data files are observed in this subdirectories but not on the parent.
|
# Since Windows 10 22H2 and Windows 11 22H2, data files are observed in this subdirectories but not on the parent.
|
||||||
# Especially in `IE` folder includes many files. These folders are protected and hidden by default.
|
# Especially in `IE` folder includes many files. These folders are protected and hidden by default.
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
function: ClearDirectoryContents
|
function: ClearDirectoryContents
|
||||||
parameters:
|
parameters:
|
||||||
@@ -573,7 +573,7 @@ actions:
|
|||||||
function: ClearDirectoryContents
|
function: ClearDirectoryContents
|
||||||
parameters:
|
parameters:
|
||||||
directoryGlob: '%LOCALAPPDATA%\Temporary Internet Files'
|
directoryGlob: '%LOCALAPPDATA%\Temporary Internet Files'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
name: Clear Internet Explorer feeds cache
|
name: Clear Internet Explorer feeds cache
|
||||||
recommend: standard
|
recommend: standard
|
||||||
@@ -1217,7 +1217,7 @@ actions:
|
|||||||
function: StopService
|
function: StopService
|
||||||
parameters:
|
parameters:
|
||||||
serviceName: wuauserv
|
serviceName: wuauserv
|
||||||
waitUntilStopped: true
|
waitUntilStopped: 'true'
|
||||||
serviceRestartStateFile: '%APPDATA%\privacy.sexy-wuauserv' # Marked: refactor-with-variables (app dir should be unified, not using %TEMP% as it can be cleaned during operation)
|
serviceRestartStateFile: '%APPDATA%\privacy.sexy-wuauserv' # Marked: refactor-with-variables (app dir should be unified, not using %TEMP% as it can be cleaned during operation)
|
||||||
-
|
-
|
||||||
function: ClearDirectoryContents
|
function: ClearDirectoryContents
|
||||||
@@ -1303,18 +1303,18 @@ actions:
|
|||||||
function: StopService
|
function: StopService
|
||||||
parameters:
|
parameters:
|
||||||
serviceName: DiagTrack
|
serviceName: DiagTrack
|
||||||
waitUntilStopped: true
|
waitUntilStopped: 'true'
|
||||||
serviceRestartStateFile: '%APPDATA%\privacy.sexy-DiagTrack' # Marked: refactor-with-variables (app dir should be unified, not using %TEMP% as it can be cleaned during operation)
|
serviceRestartStateFile: '%APPDATA%\privacy.sexy-DiagTrack' # Marked: refactor-with-variables (app dir should be unified, not using %TEMP% as it can be cleaned during operation)
|
||||||
-
|
-
|
||||||
function: DeleteFiles
|
function: DeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%PROGRAMDATA%\Microsoft\Diagnosis\ETLLogs\AutoLogger\AutoLogger-Diagtrack-Listener.etl'
|
fileGlob: '%PROGRAMDATA%\Microsoft\Diagnosis\ETLLogs\AutoLogger\AutoLogger-Diagtrack-Listener.etl'
|
||||||
grantPermissions: true
|
grantPermissions: 'true'
|
||||||
-
|
-
|
||||||
function: DeleteFiles
|
function: DeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%PROGRAMDATA%\Microsoft\Diagnosis\ETLLogs\ShutdownLogger\AutoLogger-Diagtrack-Listener.etl'
|
fileGlob: '%PROGRAMDATA%\Microsoft\Diagnosis\ETLLogs\ShutdownLogger\AutoLogger-Diagtrack-Listener.etl'
|
||||||
grantPermissions: true
|
grantPermissions: 'true'
|
||||||
-
|
-
|
||||||
function: StartService
|
function: StartService
|
||||||
parameters:
|
parameters:
|
||||||
@@ -1371,7 +1371,7 @@ actions:
|
|||||||
function: ClearDirectoryContents # Otherwise it cannot access/delete files under `Scans\History`, see https://github.com/undergroundwires/privacy.sexy/issues/246
|
function: ClearDirectoryContents # Otherwise it cannot access/delete files under `Scans\History`, see https://github.com/undergroundwires/privacy.sexy/issues/246
|
||||||
parameters:
|
parameters:
|
||||||
directoryGlob: '%ProgramData%\Microsoft\Windows Defender\Scans\History'
|
directoryGlob: '%ProgramData%\Microsoft\Windows Defender\Scans\History'
|
||||||
grantPermissions: true # Running as TrustedInstaller is not needed, and causes Defender to alarm https://github.com/undergroundwires/privacy.sexy/issues/264
|
grantPermissions: 'true' # Running as TrustedInstaller is not needed, and causes Defender to alarm https://github.com/undergroundwires/privacy.sexy/issues/264
|
||||||
-
|
-
|
||||||
name: Clear credentials in Windows Credential Manager
|
name: Clear credentials in Windows Credential Manager
|
||||||
call:
|
call:
|
||||||
@@ -1508,13 +1508,13 @@ actions:
|
|||||||
function: StopService
|
function: StopService
|
||||||
parameters:
|
parameters:
|
||||||
serviceName: DPS
|
serviceName: DPS
|
||||||
waitUntilStopped: true
|
waitUntilStopped: 'true'
|
||||||
serviceRestartStateFile: '%APPDATA%\privacy.sexy-DPS' # Marked: refactor-with-variables (app dir should be unified, not using %TEMP% as it can be cleaned during operation)
|
serviceRestartStateFile: '%APPDATA%\privacy.sexy-DPS' # Marked: refactor-with-variables (app dir should be unified, not using %TEMP% as it can be cleaned during operation)
|
||||||
-
|
-
|
||||||
function: DeleteFiles
|
function: DeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%WINDIR%\System32\sru\SRUDB.dat'
|
fileGlob: '%WINDIR%\System32\sru\SRUDB.dat'
|
||||||
grantPermissions: true
|
grantPermissions: 'true'
|
||||||
-
|
-
|
||||||
function: StartService
|
function: StartService
|
||||||
parameters:
|
parameters:
|
||||||
@@ -1526,7 +1526,7 @@ actions:
|
|||||||
function: DeleteDirectory
|
function: DeleteDirectory
|
||||||
parameters:
|
parameters:
|
||||||
directoryGlob: '%SYSTEMDRIVE%\Windows.old'
|
directoryGlob: '%SYSTEMDRIVE%\Windows.old'
|
||||||
grantPermissions: true
|
grantPermissions: 'true'
|
||||||
-
|
-
|
||||||
category: Disable OS data collection
|
category: Disable OS data collection
|
||||||
children:
|
children:
|
||||||
@@ -2813,7 +2813,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%WINDIR%\System32\CompatTelRunner.exe'
|
fileGlob: '%WINDIR%\System32\CompatTelRunner.exe'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
category: Disable background application compatibility checks (Application Experience scheduled tasks)
|
category: Disable background application compatibility checks (Application Experience scheduled tasks)
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -3037,7 +3037,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\Application Experience\' -TaskName 'SdbinstMergeDbTask'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\Application Experience\' -TaskName 'SdbinstMergeDbTask'
|
||||||
taskPathPattern: \Microsoft\Windows\Application Experience\
|
taskPathPattern: \Microsoft\Windows\Application Experience\
|
||||||
taskNamePattern: SdbinstMergeDbTask
|
taskNamePattern: SdbinstMergeDbTask
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 11 23H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 11 23H2]
|
||||||
-
|
-
|
||||||
name: Disable application backup data gathering (`MareBackup`)
|
name: Disable application backup data gathering (`MareBackup`)
|
||||||
recommend: strict
|
recommend: strict
|
||||||
@@ -5985,12 +5985,12 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%PROGRAMFILES(X86)%\NVIDIA Corporation\NvTelemetry\*'
|
fileGlob: '%PROGRAMFILES(X86)%\NVIDIA Corporation\NvTelemetry\*'
|
||||||
recurse: true
|
recurse: 'true'
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%PROGRAMFILES%\NVIDIA Corporation\NvTelemetry\*'
|
fileGlob: '%PROGRAMFILES%\NVIDIA Corporation\NvTelemetry\*'
|
||||||
recurse: true
|
recurse: 'true'
|
||||||
-
|
-
|
||||||
name: Disable Nvidia telemetry drivers
|
name: Disable Nvidia telemetry drivers
|
||||||
recommend: standard
|
recommend: standard
|
||||||
@@ -5998,7 +5998,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\DriverStore\FileRepository\NvTelemetry*.dll'
|
fileGlob: '%SYSTEMROOT%\System32\DriverStore\FileRepository\NvTelemetry*.dll'
|
||||||
recurse: true
|
recurse: 'true'
|
||||||
-
|
-
|
||||||
name: Disable participation in Nvidia telemetry
|
name: Disable participation in Nvidia telemetry
|
||||||
recommend: standard
|
recommend: standard
|
||||||
@@ -7047,7 +7047,7 @@ actions:
|
|||||||
parameters:
|
parameters:
|
||||||
serviceName: adobeupdateservice # Check: (Get-Service -Name adobeupdateservice).StartType
|
serviceName: adobeupdateservice # Check: (Get-Service -Name adobeupdateservice).StartType
|
||||||
defaultStartupMode: Automatic # Allowed values: Automatic | Manual
|
defaultStartupMode: Automatic # Allowed values: Automatic | Manual
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Adobe Acrobat Update Task" scheduled task
|
name: Disable "Adobe Acrobat Update Task" scheduled task
|
||||||
recommend: standard
|
recommend: standard
|
||||||
@@ -7091,7 +7091,7 @@ actions:
|
|||||||
parameters:
|
parameters:
|
||||||
serviceName: Razer Game Scanner Service # Check: (Get-Service -Name 'Razer Game Scanner Service').StartType
|
serviceName: Razer Game Scanner Service # Check: (Get-Service -Name 'Razer Game Scanner Service').StartType
|
||||||
defaultStartupMode: Manual # Allowed values: Automatic | Manual
|
defaultStartupMode: Manual # Allowed values: Automatic | Manual
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Logitech Gaming Registry Service"
|
name: Disable "Logitech Gaming Registry Service"
|
||||||
recommend: standard
|
recommend: standard
|
||||||
@@ -7415,7 +7415,7 @@ actions:
|
|||||||
function: RequireTLSMinimumKeySize
|
function: RequireTLSMinimumKeySize
|
||||||
parameters:
|
parameters:
|
||||||
algorithmName: Diffie-Hellman
|
algorithmName: Diffie-Hellman
|
||||||
keySizeInBits: 2048
|
keySizeInBits: '2048'
|
||||||
-
|
-
|
||||||
name: Enable strong RSA key requirement (breaks Hyper-V VMs)
|
name: Enable strong RSA key requirement (breaks Hyper-V VMs)
|
||||||
recommend: strict # Microsoft deprecated it and will end support; but breaks Hyper-V VMs, see #363
|
recommend: strict # Microsoft deprecated it and will end support; but breaks Hyper-V VMs, see #363
|
||||||
@@ -7467,8 +7467,8 @@ actions:
|
|||||||
function: RequireTLSMinimumKeySize
|
function: RequireTLSMinimumKeySize
|
||||||
parameters:
|
parameters:
|
||||||
algorithmName: PKCS
|
algorithmName: PKCS
|
||||||
keySizeInBits: 2048
|
keySizeInBits: '2048'
|
||||||
ignoreServerSide: true # Controlled by the specified server certificate
|
ignoreServerSide: 'true' # Controlled by the specified server certificate
|
||||||
-
|
-
|
||||||
category: Disable insecure connections
|
category: Disable insecure connections
|
||||||
docs: |- # refactor-with-variables: Same • Caution
|
docs: |- # refactor-with-variables: Same • Caution
|
||||||
@@ -8140,23 +8140,23 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: SMB1Protocol # Get-WindowsOptionalFeature -FeatureName 'SMB1Protocol' -Online
|
featureName: SMB1Protocol # Get-WindowsOptionalFeature -FeatureName 'SMB1Protocol' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: SMB1Protocol-Client # Get-WindowsOptionalFeature -FeatureName 'SMB1Protocol-Client' -Online
|
featureName: SMB1Protocol-Client # Get-WindowsOptionalFeature -FeatureName 'SMB1Protocol-Client' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: SMB1Protocol-Server # Get-WindowsOptionalFeature -FeatureName 'SMB1Protocol-Server' -Online
|
featureName: SMB1Protocol-Server # Get-WindowsOptionalFeature -FeatureName 'SMB1Protocol-Server' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
function: DisableService
|
function: DisableService
|
||||||
parameters:
|
parameters:
|
||||||
serviceName: mrxsmb10 # Check: (Get-Service -Name 'mrxsmb10').StartType
|
serviceName: mrxsmb10 # Check: (Get-Service -Name 'mrxsmb10').StartType
|
||||||
defaultStartupMode: Automatic # Allowed values: Boot | System | Automatic | Manual
|
defaultStartupMode: Automatic # Allowed values: Boot | System | Automatic | Manual
|
||||||
ignoreMissingOnRevert: true # This service is only available when SMB1 feature is installed
|
ignoreMissingOnRevert: 'true' # This service is only available when SMB1 feature is installed
|
||||||
-
|
-
|
||||||
function: RunInlineCode
|
function: RunInlineCode
|
||||||
# This ensures that `lanmanworkstation` does not depend on `mrxsmb10` to avoid potential system issues.
|
# This ensures that `lanmanworkstation` does not depend on `mrxsmb10` to avoid potential system issues.
|
||||||
@@ -8809,7 +8809,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: TelnetClient # Get-WindowsOptionalFeature -FeatureName 'TelnetClient' -Online
|
featureName: TelnetClient # Get-WindowsOptionalFeature -FeatureName 'TelnetClient' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Remove "RAS Connection Manager Administration Kit (CMAK)" capability
|
name: Remove "RAS Connection Manager Administration Kit (CMAK)" capability
|
||||||
docs: |- # refactor-with-variables: Same • Caution
|
docs: |- # refactor-with-variables: Same • Caution
|
||||||
@@ -9005,7 +9005,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: TFTP # Get-WindowsOptionalFeature -FeatureName 'TFTP' -Online
|
featureName: TFTP # Get-WindowsOptionalFeature -FeatureName 'TFTP' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Remove "RIP Listener" capability
|
name: Remove "RIP Listener" capability
|
||||||
docs: |- # refactor-with-variables: *Caution**
|
docs: |- # refactor-with-variables: *Caution**
|
||||||
@@ -10456,7 +10456,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\drivers\mpsdrv.sys'
|
fileGlob: '%SYSTEMROOT%\System32\drivers\mpsdrv.sys'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
function: ShowComputerRestartSuggestion
|
function: ShowComputerRestartSuggestion
|
||||||
-
|
-
|
||||||
@@ -10527,7 +10527,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%WINDIR%\System32\mpssvc.dll'
|
fileGlob: '%WINDIR%\System32\mpssvc.dll'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
function: ShowComputerRestartSuggestion
|
function: ShowComputerRestartSuggestion
|
||||||
-
|
-
|
||||||
@@ -10783,7 +10783,7 @@ actions:
|
|||||||
property: SubmitSamplesConsent # Status: Get-MpPreference | Select-Object -Property SubmitSamplesConsent
|
property: SubmitSamplesConsent # Status: Get-MpPreference | Select-Object -Property SubmitSamplesConsent
|
||||||
value: "'2'" # Set: Set-MpPreference -Force -SubmitSamplesConsent 2
|
value: "'2'" # Set: Set-MpPreference -Force -SubmitSamplesConsent 2
|
||||||
default: "'1'" # Default: 1 (Send safe samples automatically) | Remove-MpPreference -Force -SubmitSamplesConsent | Set-MpPreference -Force -SubmitSamplesConsent 1
|
default: "'1'" # Default: 1 (Send safe samples automatically) | Remove-MpPreference -Force -SubmitSamplesConsent | Set-MpPreference -Force -SubmitSamplesConsent 1
|
||||||
setDefaultOnWindows11: true # `Remove-MpPreference` sets it to 0 instead 1 (OS default) in Windows 11
|
setDefaultOnWindows11: 'true' # `Remove-MpPreference` sets it to 0 instead 1 (OS default) in Windows 11
|
||||||
-
|
-
|
||||||
function: SetRegistryValue
|
function: SetRegistryValue
|
||||||
parameters:
|
parameters:
|
||||||
@@ -11276,7 +11276,7 @@ actions:
|
|||||||
property: QuarantinePurgeItemsAfterDelay # Status: Get-MpPreference | Select-Object -Property QuarantinePurgeItemsAfterDelay
|
property: QuarantinePurgeItemsAfterDelay # Status: Get-MpPreference | Select-Object -Property QuarantinePurgeItemsAfterDelay
|
||||||
value: "'1'" # Set: Set-MpPreference -Force -QuarantinePurgeItemsAfterDelay 1
|
value: "'1'" # Set: Set-MpPreference -Force -QuarantinePurgeItemsAfterDelay 1
|
||||||
default: "'90'" # Default: 90 | Remove-MpPreference -Force -QuarantinePurgeItemsAfterDelay | Set-MpPreference -Force -QuarantinePurgeItemsAfterDelay 90
|
default: "'90'" # Default: 90 | Remove-MpPreference -Force -QuarantinePurgeItemsAfterDelay | Set-MpPreference -Force -QuarantinePurgeItemsAfterDelay 90
|
||||||
setDefaultOnWindows11: true # `Remove-MpPreference` sets it to 0 instead 90 (OS default) in Windows 11
|
setDefaultOnWindows11: 'true' # `Remove-MpPreference` sets it to 0 instead 90 (OS default) in Windows 11
|
||||||
-
|
-
|
||||||
function: SetRegistryValue
|
function: SetRegistryValue
|
||||||
parameters:
|
parameters:
|
||||||
@@ -11447,7 +11447,7 @@ actions:
|
|||||||
property: DisableAutoExclusions # Status: Get-MpPreference | Select-Object -Property DisableAutoExclusions
|
property: DisableAutoExclusions # Status: Get-MpPreference | Select-Object -Property DisableAutoExclusions
|
||||||
value: $True # Set: Set-MpPreference -Force -DisableAutoExclusions $True
|
value: $True # Set: Set-MpPreference -Force -DisableAutoExclusions $True
|
||||||
default: $False # Default: False | Remove-MpPreference -Force -DisableAutoExclusions | Set-MpPreference -Force -DisableAutoExclusions $False
|
default: $False # Default: False | Remove-MpPreference -Force -DisableAutoExclusions | Set-MpPreference -Force -DisableAutoExclusions $False
|
||||||
setDefaultOnWindows11: true # `Remove-MpPreference` has no affect (does not change the value) in Windows 11
|
setDefaultOnWindows11: 'true' # `Remove-MpPreference` has no affect (does not change the value) in Windows 11
|
||||||
-
|
-
|
||||||
function: SetRegistryValue
|
function: SetRegistryValue
|
||||||
parameters:
|
parameters:
|
||||||
@@ -11935,10 +11935,10 @@ actions:
|
|||||||
-
|
-
|
||||||
function: SetMpPreference
|
function: SetMpPreference
|
||||||
parameters:
|
parameters:
|
||||||
property: ScanParameters # Status: Get-MpPreference | Select-Object -Property ScanParameters
|
property: ScanParameters # Status: Get-MpPreference | Select-Object -Property ScanParameters
|
||||||
value: "'1'" # Set: Set-MpPreference -Force -ScanParameters '1'
|
value: "'1'" # Set: Set-MpPreference -Force -ScanParameters '1'
|
||||||
default: "'1'" # Default: 1 | Remove-MpPreference -Force -ScanParameters | Set-MpPreference -Force -ScanParameters '1'
|
default: "'1'" # Default: 1 | Remove-MpPreference -Force -ScanParameters | Set-MpPreference -Force -ScanParameters '1'
|
||||||
setDefaultOnWindows11: true # ❌ Remove-MpPreference with -ScanParameters fails due to a buggy behavior where it tries to set it to True on Windows 11
|
setDefaultOnWindows11: 'true' # ❌ Remove-MpPreference with -ScanParameters fails due to a buggy behavior where it tries to set it to True on Windows 11
|
||||||
-
|
-
|
||||||
name: Minimize daily quick scan frequency
|
name: Minimize daily quick scan frequency
|
||||||
docs: https://admx.help/?Category=Windows_10_2016&Policy=Microsoft.Policies.WindowsDefender::Scan_QuickScanInterval
|
docs: https://admx.help/?Category=Windows_10_2016&Policy=Microsoft.Policies.WindowsDefender::Scan_QuickScanInterval
|
||||||
@@ -12819,7 +12819,7 @@ actions:
|
|||||||
# function: SoftDeleteFiles
|
# function: SoftDeleteFiles
|
||||||
# parameters:
|
# parameters:
|
||||||
# fileGlob: '%PROGRAMFILES%\Windows Defender\MsMpEng.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
|
# fileGlob: '%PROGRAMFILES%\Windows Defender\MsMpEng.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
|
||||||
# grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
# grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
category: Disable Defender kernel-level drivers
|
category: Disable Defender kernel-level drivers
|
||||||
children:
|
children:
|
||||||
@@ -12840,7 +12840,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\drivers\WdNisDrv.sys'
|
fileGlob: '%SYSTEMROOT%\System32\drivers\WdNisDrv.sys'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
name: Disable "Microsoft Defender Antivirus Mini-Filter Driver" service
|
name: Disable "Microsoft Defender Antivirus Mini-Filter Driver" service
|
||||||
docs:
|
docs:
|
||||||
@@ -12858,7 +12858,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\drivers\WdFilter.sys'
|
fileGlob: '%SYSTEMROOT%\System32\drivers\WdFilter.sys'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
name: Disable "Microsoft Defender Antivirus Boot Driver" service
|
name: Disable "Microsoft Defender Antivirus Boot Driver" service
|
||||||
docs: https://web.archive.org/web/20240314062057/https://batcmd.com/windows/10/services/wdboot/
|
docs: https://web.archive.org/web/20240314062057/https://batcmd.com/windows/10/services/wdboot/
|
||||||
@@ -12874,7 +12874,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\drivers\WdBoot.sys'
|
fileGlob: '%SYSTEMROOT%\System32\drivers\WdBoot.sys'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
name: Disable "Microsoft Defender Antivirus Network Inspection" service
|
name: Disable "Microsoft Defender Antivirus Network Inspection" service
|
||||||
docs:
|
docs:
|
||||||
@@ -12890,7 +12890,7 @@ actions:
|
|||||||
# function: SoftDeleteFiles
|
# function: SoftDeleteFiles
|
||||||
# parameters:
|
# parameters:
|
||||||
# fileGlob: '%PROGRAMFILES%\Windows Defender\NisSrv.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
|
# fileGlob: '%PROGRAMFILES%\Windows Defender\NisSrv.exe' # Found also in C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.2107.4-0 and \4.18.2103.7-0 ...
|
||||||
# grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
# grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
name: Disable "Windows Defender Advanced Threat Protection Service" service
|
name: Disable "Windows Defender Advanced Threat Protection Service" service
|
||||||
docs: https://web.archive.org/web/20240314091443/https://batcmd.com/windows/10/services/sense/
|
docs: https://web.archive.org/web/20240314091443/https://batcmd.com/windows/10/services/sense/
|
||||||
@@ -12904,7 +12904,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%PROGRAMFILES%\Windows Defender Advanced Threat Protection\MsSense.exe'
|
fileGlob: '%PROGRAMFILES%\Windows Defender Advanced Threat Protection\MsSense.exe'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
name: Disable "Windows Security Service" service
|
name: Disable "Windows Security Service" service
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -12939,7 +12939,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%WINDIR%\System32\SecurityHealthService.exe'
|
fileGlob: '%WINDIR%\System32\SecurityHealthService.exe'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 22H2
|
||||||
-
|
-
|
||||||
category: Disable SmartScreen
|
category: Disable SmartScreen
|
||||||
docs:
|
docs:
|
||||||
@@ -13411,7 +13411,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicSvc.dll'
|
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicSvc.dll'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: TerminateAndBlockExecution
|
function: TerminateAndBlockExecution
|
||||||
parameters:
|
parameters:
|
||||||
@@ -13420,38 +13420,38 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicAgent.exe'
|
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicAgent.exe'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔍 Missing on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔍 Missing on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicCapsule.dll'
|
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicCapsule.dll'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔍 Missing on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔍 Missing on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicPS.dll'
|
fileGlob: '%SYSTEMROOT%\System32\WaaSMedicPS.dll'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\WaaSAssessment.dll'
|
fileGlob: '%SYSTEMROOT%\System32\WaaSAssessment.dll'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\Windows.Internal.WaaSMedicDocked.dll'
|
fileGlob: '%SYSTEMROOT%\System32\Windows.Internal.WaaSMedicDocked.dll'
|
||||||
grantPermissions: true # 🔍 Missing on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔍 Missing on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%WINDIR%\UUS\amd64\WaaSMedicSvcImpl.dll'
|
fileGlob: '%WINDIR%\UUS\amd64\WaaSMedicSvcImpl.dll'
|
||||||
grantPermissions: true # 🔍 Missing on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔍 Missing on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
-
|
-
|
||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%WINDIR%\WaaS\*' # Includes `services` and `tasks` folders that defines the desired state configuration on remediation.
|
fileGlob: '%WINDIR%\WaaS\*' # Includes `services` and `tasks` folders that defines the desired state configuration on remediation.
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
recurse: true
|
recurse: 'true'
|
||||||
-
|
-
|
||||||
name: Disable automatically enabling Windows Update Medic Service
|
name: Disable automatically enabling Windows Update Medic Service
|
||||||
recommend: strict
|
recommend: strict
|
||||||
@@ -13491,7 +13491,7 @@ actions:
|
|||||||
function: SoftDeleteFiles
|
function: SoftDeleteFiles
|
||||||
parameters:
|
parameters:
|
||||||
fileGlob: '%SYSTEMROOT%\System32\upfc.exe'
|
fileGlob: '%SYSTEMROOT%\System32\upfc.exe'
|
||||||
grantPermissions: true # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
grantPermissions: 'true' # 🔒️ Protected on Windows 10 since 22H2 | 🔒️ Protected on Windows 11 since 23H2
|
||||||
beforeIteration: |- # Skip Windows versions older than Windows 10 22H2 (build number 19045) to avoid reported blue screen issues.
|
beforeIteration: |- # Skip Windows versions older than Windows 10 22H2 (build number 19045) to avoid reported blue screen issues.
|
||||||
$osVersion = [System.Environment]::OSVersion.Version
|
$osVersion = [System.Environment]::OSVersion.Version
|
||||||
function Test-IsBeforeWin10Version22H2 { ($osVersion.Major -lt 10) -or (($osVersion.Major -eq 10) -and ($osVersion.Build -lt 19045)) }
|
function Test-IsBeforeWin10Version22H2 { ($osVersion.Major -lt 10) -or (($osVersion.Major -eq 10) -and ($osVersion.Build -lt 19045)) }
|
||||||
@@ -13658,7 +13658,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\InstallService\' -TaskName 'WakeUpAndContinueUpdates'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\InstallService\' -TaskName 'WakeUpAndContinueUpdates'
|
||||||
taskPathPattern: \Microsoft\Windows\InstallService\
|
taskPathPattern: \Microsoft\Windows\InstallService\
|
||||||
taskNamePattern: WakeUpAndContinueUpdates
|
taskNamePattern: WakeUpAndContinueUpdates
|
||||||
disableOnRevert: true
|
disableOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "WakeUpAndScanForUpdates" task
|
name: Disable "WakeUpAndScanForUpdates" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13681,7 +13681,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\InstallService\' -TaskName 'WakeUpAndScanForUpdates'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\InstallService\' -TaskName 'WakeUpAndScanForUpdates'
|
||||||
taskPathPattern: \Microsoft\Windows\InstallService\
|
taskPathPattern: \Microsoft\Windows\InstallService\
|
||||||
taskNamePattern: WakeUpAndScanForUpdates
|
taskNamePattern: WakeUpAndScanForUpdates
|
||||||
disableOnRevert: true
|
disableOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Scheduled Start" task
|
name: Disable "Scheduled Start" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13734,7 +13734,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Report policies'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Report policies'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Report policies
|
taskNamePattern: Report policies
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "Schedule Maintenance Work" task
|
name: Disable "Schedule Maintenance Work" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13760,8 +13760,8 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Maintenance Work'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Maintenance Work'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Schedule Maintenance Work
|
taskNamePattern: Schedule Maintenance Work
|
||||||
disableOnRevert: true
|
disableOnRevert: 'true'
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "Schedule Scan" task
|
name: Disable "Schedule Scan" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13786,7 +13786,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Scan'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Scan'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Schedule Scan
|
taskNamePattern: Schedule Scan
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "Schedule Scan Static Task" task
|
name: Disable "Schedule Scan Static Task" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13812,7 +13812,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Scan Static Task'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Scan Static Task'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Schedule Scan Static Task
|
taskNamePattern: Schedule Scan Static Task
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "Schedule Wake To Work" task
|
name: Disable "Schedule Wake To Work" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13837,8 +13837,8 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Wake To Work'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Wake To Work'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Schedule Wake To Work
|
taskNamePattern: Schedule Wake To Work
|
||||||
disableOnRevert: true
|
disableOnRevert: 'true'
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "Schedule Work" task
|
name: Disable "Schedule Work" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13863,8 +13863,8 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Work'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Schedule Work'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Schedule Work
|
taskNamePattern: Schedule Work
|
||||||
disableOnRevert: true
|
disableOnRevert: 'true'
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "UpdateModelTask" task
|
name: Disable "UpdateModelTask" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13894,7 +13894,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'UpdateModelTask'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'UpdateModelTask'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: UpdateModelTask
|
taskNamePattern: UpdateModelTask
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "Start Oobe Expedite Work" task
|
name: Disable "Start Oobe Expedite Work" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13921,7 +13921,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Start Oobe Expedite Work'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'Start Oobe Expedite Work'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: Start Oobe Expedite Work
|
taskNamePattern: Start Oobe Expedite Work
|
||||||
grantPermissions: true # 🔒 No permissions, Tested since [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, Tested since [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "StartOobeAppsScan_LicenseAccepted" task
|
name: Disable "StartOobeAppsScan_LicenseAccepted" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13948,7 +13948,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'StartOobeAppsScan_LicenseAccepted'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'StartOobeAppsScan_LicenseAccepted'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: StartOobeAppsScan_LicenseAccepted
|
taskNamePattern: StartOobeAppsScan_LicenseAccepted
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "StartOobeAppsScan_OobeAppReady" task
|
name: Disable "StartOobeAppsScan_OobeAppReady" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -13975,7 +13975,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'StartOobeAppsScan_OobeAppReady'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'StartOobeAppsScan_OobeAppReady'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: StartOobeAppsScan_OobeAppReady
|
taskNamePattern: StartOobeAppsScan_OobeAppReady
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "StartOobeAppsScanAfterUpdate" task
|
name: Disable "StartOobeAppsScanAfterUpdate" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -14002,7 +14002,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'StartOobeAppsScanAfterUpdate'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'StartOobeAppsScanAfterUpdate'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: StartOobeAppsScanAfterUpdate
|
taskNamePattern: StartOobeAppsScanAfterUpdate
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "USO_UxBroker" task
|
name: Disable "USO_UxBroker" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -14033,7 +14033,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'USO_UxBroker'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'USO_UxBroker'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: USO_UxBroker
|
taskNamePattern: USO_UxBroker
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "UUS Failover Task" task
|
name: Disable "UUS Failover Task" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -14060,7 +14060,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'UUS Failover Task'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\UpdateOrchestrator\' -TaskName 'UUS Failover Task'
|
||||||
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
taskPathPattern: \Microsoft\Windows\UpdateOrchestrator\
|
||||||
taskNamePattern: UUS Failover Task
|
taskNamePattern: UUS Failover Task
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable "PerformRemediation" task
|
name: Disable "PerformRemediation" task
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -14093,7 +14093,7 @@ actions:
|
|||||||
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\WaaSMedic\' -TaskName 'PerformRemediation'
|
# Check: Get-ScheduledTask -TaskPath '\Microsoft\Windows\WaaSMedic\' -TaskName 'PerformRemediation'
|
||||||
taskPathPattern: \Microsoft\Windows\WaaSMedic\
|
taskPathPattern: \Microsoft\Windows\WaaSMedic\
|
||||||
taskNamePattern: PerformRemediation
|
taskNamePattern: PerformRemediation
|
||||||
grantPermissions: true # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
grantPermissions: 'true' # 🔒 No permissions, tested since [≥ Windows 10 22H2] [≥ Windows 11 22H2]
|
||||||
-
|
-
|
||||||
name: Disable outdated Windows Update tasks
|
name: Disable outdated Windows Update tasks
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19014,7 +19014,7 @@ actions:
|
|||||||
function: DeleteDirectory
|
function: DeleteDirectory
|
||||||
parameters:
|
parameters:
|
||||||
directoryGlob: '%LOCALAPPDATA%\Microsoft\OneDrive'
|
directoryGlob: '%LOCALAPPDATA%\Microsoft\OneDrive'
|
||||||
grantPermissions: true
|
grantPermissions: 'true'
|
||||||
-
|
-
|
||||||
function: DeleteDirectory
|
function: DeleteDirectory
|
||||||
parameters:
|
parameters:
|
||||||
@@ -19465,7 +19465,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: DirectPlay # Get-WindowsOptionalFeature -FeatureName 'DirectPlay' -Online
|
featureName: DirectPlay # Get-WindowsOptionalFeature -FeatureName 'DirectPlay' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Internet Explorer" feature
|
name: Disable "Internet Explorer" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19483,17 +19483,17 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Internet-Explorer-Optional-x64 # Get-WindowsOptionalFeature -FeatureName 'Internet-Explorer-Optional-x64' -Online
|
featureName: Internet-Explorer-Optional-x64 # Get-WindowsOptionalFeature -FeatureName 'Internet-Explorer-Optional-x64' -Online
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Internet-Explorer-Optional-x84 # Get-WindowsOptionalFeature -FeatureName 'Internet-Explorer-Optional-x84' -Online
|
featureName: Internet-Explorer-Optional-x84 # Get-WindowsOptionalFeature -FeatureName 'Internet-Explorer-Optional-x84' -Online
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Internet-Explorer-Optional-amd64 # Get-WindowsOptionalFeature -FeatureName 'Internet-Explorer-Optional-amd64' -Online
|
featureName: Internet-Explorer-Optional-amd64 # Get-WindowsOptionalFeature -FeatureName 'Internet-Explorer-Optional-amd64' -Online
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Legacy Components" feature
|
name: Disable "Legacy Components" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19510,7 +19510,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: LegacyComponents # Get-WindowsOptionalFeature -FeatureName 'LegacyComponents' -Online
|
featureName: LegacyComponents # Get-WindowsOptionalFeature -FeatureName 'LegacyComponents' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
category: Disable Hyper-V virtualization features
|
category: Disable Hyper-V virtualization features
|
||||||
children:
|
children:
|
||||||
@@ -19530,7 +19530,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Microsoft-Hyper-V-All # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-All' -Online
|
featureName: Microsoft-Hyper-V-All # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-All' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Hyper-V GUI Management Tools" feature
|
name: Disable "Hyper-V GUI Management Tools" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19547,7 +19547,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Microsoft-Hyper-V-Management-Clients # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Management-Clients' -Online
|
featureName: Microsoft-Hyper-V-Management-Clients # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Management-Clients' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Hyper-V Management Tools" feature
|
name: Disable "Hyper-V Management Tools" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19564,7 +19564,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Microsoft-Hyper-V-Tools-All # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Tools-All' -Online
|
featureName: Microsoft-Hyper-V-Tools-All # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Tools-All' -Online
|
||||||
disabledByDefault: true # Default: Disabled (tested: Windows 10 22H2, Windows 11 23H2)
|
disabledByDefault: 'true' # Default: Disabled (tested: Windows 10 22H2, Windows 11 23H2)
|
||||||
-
|
-
|
||||||
name: Disable "Hyper-V Module for Windows PowerShell" feature
|
name: Disable "Hyper-V Module for Windows PowerShell" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19581,7 +19581,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Microsoft-Hyper-V-Management-PowerShell # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Management-PowerShell' -Online
|
featureName: Microsoft-Hyper-V-Management-PowerShell # Get-WindowsOptionalFeature -FeatureName 'Microsoft-Hyper-V-Management-PowerShell' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
category: Disable printing features
|
category: Disable printing features
|
||||||
children:
|
children:
|
||||||
@@ -19620,7 +19620,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Printing-Foundation-LPDPrintService # Get-WindowsOptionalFeature -FeatureName 'Printing-Foundation-LPDPrintService' -Online
|
featureName: Printing-Foundation-LPDPrintService # Get-WindowsOptionalFeature -FeatureName 'Printing-Foundation-LPDPrintService' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "LPR Port Monitor" feature
|
name: Disable "LPR Port Monitor" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19637,7 +19637,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Printing-Foundation-LPRPortMonitor # Get-WindowsOptionalFeature -FeatureName 'Printing-Foundation-LPRPortMonitor' -Online
|
featureName: Printing-Foundation-LPRPortMonitor # Get-WindowsOptionalFeature -FeatureName 'Printing-Foundation-LPRPortMonitor' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Microsoft Print to PDF" feature
|
name: Disable "Microsoft Print to PDF" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19707,7 +19707,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Printing-XPSServices-Features # Get-WindowsOptionalFeature -FeatureName 'Printing-XPSServices-Features' -Online
|
featureName: Printing-XPSServices-Features # Get-WindowsOptionalFeature -FeatureName 'Printing-XPSServices-Features' -Online
|
||||||
disabledByDefault: true
|
disabledByDefault: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "XPS Viewer" feature
|
name: Disable "XPS Viewer" feature
|
||||||
recommend: standard # Deprecated and missing on modern versions of Windows
|
recommend: standard # Deprecated and missing on modern versions of Windows
|
||||||
@@ -19729,7 +19729,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: Xps-Foundation-Xps-Viewer # Get-WindowsOptionalFeature -FeatureName 'Xps-Foundation-Xps-Viewer' -Online
|
featureName: Xps-Foundation-Xps-Viewer # Get-WindowsOptionalFeature -FeatureName 'Xps-Foundation-Xps-Viewer' -Online
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Media Features" feature
|
name: Disable "Media Features" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -19767,7 +19767,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: ScanManagementConsole # Get-WindowsOptionalFeature -FeatureName 'ScanManagementConsole' -Online
|
featureName: ScanManagementConsole # Get-WindowsOptionalFeature -FeatureName 'ScanManagementConsole' -Online
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Windows Fax and Scan" feature
|
name: Disable "Windows Fax and Scan" feature
|
||||||
recommend: standard # Deprecated and missing on modern versions of Windows
|
recommend: standard # Deprecated and missing on modern versions of Windows
|
||||||
@@ -19789,7 +19789,7 @@ actions:
|
|||||||
function: DisableWindowsFeature
|
function: DisableWindowsFeature
|
||||||
parameters:
|
parameters:
|
||||||
featureName: FaxServicesClientPackage # Get-WindowsOptionalFeature -FeatureName 'FaxServicesClientPackage' -Online
|
featureName: FaxServicesClientPackage # Get-WindowsOptionalFeature -FeatureName 'FaxServicesClientPackage' -Online
|
||||||
ignoreMissingOnRevert: true
|
ignoreMissingOnRevert: 'true'
|
||||||
-
|
-
|
||||||
name: Disable "Windows Media Player" feature
|
name: Disable "Windows Media Player" feature
|
||||||
docs: |-
|
docs: |-
|
||||||
@@ -20667,8 +20667,8 @@ actions:
|
|||||||
function: ShowMessage
|
function: ShowMessage
|
||||||
parameters:
|
parameters:
|
||||||
message: Disabling Network settings on Windows 10 is known to break Network settings.
|
message: Disabling Network settings on Windows 10 is known to break Network settings.
|
||||||
ignoreWindows11: true
|
ignoreWindows11: 'true'
|
||||||
warn: true
|
warn: 'true'
|
||||||
-
|
-
|
||||||
function: DisableService
|
function: DisableService
|
||||||
parameters:
|
parameters:
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { validateParameterName } from '@/application/Parser/Executable/Script/Compiler/Function/Shared/ParameterNameValidator';
|
||||||
|
|
||||||
|
describe('ParameterNameValidator', () => {
|
||||||
|
describe('accepts when valid', () => {
|
||||||
|
// arrange
|
||||||
|
const validValues: readonly string[] = [
|
||||||
|
'lowercase',
|
||||||
|
'onlyLetters',
|
||||||
|
'l3tt3rsW1thNumb3rs',
|
||||||
|
];
|
||||||
|
validValues.forEach((validValue) => {
|
||||||
|
it(validValue, () => {
|
||||||
|
// act
|
||||||
|
const act = () => validateParameterName(validValue);
|
||||||
|
// assert
|
||||||
|
expect(act).to.not.throw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('throws if invalid', () => {
|
||||||
|
// arrange
|
||||||
|
const testScenarios: readonly {
|
||||||
|
readonly description: string;
|
||||||
|
readonly value: string;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
description: 'empty name',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'has @',
|
||||||
|
value: 'b@d',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'has {',
|
||||||
|
value: 'b{a}d',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
testScenarios.forEach((
|
||||||
|
{ description, value },
|
||||||
|
) => {
|
||||||
|
it(description, () => {
|
||||||
|
// act
|
||||||
|
const act = () => validateParameterName(value);
|
||||||
|
// assert
|
||||||
|
expect(act).to.throw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { createTypeValidator } from '@/application/Parser/Common/TypeValidator';
|
import { createTypeValidator, type NonEmptyStringAssertion, type RegexValidationRule } from '@/application/Parser/Common/TypeValidator';
|
||||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||||
|
|
||||||
describe('createTypeValidator', () => {
|
describe('createTypeValidator', () => {
|
||||||
describe('assertObject', () => {
|
describe('assertObject', () => {
|
||||||
@@ -146,6 +146,108 @@ describe('createTypeValidator', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('assertNonEmptyString', () => {
|
||||||
|
describe('with valid string', () => {
|
||||||
|
it('accepts non-empty string without regex rule', () => {
|
||||||
|
// arrange
|
||||||
|
const nonEmptyString = 'hello';
|
||||||
|
const { assertNonEmptyString } = createTypeValidator();
|
||||||
|
// act
|
||||||
|
const act = () => assertNonEmptyString({ value: nonEmptyString, valueName: 'unimportant name' });
|
||||||
|
// assert
|
||||||
|
expect(act).to.not.throw();
|
||||||
|
});
|
||||||
|
it('accepts if the string matches the regex', () => {
|
||||||
|
// arrange
|
||||||
|
const regex: RegExp = /goodbye/;
|
||||||
|
const stringMatchingRegex = 'Valid string containing "goodbye"';
|
||||||
|
const rule: RegexValidationRule = {
|
||||||
|
expectedMatch: regex,
|
||||||
|
errorMessage: 'String contain "goodbye"',
|
||||||
|
};
|
||||||
|
const { assertNonEmptyString } = createTypeValidator();
|
||||||
|
// act
|
||||||
|
const act = () => assertNonEmptyString({
|
||||||
|
value: stringMatchingRegex,
|
||||||
|
valueName: 'unimportant name',
|
||||||
|
rule,
|
||||||
|
});
|
||||||
|
// assert
|
||||||
|
expect(act).to.not.throw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('with invalid string', () => {
|
||||||
|
describe('throws error for missing string', () => {
|
||||||
|
itEachAbsentStringValue((absentValue) => {
|
||||||
|
// arrange
|
||||||
|
const valueName = 'absent string value';
|
||||||
|
const expectedMessage = `'${valueName}' is missing.`;
|
||||||
|
const { assertNonEmptyString } = createTypeValidator();
|
||||||
|
// act
|
||||||
|
const act = () => assertNonEmptyString({ value: absentValue, valueName });
|
||||||
|
// assert
|
||||||
|
expect(act).to.throw(expectedMessage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('throws error for non string values', () => {
|
||||||
|
// arrange
|
||||||
|
const testScenarios: readonly {
|
||||||
|
readonly description: string;
|
||||||
|
readonly invalidValue: unknown;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
description: 'number',
|
||||||
|
invalidValue: 42,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'boolean',
|
||||||
|
invalidValue: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'object',
|
||||||
|
invalidValue: { property: 'value' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'array',
|
||||||
|
invalidValue: ['a', 'r', 'r', 'a', 'y'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
testScenarios.forEach(({
|
||||||
|
description, invalidValue,
|
||||||
|
}) => {
|
||||||
|
it(description, () => {
|
||||||
|
const valueName = 'invalidValue';
|
||||||
|
const expectedMessage = `'${valueName}' should be of type 'string', but is of type '${typeof invalidValue}'.`;
|
||||||
|
const { assertNonEmptyString } = createTypeValidator();
|
||||||
|
// act
|
||||||
|
const act = () => assertNonEmptyString({ value: invalidValue, valueName });
|
||||||
|
// assert
|
||||||
|
expect(act).to.throw(expectedMessage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('throws an error if the string does not match the regex', () => {
|
||||||
|
// arrange
|
||||||
|
const regex: RegExp = /goodbye/;
|
||||||
|
const stringNotMatchingRegex = 'Hello';
|
||||||
|
const expectedMessage = 'String should contain "goodbye"';
|
||||||
|
const rule: RegexValidationRule = {
|
||||||
|
expectedMatch: regex,
|
||||||
|
errorMessage: expectedMessage,
|
||||||
|
};
|
||||||
|
const assertion: NonEmptyStringAssertion = {
|
||||||
|
value: stringNotMatchingRegex,
|
||||||
|
valueName: 'non-important-value-name',
|
||||||
|
rule,
|
||||||
|
};
|
||||||
|
const { assertNonEmptyString } = createTypeValidator();
|
||||||
|
// act
|
||||||
|
const act = () => assertNonEmptyString(assertion);
|
||||||
|
// assert
|
||||||
|
expect(act).to.throw(expectedMessage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function createObjectWithProperties(properties: readonly string[]): object {
|
function createObjectWithProperties(properties: readonly string[]): object {
|
||||||
|
|||||||
@@ -1,52 +1,110 @@
|
|||||||
import { describe, expect } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { FunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
import { createFunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
import { TypeValidatorStub } from '@tests/unit/shared/Stubs/TypeValidatorStub';
|
||||||
import { testParameterName } from '../../../ParameterNameTestRunner';
|
import type { NonEmptyStringAssertion, TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
||||||
|
import { createParameterNameValidatorStub } from '@tests/unit/shared/Stubs/ParameterNameValidatorStub';
|
||||||
|
import type { ParameterNameValidator } from '@/application/Parser/Executable/Script/Compiler/Function/Shared/ParameterNameValidator';
|
||||||
|
|
||||||
describe('FunctionCallArgument', () => {
|
describe('FunctionCallArgument', () => {
|
||||||
describe('ctor', () => {
|
describe('createFunctionCallArgument', () => {
|
||||||
describe('parameter name', () => {
|
describe('parameter name', () => {
|
||||||
testParameterName(
|
it('assigns correctly', () => {
|
||||||
(parameterName) => new FunctionCallArgumentBuilder()
|
|
||||||
.withParameterName(parameterName)
|
|
||||||
.build()
|
|
||||||
.parameterName,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
describe('throws if argument value is absent', () => {
|
|
||||||
itEachAbsentStringValue((absentValue) => {
|
|
||||||
// arrange
|
// arrange
|
||||||
const parameterName = 'paramName';
|
const expectedName = 'expected parameter name';
|
||||||
const expectedError = `Missing argument value for the parameter "${parameterName}".`;
|
const context = new TestContext()
|
||||||
const argumentValue = absentValue;
|
.withParameterName(expectedName);
|
||||||
// act
|
// act
|
||||||
const act = () => new FunctionCallArgumentBuilder()
|
const actualArgument = context.create();
|
||||||
.withParameterName(parameterName)
|
|
||||||
.withArgumentValue(argumentValue)
|
|
||||||
.build();
|
|
||||||
// assert
|
// assert
|
||||||
expect(act).to.throw(expectedError);
|
const actualName = actualArgument.parameterName;
|
||||||
}, { excludeNull: true, excludeUndefined: true });
|
expect(actualName).toEqual(expectedName);
|
||||||
|
});
|
||||||
|
it('validates parameter name', () => {
|
||||||
|
// arrange
|
||||||
|
const validator = createParameterNameValidatorStub();
|
||||||
|
const expectedParameterName = 'parameter name expected to be validated';
|
||||||
|
const context = new TestContext()
|
||||||
|
.withParameterName(expectedParameterName)
|
||||||
|
.withParameterNameValidator(validator.validator);
|
||||||
|
// act
|
||||||
|
context.create();
|
||||||
|
// assert
|
||||||
|
expect(validator.validatedNames).to.have.lengthOf(1);
|
||||||
|
expect(validator.validatedNames).to.include(expectedParameterName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('argument value', () => {
|
||||||
|
it('assigns correctly', () => {
|
||||||
|
// arrange
|
||||||
|
const expectedValue = 'expected argument value';
|
||||||
|
const context = new TestContext()
|
||||||
|
.withArgumentValue(expectedValue);
|
||||||
|
// act
|
||||||
|
const actualArgument = context.create();
|
||||||
|
// assert
|
||||||
|
const actualValue = actualArgument.argumentValue;
|
||||||
|
expect(actualValue).toEqual(expectedValue);
|
||||||
|
});
|
||||||
|
it('validates argument value', () => {
|
||||||
|
// arrange
|
||||||
|
const parameterNameInError = 'expected parameter with argument error';
|
||||||
|
const expectedArgumentValue = 'argument value to be validated';
|
||||||
|
const expectedAssertion: NonEmptyStringAssertion = {
|
||||||
|
value: expectedArgumentValue,
|
||||||
|
valueName: `Missing argument value for the parameter "${parameterNameInError}".`,
|
||||||
|
};
|
||||||
|
const typeValidator = new TypeValidatorStub();
|
||||||
|
const context = new TestContext()
|
||||||
|
.withArgumentValue(expectedArgumentValue)
|
||||||
|
.withParameterName(parameterNameInError)
|
||||||
|
.withTypeValidator(typeValidator);
|
||||||
|
// act
|
||||||
|
context.create();
|
||||||
|
// assert
|
||||||
|
typeValidator.assertNonEmptyString(expectedAssertion);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
class FunctionCallArgumentBuilder {
|
class TestContext {
|
||||||
private parameterName = 'default-parameter-name';
|
private parameterName = `[${TestContext.name}] default-parameter-name`;
|
||||||
|
|
||||||
private argumentValue = 'default-argument-value';
|
private argumentValue = `[${TestContext.name}] default-argument-value`;
|
||||||
|
|
||||||
public withParameterName(parameterName: string) {
|
private typeValidator: TypeValidator = new TypeValidatorStub();
|
||||||
|
|
||||||
|
private parameterNameValidator
|
||||||
|
: ParameterNameValidator = createParameterNameValidatorStub().validator;
|
||||||
|
|
||||||
|
public withParameterName(parameterName: string): this {
|
||||||
this.parameterName = parameterName;
|
this.parameterName = parameterName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withArgumentValue(argumentValue: string) {
|
public withArgumentValue(argumentValue: string): this {
|
||||||
this.argumentValue = argumentValue;
|
this.argumentValue = argumentValue;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public build() {
|
public withTypeValidator(typeValidator: TypeValidator): this {
|
||||||
return new FunctionCallArgument(this.parameterName, this.argumentValue);
|
this.typeValidator = typeValidator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withParameterNameValidator(parameterNameValidator: ParameterNameValidator): this {
|
||||||
|
this.parameterNameValidator = parameterNameValidator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public create(): ReturnType<typeof createFunctionCallArgument> {
|
||||||
|
return createFunctionCallArgument(
|
||||||
|
this.parameterName,
|
||||||
|
this.argumentValue,
|
||||||
|
{
|
||||||
|
typeValidator: this.typeValidator,
|
||||||
|
validateParameterName: this.parameterNameValidator,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest';
|
|||||||
import { FunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
import { FunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
|
||||||
import { FunctionCallArgumentStub } from '@tests/unit/shared/Stubs/FunctionCallArgumentStub';
|
import { FunctionCallArgumentStub } from '@tests/unit/shared/Stubs/FunctionCallArgumentStub';
|
||||||
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||||
import type { IFunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgument';
|
import type { FunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
|
||||||
describe('FunctionCallArgumentCollection', () => {
|
describe('FunctionCallArgumentCollection', () => {
|
||||||
describe('addArgument', () => {
|
describe('addArgument', () => {
|
||||||
@@ -25,7 +25,7 @@ describe('FunctionCallArgumentCollection', () => {
|
|||||||
// arrange
|
// arrange
|
||||||
const testCases: ReadonlyArray<{
|
const testCases: ReadonlyArray<{
|
||||||
readonly description: string;
|
readonly description: string;
|
||||||
readonly args: readonly IFunctionCallArgument[];
|
readonly args: readonly FunctionCallArgument[];
|
||||||
readonly expectedParameterNames: string[];
|
readonly expectedParameterNames: string[];
|
||||||
}> = [{
|
}> = [{
|
||||||
description: 'no args',
|
description: 'no args',
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { SharedFunctionCollectionStub } from '@tests/unit/shared/Stubs/SharedFun
|
|||||||
import { itThrowsContextualError } from '@tests/unit/application/Parser/Common/ContextualErrorTester';
|
import { itThrowsContextualError } from '@tests/unit/application/Parser/Common/ContextualErrorTester';
|
||||||
import type { ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
import type { ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||||
import { errorWithContextWrapperStub } from '@tests/unit/shared/Stubs/ErrorWithContextWrapperStub';
|
import { errorWithContextWrapperStub } from '@tests/unit/shared/Stubs/ErrorWithContextWrapperStub';
|
||||||
|
import type { FunctionCallArgumentFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
import { FunctionCallArgumentFactoryStub } from '../../../../../../../../../../../shared/Stubs/FunctionCallArgumentFactoryStub';
|
||||||
|
|
||||||
describe('NestedFunctionArgumentCompiler', () => {
|
describe('NestedFunctionArgumentCompiler', () => {
|
||||||
describe('createCompiledNestedCall', () => {
|
describe('createCompiledNestedCall', () => {
|
||||||
@@ -266,6 +268,9 @@ class NestedFunctionArgumentCompilerBuilder implements ArgumentCompiler {
|
|||||||
|
|
||||||
private wrapError: ErrorWithContextWrapper = errorWithContextWrapperStub;
|
private wrapError: ErrorWithContextWrapper = errorWithContextWrapperStub;
|
||||||
|
|
||||||
|
private callArgumentFactory
|
||||||
|
: FunctionCallArgumentFactory = new FunctionCallArgumentFactoryStub().factory;
|
||||||
|
|
||||||
public withExpressionsCompiler(expressionsCompiler: IExpressionsCompiler): this {
|
public withExpressionsCompiler(expressionsCompiler: IExpressionsCompiler): this {
|
||||||
this.expressionsCompiler = expressionsCompiler;
|
this.expressionsCompiler = expressionsCompiler;
|
||||||
return this;
|
return this;
|
||||||
@@ -292,10 +297,11 @@ class NestedFunctionArgumentCompilerBuilder implements ArgumentCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createCompiledNestedCall(): FunctionCall {
|
public createCompiledNestedCall(): FunctionCall {
|
||||||
const compiler = new NestedFunctionArgumentCompiler(
|
const compiler = new NestedFunctionArgumentCompiler({
|
||||||
this.expressionsCompiler,
|
expressionsCompiler: this.expressionsCompiler,
|
||||||
this.wrapError,
|
wrapError: this.wrapError,
|
||||||
);
|
createCallArgument: this.callArgumentFactory,
|
||||||
|
});
|
||||||
return compiler.createCompiledNestedCall(
|
return compiler.createCompiledNestedCall(
|
||||||
this.nestedFunctionCall,
|
this.nestedFunctionCall,
|
||||||
this.parentFunctionCall,
|
this.parentFunctionCall,
|
||||||
|
|||||||
@@ -3,8 +3,12 @@ import type { FunctionCallsData, FunctionCallData } from '@/application/collecti
|
|||||||
import { parseFunctionCalls } from '@/application/Parser/Executable/Script/Compiler/Function/Call/FunctionCallsParser';
|
import { parseFunctionCalls } from '@/application/Parser/Executable/Script/Compiler/Function/Call/FunctionCallsParser';
|
||||||
import { FunctionCallDataStub } from '@tests/unit/shared/Stubs/FunctionCallDataStub';
|
import { FunctionCallDataStub } from '@tests/unit/shared/Stubs/FunctionCallDataStub';
|
||||||
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||||
import type { NonEmptyCollectionAssertion, ObjectAssertion, TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
import type {
|
||||||
|
NonEmptyCollectionAssertion, ObjectAssertion, TypeValidator,
|
||||||
|
} from '@/application/Parser/Common/TypeValidator';
|
||||||
import { TypeValidatorStub } from '@tests/unit/shared/Stubs/TypeValidatorStub';
|
import { TypeValidatorStub } from '@tests/unit/shared/Stubs/TypeValidatorStub';
|
||||||
|
import type { FunctionCallArgumentFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
import { FunctionCallArgumentFactoryStub } from '@tests/unit/shared/Stubs/FunctionCallArgumentFactoryStub';
|
||||||
|
|
||||||
describe('FunctionCallsParser', () => {
|
describe('FunctionCallsParser', () => {
|
||||||
describe('parseFunctionCalls', () => {
|
describe('parseFunctionCalls', () => {
|
||||||
@@ -174,12 +178,15 @@ describe('FunctionCallsParser', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
class TestContext {
|
class TestContext {
|
||||||
private validator: TypeValidator = new TypeValidatorStub();
|
private typeValidator: TypeValidator = new TypeValidatorStub();
|
||||||
|
|
||||||
|
private createCallArgument
|
||||||
|
: FunctionCallArgumentFactory = new FunctionCallArgumentFactoryStub().factory;
|
||||||
|
|
||||||
private calls: FunctionCallsData = [new FunctionCallDataStub()];
|
private calls: FunctionCallsData = [new FunctionCallDataStub()];
|
||||||
|
|
||||||
public withTypeValidator(typeValidator: TypeValidator): this {
|
public withTypeValidator(typeValidator: TypeValidator): this {
|
||||||
this.validator = typeValidator;
|
this.typeValidator = typeValidator;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +198,10 @@ class TestContext {
|
|||||||
public parse(): ReturnType<typeof parseFunctionCalls> {
|
public parse(): ReturnType<typeof parseFunctionCalls> {
|
||||||
return parseFunctionCalls(
|
return parseFunctionCalls(
|
||||||
this.calls,
|
this.calls,
|
||||||
this.validator,
|
{
|
||||||
|
typeValidator: this.typeValidator,
|
||||||
|
createCallArgument: this.createCallArgument,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
import { FunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameter';
|
|
||||||
import { testParameterName } from '../../ParameterNameTestRunner';
|
|
||||||
|
|
||||||
describe('FunctionParameter', () => {
|
|
||||||
describe('name', () => {
|
|
||||||
testParameterName(
|
|
||||||
(parameterName) => new FunctionParameterBuilder()
|
|
||||||
.withName(parameterName)
|
|
||||||
.build()
|
|
||||||
.name,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
describe('isOptional', () => {
|
|
||||||
describe('sets as expected', () => {
|
|
||||||
// arrange
|
|
||||||
const expectedValues = [true, false];
|
|
||||||
for (const expected of expectedValues) {
|
|
||||||
it(expected.toString(), () => {
|
|
||||||
// act
|
|
||||||
const sut = new FunctionParameterBuilder()
|
|
||||||
.withIsOptional(expected)
|
|
||||||
.build();
|
|
||||||
// expect
|
|
||||||
expect(sut.isOptional).to.equal(expected);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
class FunctionParameterBuilder {
|
|
||||||
private name = 'parameterFromParameterBuilder';
|
|
||||||
|
|
||||||
private isOptional = false;
|
|
||||||
|
|
||||||
public withName(name: string) {
|
|
||||||
this.name = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public withIsOptional(isOptional: boolean) {
|
|
||||||
this.isOptional = isOptional;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public build() {
|
|
||||||
return new FunctionParameter(this.name, this.isOptional);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import type { ParameterDefinitionData } from '@/application/collections/';
|
||||||
|
import type { ParameterNameValidator } from '@/application/Parser/Executable/Script/Compiler/Function/Shared/ParameterNameValidator';
|
||||||
|
import { createParameterNameValidatorStub } from '@tests/unit/shared/Stubs/ParameterNameValidatorStub';
|
||||||
|
import { parseFunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterParser';
|
||||||
|
import { ParameterDefinitionDataStub } from '@tests/unit/shared/Stubs/ParameterDefinitionDataStub';
|
||||||
|
|
||||||
|
describe('FunctionParameterParser', () => {
|
||||||
|
describe('parseFunctionParameter', () => {
|
||||||
|
describe('name', () => {
|
||||||
|
it('assigns correctly', () => {
|
||||||
|
// arrange
|
||||||
|
const expectedName = 'expected-function-name';
|
||||||
|
const data = new ParameterDefinitionDataStub()
|
||||||
|
.withName(expectedName);
|
||||||
|
// act
|
||||||
|
const actual = new TestContext()
|
||||||
|
.withData(data)
|
||||||
|
.parse();
|
||||||
|
// expect
|
||||||
|
const actualName = actual.name;
|
||||||
|
expect(actualName).to.equal(expectedName);
|
||||||
|
});
|
||||||
|
it('validates correctly', () => {
|
||||||
|
// arrange
|
||||||
|
const expectedName = 'expected-function-name';
|
||||||
|
const { validator, validatedNames } = createParameterNameValidatorStub();
|
||||||
|
const data = new ParameterDefinitionDataStub()
|
||||||
|
.withName(expectedName);
|
||||||
|
// act
|
||||||
|
new TestContext()
|
||||||
|
.withData(data)
|
||||||
|
.withValidator(validator)
|
||||||
|
.parse();
|
||||||
|
// expect
|
||||||
|
expect(validatedNames).to.have.lengthOf(1);
|
||||||
|
expect(validatedNames).to.contain(expectedName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('isOptional', () => {
|
||||||
|
describe('assigns correctly', () => {
|
||||||
|
// arrange
|
||||||
|
const expectedValues = [true, false];
|
||||||
|
for (const expected of expectedValues) {
|
||||||
|
it(expected.toString(), () => {
|
||||||
|
const data = new ParameterDefinitionDataStub()
|
||||||
|
.withOptionality(expected);
|
||||||
|
// act
|
||||||
|
const actual = new TestContext()
|
||||||
|
.withData(data)
|
||||||
|
.parse();
|
||||||
|
// expect
|
||||||
|
expect(actual.isOptional).to.equal(expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
class TestContext {
|
||||||
|
private data: ParameterDefinitionData = new ParameterDefinitionDataStub()
|
||||||
|
.withName(`[${TestContext.name}]function-name`);
|
||||||
|
|
||||||
|
private validator: ParameterNameValidator = createParameterNameValidatorStub().validator;
|
||||||
|
|
||||||
|
public withData(data: ParameterDefinitionData) {
|
||||||
|
this.data = data;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withValidator(parameterNameValidator: ParameterNameValidator): this {
|
||||||
|
this.validator = parameterNameValidator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public parse() {
|
||||||
|
return parseFunctionParameter(
|
||||||
|
this.data,
|
||||||
|
this.validator,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import type {
|
|||||||
ParameterDefinitionData, FunctionCallsData,
|
ParameterDefinitionData, FunctionCallsData,
|
||||||
} from '@/application/collections/';
|
} from '@/application/collections/';
|
||||||
import type { ISharedFunction } from '@/application/Parser/Executable/Script/Compiler/Function/ISharedFunction';
|
import type { ISharedFunction } from '@/application/Parser/Executable/Script/Compiler/Function/ISharedFunction';
|
||||||
import { parseSharedFunctions, type FunctionParameterFactory } from '@/application/Parser/Executable/Script/Compiler/Function/SharedFunctionsParser';
|
import { parseSharedFunctions } from '@/application/Parser/Executable/Script/Compiler/Function/SharedFunctionsParser';
|
||||||
import { createFunctionDataWithCall, createFunctionDataWithCode, createFunctionDataWithoutCallOrCode } from '@tests/unit/shared/Stubs/FunctionDataStub';
|
import { createFunctionDataWithCall, createFunctionDataWithCode, createFunctionDataWithoutCallOrCode } from '@tests/unit/shared/Stubs/FunctionDataStub';
|
||||||
import { ParameterDefinitionDataStub } from '@tests/unit/shared/Stubs/ParameterDefinitionDataStub';
|
import { ParameterDefinitionDataStub } from '@tests/unit/shared/Stubs/ParameterDefinitionDataStub';
|
||||||
import { FunctionCallDataStub } from '@tests/unit/shared/Stubs/FunctionCallDataStub';
|
import { FunctionCallDataStub } from '@tests/unit/shared/Stubs/FunctionCallDataStub';
|
||||||
@@ -16,7 +16,6 @@ import type { ICodeValidator } from '@/application/Parser/Executable/Script/Vali
|
|||||||
import { NoEmptyLines } from '@/application/Parser/Executable/Script/Validation/Rules/NoEmptyLines';
|
import { NoEmptyLines } from '@/application/Parser/Executable/Script/Validation/Rules/NoEmptyLines';
|
||||||
import { NoDuplicatedLines } from '@/application/Parser/Executable/Script/Validation/Rules/NoDuplicatedLines';
|
import { NoDuplicatedLines } from '@/application/Parser/Executable/Script/Validation/Rules/NoDuplicatedLines';
|
||||||
import type { ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
import type { ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||||
import { FunctionParameterStub } from '@tests/unit/shared/Stubs/FunctionParameterStub';
|
|
||||||
import { errorWithContextWrapperStub } from '@tests/unit/shared/Stubs/ErrorWithContextWrapperStub';
|
import { errorWithContextWrapperStub } from '@tests/unit/shared/Stubs/ErrorWithContextWrapperStub';
|
||||||
import { itThrowsContextualError } from '@tests/unit/application/Parser/Common/ContextualErrorTester';
|
import { itThrowsContextualError } from '@tests/unit/application/Parser/Common/ContextualErrorTester';
|
||||||
import type { FunctionParameterCollectionFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterCollectionFactory';
|
import type { FunctionParameterCollectionFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterCollectionFactory';
|
||||||
@@ -26,6 +25,8 @@ import { createFunctionCallsParserStub } from '@tests/unit/shared/Stubs/Function
|
|||||||
import { FunctionCallStub } from '@tests/unit/shared/Stubs/FunctionCallStub';
|
import { FunctionCallStub } from '@tests/unit/shared/Stubs/FunctionCallStub';
|
||||||
import type { IReadOnlyFunctionParameterCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/IFunctionParameterCollection';
|
import type { IReadOnlyFunctionParameterCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/IFunctionParameterCollection';
|
||||||
import type { FunctionCall } from '@/application/Parser/Executable/Script/Compiler/Function/Call/FunctionCall';
|
import type { FunctionCall } from '@/application/Parser/Executable/Script/Compiler/Function/Call/FunctionCall';
|
||||||
|
import type { FunctionParameterParser } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterParser';
|
||||||
|
import { createFunctionParameterParserStub } from '@tests/unit/shared/Stubs/FunctionParameterParserStub';
|
||||||
import { expectCallsFunctionBody, expectCodeFunctionBody } from './ExpectFunctionBodyType';
|
import { expectCallsFunctionBody, expectCodeFunctionBody } from './ExpectFunctionBodyType';
|
||||||
|
|
||||||
describe('SharedFunctionsParser', () => {
|
describe('SharedFunctionsParser', () => {
|
||||||
@@ -185,7 +186,7 @@ describe('SharedFunctionsParser', () => {
|
|||||||
const functionName = 'functionName';
|
const functionName = 'functionName';
|
||||||
const expectedErrorMessage = `Failed to create parameter: ${invalidParameterName} for function "${functionName}"`;
|
const expectedErrorMessage = `Failed to create parameter: ${invalidParameterName} for function "${functionName}"`;
|
||||||
const expectedInnerError = new Error('injected error');
|
const expectedInnerError = new Error('injected error');
|
||||||
const parameterFactory: FunctionParameterFactory = () => {
|
const parser: FunctionParameterParser = () => {
|
||||||
throw expectedInnerError;
|
throw expectedInnerError;
|
||||||
};
|
};
|
||||||
const functionData = createFunctionDataWithCode()
|
const functionData = createFunctionDataWithCode()
|
||||||
@@ -196,7 +197,7 @@ describe('SharedFunctionsParser', () => {
|
|||||||
throwingAction: (wrapError) => {
|
throwingAction: (wrapError) => {
|
||||||
new TestContext()
|
new TestContext()
|
||||||
.withFunctions([functionData])
|
.withFunctions([functionData])
|
||||||
.withFunctionParameterFactory(parameterFactory)
|
.withFunctionParameterParser(parser)
|
||||||
.withErrorWrapper(wrapError)
|
.withErrorWrapper(wrapError)
|
||||||
.parseFunctions();
|
.parseFunctions();
|
||||||
},
|
},
|
||||||
@@ -415,12 +416,7 @@ class TestContext {
|
|||||||
|
|
||||||
private functionCallsParser: FunctionCallsParser = createFunctionCallsParserStub().parser;
|
private functionCallsParser: FunctionCallsParser = createFunctionCallsParserStub().parser;
|
||||||
|
|
||||||
private parameterFactory: FunctionParameterFactory = (
|
private functionParameterParser: FunctionParameterParser = createFunctionParameterParserStub;
|
||||||
name: string,
|
|
||||||
isOptional: boolean,
|
|
||||||
) => new FunctionParameterStub()
|
|
||||||
.withName(name)
|
|
||||||
.withOptional(isOptional);
|
|
||||||
|
|
||||||
private parameterCollectionFactory
|
private parameterCollectionFactory
|
||||||
: FunctionParameterCollectionFactory = () => new FunctionParameterCollectionStub();
|
: FunctionParameterCollectionFactory = () => new FunctionParameterCollectionStub();
|
||||||
@@ -450,8 +446,8 @@ class TestContext {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withFunctionParameterFactory(parameterFactory: FunctionParameterFactory): this {
|
public withFunctionParameterParser(functionParameterParser: FunctionParameterParser): this {
|
||||||
this.parameterFactory = parameterFactory;
|
this.functionParameterParser = functionParameterParser;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,7 +465,7 @@ class TestContext {
|
|||||||
{
|
{
|
||||||
codeValidator: this.codeValidator,
|
codeValidator: this.codeValidator,
|
||||||
wrapError: this.wrapError,
|
wrapError: this.wrapError,
|
||||||
createParameter: this.parameterFactory,
|
parseParameter: this.functionParameterParser,
|
||||||
createParameterCollection: this.parameterCollectionFactory,
|
createParameterCollection: this.parameterCollectionFactory,
|
||||||
parseFunctionCalls: this.functionCallsParser,
|
parseFunctionCalls: this.functionCallsParser,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
|
|
||||||
export function testParameterName(action: (parameterName: string) => string) {
|
|
||||||
describe('name', () => {
|
|
||||||
describe('sets as expected', () => {
|
|
||||||
// arrange
|
|
||||||
const expectedValues: readonly string[] = [
|
|
||||||
'lowercase',
|
|
||||||
'onlyLetters',
|
|
||||||
'l3tt3rsW1thNumb3rs',
|
|
||||||
];
|
|
||||||
for (const expected of expectedValues) {
|
|
||||||
it(expected, () => {
|
|
||||||
// act
|
|
||||||
const value = action(expected);
|
|
||||||
// assert
|
|
||||||
expect(value).to.equal(expected);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
describe('throws if invalid', () => {
|
|
||||||
// arrange
|
|
||||||
const testScenarios: readonly {
|
|
||||||
readonly description: string;
|
|
||||||
readonly value: string;
|
|
||||||
readonly expectedError: string;
|
|
||||||
}[] = [
|
|
||||||
{
|
|
||||||
description: 'empty Name',
|
|
||||||
value: '',
|
|
||||||
expectedError: 'missing parameter name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: 'has @',
|
|
||||||
value: 'b@d',
|
|
||||||
expectedError: 'parameter name must be alphanumeric but it was "b@d"',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: 'has {',
|
|
||||||
value: 'b{a}d',
|
|
||||||
expectedError: 'parameter name must be alphanumeric but it was "b{a}d"',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
for (const { description, value, expectedError } of testScenarios) {
|
|
||||||
it(description, () => {
|
|
||||||
// act
|
|
||||||
const act = () => action(value);
|
|
||||||
// assert
|
|
||||||
expect(act).to.throw(expectedError);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { describe, it } from 'vitest';
|
||||||
|
import { TypeValidatorStub } from '@tests/unit/shared/Stubs/TypeValidatorStub';
|
||||||
|
import { validateParameterName } from '@/application/Parser/Executable/Script/Compiler/Function/Shared/ParameterNameValidator';
|
||||||
|
import type { NonEmptyStringAssertion } from '@/application/Parser/Common/TypeValidator';
|
||||||
|
|
||||||
|
describe('ParameterNameValidator', () => {
|
||||||
|
it('asserts correctly', () => {
|
||||||
|
// arrange
|
||||||
|
const parameterName = 'expected-parameter-name';
|
||||||
|
const validator = new TypeValidatorStub();
|
||||||
|
const expectedAssertion: NonEmptyStringAssertion = {
|
||||||
|
value: parameterName,
|
||||||
|
valueName: 'parameter name',
|
||||||
|
rule: {
|
||||||
|
expectedMatch: /^[0-9a-zA-Z]+$/,
|
||||||
|
errorMessage: `parameter name must be alphanumeric but it was "${parameterName}".`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// act
|
||||||
|
validateParameterName(parameterName, validator);
|
||||||
|
// assert
|
||||||
|
validator.assertNonEmptyString(expectedAssertion);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,91 +1,120 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { CodeSubstituter } from '@/application/Parser/ScriptingDefinition/CodeSubstituter';
|
|
||||||
import type { IExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/IExpressionsCompiler';
|
import type { IExpressionsCompiler } from '@/application/Parser/Executable/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||||
import { ProjectDetailsStub } from '@tests/unit/shared/Stubs/ProjectDetailsStub';
|
import { ProjectDetailsStub } from '@tests/unit/shared/Stubs/ProjectDetailsStub';
|
||||||
import { ExpressionsCompilerStub } from '@tests/unit/shared/Stubs/ExpressionsCompilerStub';
|
import { ExpressionsCompilerStub } from '@tests/unit/shared/Stubs/ExpressionsCompilerStub';
|
||||||
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||||
|
import { substituteCode } from '@/application/Parser/ScriptingDefinition/CodeSubstituter';
|
||||||
|
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||||
|
import type { FunctionCallArgumentFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
import { FunctionCallArgumentFactoryStub } from '@tests/unit/shared/Stubs/FunctionCallArgumentFactoryStub';
|
||||||
|
|
||||||
describe('CodeSubstituter', () => {
|
describe('CodeSubstituter', () => {
|
||||||
describe('throws if code is empty', () => {
|
describe('substituteCode', () => {
|
||||||
itEachAbsentStringValue((emptyCode) => {
|
describe('throws if code is empty', () => {
|
||||||
// arrange
|
itEachAbsentStringValue((emptyCode) => {
|
||||||
const expectedError = 'missing code';
|
// arrange
|
||||||
const code = emptyCode;
|
const expectedError = 'missing code';
|
||||||
const projectDetails = new ProjectDetailsStub();
|
const context = new TestContext()
|
||||||
const sut = new CodeSubstituterBuilder().build();
|
.withCode(emptyCode);
|
||||||
// act
|
|
||||||
const act = () => sut.substitute(code, projectDetails);
|
|
||||||
// assert
|
|
||||||
expect(act).to.throw(expectedError);
|
|
||||||
}, { excludeNull: true, excludeUndefined: true });
|
|
||||||
});
|
|
||||||
describe('substitutes parameters as expected values', () => {
|
|
||||||
// arrange
|
|
||||||
const projectDetails = new ProjectDetailsStub();
|
|
||||||
const date = new Date();
|
|
||||||
const testCases: Array<{ parameter: string, argument: string }> = [
|
|
||||||
{
|
|
||||||
parameter: 'homepage',
|
|
||||||
argument: projectDetails.homepage,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
parameter: 'version',
|
|
||||||
argument: projectDetails.version.toString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
parameter: 'date',
|
|
||||||
argument: date.toUTCString(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
for (const testCase of testCases) {
|
|
||||||
it(`substitutes ${testCase.parameter} as expected`, () => {
|
|
||||||
const compilerStub = new ExpressionsCompilerStub();
|
|
||||||
const sut = new CodeSubstituterBuilder()
|
|
||||||
.withCompiler(compilerStub)
|
|
||||||
.withDate(date)
|
|
||||||
.build();
|
|
||||||
// act
|
// act
|
||||||
sut.substitute('non empty code', projectDetails);
|
const act = () => context.substitute();
|
||||||
// assert
|
// assert
|
||||||
expect(compilerStub.callHistory).to.have.lengthOf(1);
|
expect(act).to.throw(expectedError);
|
||||||
const parameters = compilerStub.callHistory[0].args[1];
|
}, { excludeNull: true, excludeUndefined: true });
|
||||||
expect(parameters.hasArgument(testCase.parameter));
|
});
|
||||||
const { argumentValue } = parameters.getArgument(testCase.parameter);
|
describe('substitutes parameters as expected values', () => {
|
||||||
expect(argumentValue).to.equal(testCase.argument);
|
// arrange
|
||||||
});
|
const projectDetails = new ProjectDetailsStub();
|
||||||
}
|
const date = new Date();
|
||||||
});
|
const testCases: Array<{ parameter: string, argument: string }> = [
|
||||||
it('returns code as it is', () => {
|
{
|
||||||
// arrange
|
parameter: 'homepage',
|
||||||
const expected = 'expected-code';
|
argument: projectDetails.homepage,
|
||||||
const compilerStub = new ExpressionsCompilerStub();
|
},
|
||||||
const sut = new CodeSubstituterBuilder()
|
{
|
||||||
.withCompiler(compilerStub)
|
parameter: 'version',
|
||||||
.build();
|
argument: projectDetails.version.toString(),
|
||||||
// act
|
},
|
||||||
sut.substitute(expected, new ProjectDetailsStub());
|
{
|
||||||
// assert
|
parameter: 'date',
|
||||||
expect(compilerStub.callHistory).to.have.lengthOf(1);
|
argument: date.toUTCString(),
|
||||||
expect(compilerStub.callHistory[0].args[0]).to.equal(expected);
|
},
|
||||||
|
];
|
||||||
|
for (const testCase of testCases) {
|
||||||
|
it(`substitutes ${testCase.parameter} as expected`, () => {
|
||||||
|
const compilerStub = new ExpressionsCompilerStub();
|
||||||
|
const context = new TestContext()
|
||||||
|
.withCompiler(compilerStub)
|
||||||
|
.withDate(date)
|
||||||
|
.withProjectDetails(projectDetails);
|
||||||
|
// act
|
||||||
|
context.substitute();
|
||||||
|
// assert
|
||||||
|
expect(compilerStub.callHistory).to.have.lengthOf(1);
|
||||||
|
const parameters = compilerStub.callHistory[0].args[1];
|
||||||
|
expect(parameters.hasArgument(testCase.parameter));
|
||||||
|
const { argumentValue } = parameters.getArgument(testCase.parameter);
|
||||||
|
expect(argumentValue).to.equal(testCase.argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it('returns code as it is', () => {
|
||||||
|
// arrange
|
||||||
|
const expected = 'expected-code';
|
||||||
|
const compilerStub = new ExpressionsCompilerStub();
|
||||||
|
const context = new TestContext()
|
||||||
|
.withCompiler(compilerStub)
|
||||||
|
.withCode(expected);
|
||||||
|
// act
|
||||||
|
context.substitute();
|
||||||
|
// assert
|
||||||
|
expect(compilerStub.callHistory).to.have.lengthOf(1);
|
||||||
|
expect(compilerStub.callHistory[0].args[0]).to.equal(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
class CodeSubstituterBuilder {
|
class TestContext {
|
||||||
private compiler: IExpressionsCompiler = new ExpressionsCompilerStub();
|
private compiler: IExpressionsCompiler = new ExpressionsCompilerStub();
|
||||||
|
|
||||||
private date = new Date();
|
private date = new Date();
|
||||||
|
|
||||||
public withCompiler(compiler: IExpressionsCompiler) {
|
private code = `[${TestContext.name}] default code for testing`;
|
||||||
|
|
||||||
|
private projectDetails: ProjectDetails = new ProjectDetailsStub();
|
||||||
|
|
||||||
|
private callArgumentFactory
|
||||||
|
: FunctionCallArgumentFactory = new FunctionCallArgumentFactoryStub().factory;
|
||||||
|
|
||||||
|
public withCompiler(compiler: IExpressionsCompiler): this {
|
||||||
this.compiler = compiler;
|
this.compiler = compiler;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withDate(date: Date) {
|
public withDate(date: Date): this {
|
||||||
this.date = date;
|
this.date = date;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public build() {
|
public withCode(code: string): this {
|
||||||
return new CodeSubstituter(this.compiler, this.date);
|
this.code = code;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public withProjectDetails(projectDetails: ProjectDetails): this {
|
||||||
|
this.projectDetails = projectDetails;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public substitute(): ReturnType<typeof substituteCode> {
|
||||||
|
return substituteCode(
|
||||||
|
this.code,
|
||||||
|
this.projectDetails,
|
||||||
|
{
|
||||||
|
compiler: this.compiler,
|
||||||
|
provideDate: () => this.date,
|
||||||
|
createCallArgument: this.callArgumentFactory,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||||
import type { EnumParser } from '@/application/Common/Enum';
|
import type { EnumParser } from '@/application/Common/Enum';
|
||||||
import type { ICodeSubstituter } from '@/application/Parser/ScriptingDefinition/ICodeSubstituter';
|
import type { CodeSubstituter } from '@/application/Parser/ScriptingDefinition/CodeSubstituter';
|
||||||
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||||
import { ProjectDetailsStub } from '@tests/unit/shared/Stubs/ProjectDetailsStub';
|
import { ProjectDetailsStub } from '@tests/unit/shared/Stubs/ProjectDetailsStub';
|
||||||
import { EnumParserStub } from '@tests/unit/shared/Stubs/EnumParserStub';
|
import { EnumParserStub } from '@tests/unit/shared/Stubs/EnumParserStub';
|
||||||
@@ -83,7 +83,7 @@ describe('ScriptingDefinitionParser', () => {
|
|||||||
const context = new TestContext()
|
const context = new TestContext()
|
||||||
.withData(data)
|
.withData(data)
|
||||||
.withProjectDetails(projectDetails)
|
.withProjectDetails(projectDetails)
|
||||||
.withSubstituter(substituterMock);
|
.withSubstituter(substituterMock.substitute);
|
||||||
// act
|
// act
|
||||||
const definition = context.parseScriptingDefinition();
|
const definition = context.parseScriptingDefinition();
|
||||||
// assert
|
// assert
|
||||||
@@ -99,7 +99,7 @@ class TestContext {
|
|||||||
private languageParser: EnumParser<ScriptingLanguage> = new EnumParserStub<ScriptingLanguage>()
|
private languageParser: EnumParser<ScriptingLanguage> = new EnumParserStub<ScriptingLanguage>()
|
||||||
.setupDefaultValue(ScriptingLanguage.shellscript);
|
.setupDefaultValue(ScriptingLanguage.shellscript);
|
||||||
|
|
||||||
private codeSubstituter: ICodeSubstituter = new CodeSubstituterStub();
|
private codeSubstituter: CodeSubstituter = new CodeSubstituterStub().substitute;
|
||||||
|
|
||||||
private validator: TypeValidator = new TypeValidatorStub();
|
private validator: TypeValidator = new TypeValidatorStub();
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ class TestContext {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withSubstituter(substituter: ICodeSubstituter): this {
|
public withSubstituter(substituter: CodeSubstituter): this {
|
||||||
this.codeSubstituter = substituter;
|
this.codeSubstituter = substituter;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||||
import type { ICodeSubstituter } from '@/application/Parser/ScriptingDefinition/ICodeSubstituter';
|
import type { CodeSubstituter } from '@/application/Parser/ScriptingDefinition/CodeSubstituter';
|
||||||
|
|
||||||
export class CodeSubstituterStub implements ICodeSubstituter {
|
export class CodeSubstituterStub {
|
||||||
private readonly scenarios = new Array<{
|
private readonly scenarios = new Array<{
|
||||||
code: string, projectDetails: ProjectDetails, result: string }>();
|
code: string, projectDetails: ProjectDetails, result: string }>();
|
||||||
|
|
||||||
public substitute(code: string, projectDetails: ProjectDetails): string {
|
public setup(code: string, projectDetails: ProjectDetails, result: string) {
|
||||||
|
this.scenarios.push({ code, projectDetails, result });
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public substitute: CodeSubstituter = (code: string, projectDetails: ProjectDetails) => {
|
||||||
const scenario = this.scenarios.find(
|
const scenario = this.scenarios.find(
|
||||||
(s) => s.code === code && s.projectDetails === projectDetails,
|
(s) => s.code === code && s.projectDetails === projectDetails,
|
||||||
);
|
);
|
||||||
if (scenario) {
|
if (scenario) {
|
||||||
return scenario.result;
|
return scenario.result;
|
||||||
}
|
}
|
||||||
return `[CodeSubstituterStub] - code: ${code}`;
|
return `[${CodeSubstituterStub.name}] - code: ${code}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
public setup(code: string, projectDetails: ProjectDetails, result: string) {
|
|
||||||
this.scenarios.push({ code, projectDetails, result });
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { IFunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgument';
|
import type { FunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
import type { IFunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
|
import type { IFunctionCallArgumentCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
|
||||||
import { FunctionCallArgumentStub } from './FunctionCallArgumentStub';
|
import { FunctionCallArgumentStub } from './FunctionCallArgumentStub';
|
||||||
|
|
||||||
export class FunctionCallArgumentCollectionStub implements IFunctionCallArgumentCollection {
|
export class FunctionCallArgumentCollectionStub implements IFunctionCallArgumentCollection {
|
||||||
private args = new Array<IFunctionCallArgument>();
|
private args = new Array<FunctionCallArgument>();
|
||||||
|
|
||||||
public withEmptyArguments(): this {
|
public withEmptyArguments(): this {
|
||||||
this.args.length = 0;
|
this.args.length = 0;
|
||||||
@@ -36,7 +36,7 @@ export class FunctionCallArgumentCollectionStub implements IFunctionCallArgument
|
|||||||
return this.args.some((a) => a.parameterName === parameterName);
|
return this.args.some((a) => a.parameterName === parameterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addArgument(argument: IFunctionCallArgument): void {
|
public addArgument(argument: FunctionCallArgument): void {
|
||||||
this.args.push(argument);
|
this.args.push(argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ export class FunctionCallArgumentCollectionStub implements IFunctionCallArgument
|
|||||||
return this.args.map((a) => a.parameterName);
|
return this.args.map((a) => a.parameterName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getArgument(parameterName: string): IFunctionCallArgument {
|
public getArgument(parameterName: string): FunctionCallArgument {
|
||||||
const arg = this.args.find((a) => a.parameterName === parameterName);
|
const arg = this.args.find((a) => a.parameterName === parameterName);
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
throw new Error(`no argument exists for parameter "${parameterName}"`);
|
throw new Error(`no argument exists for parameter "${parameterName}"`);
|
||||||
|
|||||||
10
tests/unit/shared/Stubs/FunctionCallArgumentFactoryStub.ts
Normal file
10
tests/unit/shared/Stubs/FunctionCallArgumentFactoryStub.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import type { FunctionCallArgumentFactory } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
import { FunctionCallArgumentStub } from './FunctionCallArgumentStub';
|
||||||
|
|
||||||
|
export class FunctionCallArgumentFactoryStub {
|
||||||
|
public factory: FunctionCallArgumentFactory = (parameterName, argumentValue) => {
|
||||||
|
return new FunctionCallArgumentStub()
|
||||||
|
.withParameterName(parameterName)
|
||||||
|
.withArgumentValue(argumentValue);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { IFunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/IFunctionCallArgument';
|
import type { FunctionCallArgument } from '@/application/Parser/Executable/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
|
||||||
|
|
||||||
export class FunctionCallArgumentStub implements IFunctionCallArgument {
|
export class FunctionCallArgumentStub implements FunctionCallArgument {
|
||||||
public parameterName = 'stub-parameter-name';
|
public parameterName = 'stub-parameter-name';
|
||||||
|
|
||||||
public argumentValue = 'stub-arg-name';
|
public argumentValue = 'stub-arg-name';
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import type { IFunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/IFunctionParameter';
|
|
||||||
import type { IFunctionParameterCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/IFunctionParameterCollection';
|
import type { IFunctionParameterCollection } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/IFunctionParameterCollection';
|
||||||
|
import type { FunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameter';
|
||||||
import { FunctionParameterStub } from './FunctionParameterStub';
|
import { FunctionParameterStub } from './FunctionParameterStub';
|
||||||
|
|
||||||
export class FunctionParameterCollectionStub implements IFunctionParameterCollection {
|
export class FunctionParameterCollectionStub implements IFunctionParameterCollection {
|
||||||
private parameters = new Array<IFunctionParameter>();
|
private parameters = new Array<FunctionParameter>();
|
||||||
|
|
||||||
public addParameter(parameter: IFunctionParameter): void {
|
public addParameter(parameter: FunctionParameter): void {
|
||||||
this.parameters.push(parameter);
|
this.parameters.push(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get all(): readonly IFunctionParameter[] {
|
public get all(): readonly FunctionParameter[] {
|
||||||
return this.parameters;
|
return this.parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
tests/unit/shared/Stubs/FunctionParameterParserStub.ts
Normal file
8
tests/unit/shared/Stubs/FunctionParameterParserStub.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { FunctionParameterParser } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameterParser';
|
||||||
|
import { FunctionParameterStub } from './FunctionParameterStub';
|
||||||
|
|
||||||
|
export const createFunctionParameterParserStub: FunctionParameterParser = (parameters) => {
|
||||||
|
return new FunctionParameterStub()
|
||||||
|
.withName(parameters.name)
|
||||||
|
.withOptional(parameters.optional || false);
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { IFunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/IFunctionParameter';
|
import type { FunctionParameter } from '@/application/Parser/Executable/Script/Compiler/Function/Parameter/FunctionParameter';
|
||||||
|
|
||||||
export class FunctionParameterStub implements IFunctionParameter {
|
export class FunctionParameterStub implements FunctionParameter {
|
||||||
public name = 'function-parameter-stub';
|
public name = 'function-parameter-stub';
|
||||||
|
|
||||||
public isOptional = true;
|
public isOptional = true;
|
||||||
|
|||||||
12
tests/unit/shared/Stubs/ParameterNameValidatorStub.ts
Normal file
12
tests/unit/shared/Stubs/ParameterNameValidatorStub.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { ParameterNameValidator } from '@/application/Parser/Executable/Script/Compiler/Function/Shared/ParameterNameValidator';
|
||||||
|
|
||||||
|
export const createParameterNameValidatorStub = () => {
|
||||||
|
const validatedNames = new Array<string>();
|
||||||
|
const validator: ParameterNameValidator = (name) => {
|
||||||
|
validatedNames.push(name);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
validator,
|
||||||
|
validatedNames,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import type { NonEmptyCollectionAssertion, ObjectAssertion, TypeValidator } from '@/application/Parser/Common/TypeValidator';
|
import type {
|
||||||
|
NonEmptyCollectionAssertion, NonEmptyStringAssertion,
|
||||||
|
ObjectAssertion, TypeValidator,
|
||||||
|
} from '@/application/Parser/Common/TypeValidator';
|
||||||
import type { FunctionKeys } from '@/TypeHelpers';
|
import type { FunctionKeys } from '@/TypeHelpers';
|
||||||
import { expectDeepIncludes } from '@tests/shared/Assertions/ExpectDeepIncludes';
|
import { expectDeepIncludes } from '@tests/shared/Assertions/ExpectDeepIncludes';
|
||||||
import { StubWithObservableMethodCalls } from './StubWithObservableMethodCalls';
|
import { StubWithObservableMethodCalls } from './StubWithObservableMethodCalls';
|
||||||
@@ -22,6 +25,13 @@ export class TypeValidatorStub
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public assertNonEmptyString(assertion: NonEmptyStringAssertion): void {
|
||||||
|
this.registerMethodCall({
|
||||||
|
methodName: 'assertNonEmptyString',
|
||||||
|
args: [assertion],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public expectObjectAssertion<T>(
|
public expectObjectAssertion<T>(
|
||||||
expectedAssertion: ObjectAssertion<T>,
|
expectedAssertion: ObjectAssertion<T>,
|
||||||
): void {
|
): void {
|
||||||
@@ -34,6 +44,12 @@ export class TypeValidatorStub
|
|||||||
this.expectAssertion('assertNonEmptyCollection', expectedAssertion);
|
this.expectAssertion('assertNonEmptyCollection', expectedAssertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public expectNonEmptyStringAssertion(
|
||||||
|
expectedAssertion: NonEmptyStringAssertion,
|
||||||
|
): void {
|
||||||
|
this.expectAssertion('assertNonEmptyString', expectedAssertion);
|
||||||
|
}
|
||||||
|
|
||||||
private expectAssertion<T extends FunctionKeys<TypeValidator>>(
|
private expectAssertion<T extends FunctionKeys<TypeValidator>>(
|
||||||
methodName: T,
|
methodName: T,
|
||||||
expectedAssertion: Parameters<TypeValidator[T]>[0],
|
expectedAssertion: Parameters<TypeValidator[T]>[0],
|
||||||
|
|||||||
Reference in New Issue
Block a user