Refactor executable IDs to use strings #262
This commit unifies executable ID structure across categories and scripts, paving the way for more complex ID solutions for #262. It also refactors related code to adapt to the changes. Key changes: - Change numeric IDs to string IDs for categories - Use named types for string IDs to improve code clarity - Add unit tests to verify ID uniqueness Other supporting changes: - Separate concerns in entities for data access and executables by using separate abstractions (`Identifiable` and `RepositoryEntity`) - Simplify usage and construction of entities. - Remove `BaseEntity` for simplicity. - Move creation of categories/scripts to domain layer - Refactor CategoryCollection for better validation logic isolation - Rename some categories to keep the names (used as pseudo-IDs) unique on Windows.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { IApplication } from '@/domain/IApplication';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import { assertInRange } from '@/application/Common/Enum';
|
||||
import { CategoryCollectionState } from './State/CategoryCollectionState';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { AdaptiveFilterContext } from './Filter/AdaptiveFilterContext';
|
||||
import { ApplicationCode } from './Code/ApplicationCode';
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import type { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { splitTextIntoLines } from '@/application/Common/Text/SplitTextIntoLines';
|
||||
import type { ExecutableId } from '@/domain/Executables/Identifiable';
|
||||
import type { ICodeChangedEvent } from './ICodeChangedEvent';
|
||||
|
||||
export class CodeChangedEvent implements ICodeChangedEvent {
|
||||
@@ -37,12 +38,12 @@ export class CodeChangedEvent implements ICodeChangedEvent {
|
||||
}
|
||||
|
||||
public getScriptPositionInCode(script: Script): ICodePosition {
|
||||
return this.getPositionById(script.id);
|
||||
return this.getPositionById(script.executableId);
|
||||
}
|
||||
|
||||
private getPositionById(scriptId: string): ICodePosition {
|
||||
private getPositionById(scriptId: ExecutableId): ICodePosition {
|
||||
const position = [...this.scripts.entries()]
|
||||
.filter(([s]) => s.id === scriptId)
|
||||
.filter(([s]) => s.executableId === scriptId)
|
||||
.map(([, pos]) => pos)
|
||||
.at(0);
|
||||
if (!position) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { FilterChange } from './Event/FilterChange';
|
||||
import { LinearFilterStrategy } from './Strategy/LinearFilterStrategy';
|
||||
import type { FilterResult } from './Result/FilterResult';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import type { FilterResult } from '../Result/FilterResult';
|
||||
|
||||
export interface FilterStrategy {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Category } from '@/domain/Executables/Category/Category';
|
||||
import type { ScriptCode } from '@/domain/Executables/Script/Code/ScriptCode';
|
||||
import type { Documentable } from '@/domain/Executables/Documentable';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import { AppliedFilterResult } from '../Result/AppliedFilterResult';
|
||||
import type { FilterStrategy } from './FilterStrategy';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import type { IApplicationCode } from './Code/IApplicationCode';
|
||||
import type { ReadonlyFilterContext, FilterContext } from './Filter/FilterContext';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { ExecutableId } from '@/domain/Executables/Identifiable';
|
||||
|
||||
type CategorySelectionStatus = {
|
||||
readonly isSelected: true;
|
||||
readonly isReverted: boolean;
|
||||
@@ -6,7 +8,7 @@ type CategorySelectionStatus = {
|
||||
};
|
||||
|
||||
export interface CategorySelectionChange {
|
||||
readonly categoryId: number;
|
||||
readonly categoryId: ExecutableId;
|
||||
readonly newStatus: CategorySelectionStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Category } from '@/domain/Executables/Category/Category';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import type { CategorySelectionChange, CategorySelectionChangeCommand } from './CategorySelectionChange';
|
||||
import type { CategorySelection } from './CategorySelection';
|
||||
import type { ScriptSelection } from '../Script/ScriptSelection';
|
||||
@@ -23,7 +23,7 @@ export class ScriptToCategorySelectionMapper implements CategorySelection {
|
||||
return false;
|
||||
}
|
||||
return scripts.every(
|
||||
(script) => selectedScripts.some((selected) => selected.id === script.id),
|
||||
(script) => selectedScripts.some((selected) => selected.id === script.executableId),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ export class ScriptToCategorySelectionMapper implements CategorySelection {
|
||||
const scripts = category.getAllScriptsRecursively();
|
||||
const scriptsChangesInCategory = scripts
|
||||
.map((script): ScriptSelectionChange => ({
|
||||
scriptId: script.id,
|
||||
scriptId: script.executableId,
|
||||
newStatus: {
|
||||
...change.newStatus,
|
||||
},
|
||||
|
||||
@@ -2,8 +2,9 @@ import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryReposito
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||
import type { ReadonlyRepository, Repository } from '@/application/Repository/Repository';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { batchedDebounce } from '@/application/Common/Timing/BatchedDebounce';
|
||||
import type { ExecutableId } from '@/domain/Executables/Identifiable';
|
||||
import { UserSelectedScript } from './UserSelectedScript';
|
||||
import type { ScriptSelection } from './ScriptSelection';
|
||||
import type { ScriptSelectionChange, ScriptSelectionChangeCommand } from './ScriptSelectionChange';
|
||||
@@ -16,7 +17,7 @@ export type DebounceFunction = typeof batchedDebounce<ScriptSelectionChangeComma
|
||||
export class DebouncedScriptSelection implements ScriptSelection {
|
||||
public readonly changed = new EventSource<ReadonlyArray<SelectedScript>>();
|
||||
|
||||
private readonly scripts: Repository<string, SelectedScript>;
|
||||
private readonly scripts: Repository<SelectedScript>;
|
||||
|
||||
public readonly processChanges: ScriptSelection['processChanges'];
|
||||
|
||||
@@ -25,7 +26,7 @@ export class DebouncedScriptSelection implements ScriptSelection {
|
||||
selectedScripts: ReadonlyArray<SelectedScript>,
|
||||
debounce: DebounceFunction = batchedDebounce,
|
||||
) {
|
||||
this.scripts = new InMemoryRepository<string, SelectedScript>();
|
||||
this.scripts = new InMemoryRepository<SelectedScript>();
|
||||
for (const script of selectedScripts) {
|
||||
this.scripts.addItem(script);
|
||||
}
|
||||
@@ -38,8 +39,8 @@ export class DebouncedScriptSelection implements ScriptSelection {
|
||||
);
|
||||
}
|
||||
|
||||
public isSelected(scriptId: string): boolean {
|
||||
return this.scripts.exists(scriptId);
|
||||
public isSelected(scriptExecutableId: ExecutableId): boolean {
|
||||
return this.scripts.exists(scriptExecutableId);
|
||||
}
|
||||
|
||||
public get selectedScripts(): readonly SelectedScript[] {
|
||||
@@ -49,7 +50,7 @@ export class DebouncedScriptSelection implements ScriptSelection {
|
||||
public selectAll(): void {
|
||||
const scriptsToSelect = this.collection
|
||||
.getAllScripts()
|
||||
.filter((script) => !this.scripts.exists(script.id))
|
||||
.filter((script) => !this.scripts.exists(script.executableId))
|
||||
.map((script) => new UserSelectedScript(script, false));
|
||||
if (scriptsToSelect.length === 0) {
|
||||
return;
|
||||
@@ -116,12 +117,12 @@ export class DebouncedScriptSelection implements ScriptSelection {
|
||||
private applyChange(change: ScriptSelectionChange): number {
|
||||
const script = this.collection.getScript(change.scriptId);
|
||||
if (change.newStatus.isSelected) {
|
||||
return this.addOrUpdateScript(script.id, change.newStatus.isReverted);
|
||||
return this.addOrUpdateScript(script.executableId, change.newStatus.isReverted);
|
||||
}
|
||||
return this.removeScript(script.id);
|
||||
return this.removeScript(script.executableId);
|
||||
}
|
||||
|
||||
private addOrUpdateScript(scriptId: string, revert: boolean): number {
|
||||
private addOrUpdateScript(scriptId: ExecutableId, revert: boolean): number {
|
||||
const script = this.collection.getScript(scriptId);
|
||||
const selectedScript = new UserSelectedScript(script, revert);
|
||||
if (!this.scripts.exists(selectedScript.id)) {
|
||||
@@ -136,7 +137,7 @@ export class DebouncedScriptSelection implements ScriptSelection {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private removeScript(scriptId: string): number {
|
||||
private removeScript(scriptId: ExecutableId): number {
|
||||
if (!this.scripts.exists(scriptId)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -152,24 +153,24 @@ function assertNonEmptyScriptSelection(selectedItems: readonly Script[]) {
|
||||
}
|
||||
|
||||
function getScriptIdsToBeSelected(
|
||||
existingItems: ReadonlyRepository<string, SelectedScript>,
|
||||
existingItems: ReadonlyRepository<SelectedScript>,
|
||||
desiredScripts: readonly Script[],
|
||||
): string[] {
|
||||
return desiredScripts
|
||||
.filter((script) => !existingItems.exists(script.id))
|
||||
.map((script) => script.id);
|
||||
.filter((script) => !existingItems.exists(script.executableId))
|
||||
.map((script) => script.executableId);
|
||||
}
|
||||
|
||||
function getScriptIdsToBeDeselected(
|
||||
existingItems: ReadonlyRepository<string, SelectedScript>,
|
||||
existingItems: ReadonlyRepository<SelectedScript>,
|
||||
desiredScripts: readonly Script[],
|
||||
): string[] {
|
||||
return existingItems
|
||||
.getItems()
|
||||
.filter((existing) => !desiredScripts.some((script) => existing.id === script.id))
|
||||
.filter((existing) => !desiredScripts.some((script) => existing.id === script.executableId))
|
||||
.map((script) => script.id);
|
||||
}
|
||||
|
||||
function equals(a: SelectedScript, b: SelectedScript): boolean {
|
||||
return a.script.equals(b.script.id) && a.revert === b.revert;
|
||||
return a.script.executableId === b.script.executableId && a.revert === b.revert;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import type { ExecutableId } from '@/domain/Executables/Identifiable';
|
||||
import type { SelectedScript } from './SelectedScript';
|
||||
import type { ScriptSelectionChangeCommand } from './ScriptSelectionChange';
|
||||
|
||||
export interface ReadonlyScriptSelection {
|
||||
readonly changed: IEventSource<readonly SelectedScript[]>;
|
||||
readonly selectedScripts: readonly SelectedScript[];
|
||||
isSelected(scriptId: string): boolean;
|
||||
isSelected(scriptExecutableId: ExecutableId): boolean;
|
||||
}
|
||||
|
||||
export interface ScriptSelection extends ReadonlyScriptSelection {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { ExecutableId } from '@/domain/Executables/Identifiable';
|
||||
|
||||
export type ScriptSelectionStatus = {
|
||||
readonly isSelected: true;
|
||||
readonly isReverted: boolean;
|
||||
@@ -7,7 +9,7 @@ export type ScriptSelectionStatus = {
|
||||
};
|
||||
|
||||
export interface ScriptSelectionChange {
|
||||
readonly scriptId: string;
|
||||
readonly scriptId: ExecutableId;
|
||||
readonly newStatus: ScriptSelectionStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import type { IEntity } from '@/infrastructure/Entity/IEntity';
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import type { RepositoryEntity } from '@/application/Repository/RepositoryEntity';
|
||||
|
||||
type ScriptId = Script['id'];
|
||||
|
||||
export interface SelectedScript extends IEntity<ScriptId> {
|
||||
export interface SelectedScript extends RepositoryEntity {
|
||||
readonly script: Script;
|
||||
readonly revert: boolean;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { BaseEntity } from '@/infrastructure/Entity/BaseEntity';
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import type { SelectedScript } from './SelectedScript';
|
||||
import type { RepositoryEntity } from '@/application/Repository/RepositoryEntity';
|
||||
|
||||
type SelectedScriptId = SelectedScript['id'];
|
||||
export class UserSelectedScript implements RepositoryEntity {
|
||||
public readonly id: string;
|
||||
|
||||
export class UserSelectedScript extends BaseEntity<SelectedScriptId> {
|
||||
constructor(
|
||||
public readonly script: Script,
|
||||
public readonly revert: boolean,
|
||||
) {
|
||||
super(script.id);
|
||||
this.id = script.executableId;
|
||||
if (revert && !script.canRevert()) {
|
||||
throw new Error(`The script with ID '${script.id}' is not reversible and cannot be reverted.`);
|
||||
throw new Error(`The script with ID '${script.executableId}' is not reversible and cannot be reverted.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { ScriptToCategorySelectionMapper } from './Category/ScriptToCategorySelectionMapper';
|
||||
import { DebouncedScriptSelection } from './Script/DebouncedScriptSelection';
|
||||
import type { CategorySelection } from './Category/CategorySelection';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CollectionData } from '@/application/collections/';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import type { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||
import { CategoryCollection } from '@/domain/CategoryCollection';
|
||||
import type { ICategoryCollection } from '@/domain/Collection/ICategoryCollection';
|
||||
import { CategoryCollection } from '@/domain/Collection/CategoryCollection';
|
||||
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
|
||||
import { createEnumParser, type EnumParser } from '../Common/Enum';
|
||||
import { parseCategory, type CategoryParser } from './Executable/CategoryParser';
|
||||
|
||||
@@ -3,16 +3,14 @@ import type {
|
||||
} from '@/application/collections/';
|
||||
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||
import type { Category } from '@/domain/Executables/Category/Category';
|
||||
import { CollectionCategory } from '@/domain/Executables/Category/CollectionCategory';
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import { createCategory, type CategoryFactory } from '@/domain/Executables/Category/CategoryFactory';
|
||||
import { parseDocs, type DocsParser } from './DocumentationParser';
|
||||
import { parseScript, type ScriptParser } from './Script/ScriptParser';
|
||||
import { createExecutableDataValidator, type ExecutableValidator, type ExecutableValidatorFactory } from './Validation/ExecutableValidator';
|
||||
import { ExecutableType } from './Validation/ExecutableType';
|
||||
import type { CategoryCollectionSpecificUtilities } from './CategoryCollectionSpecificUtilities';
|
||||
|
||||
let categoryIdCounter = 0;
|
||||
|
||||
export const parseCategory: CategoryParser = (
|
||||
category: CategoryData,
|
||||
collectionUtilities: CategoryCollectionSpecificUtilities,
|
||||
@@ -59,7 +57,7 @@ function parseCategoryRecursively(
|
||||
}
|
||||
try {
|
||||
return context.categoryUtilities.createCategory({
|
||||
id: categoryIdCounter++,
|
||||
executableId: context.categoryData.category, // Pseudo-ID for uniqueness until real ID support
|
||||
name: context.categoryData.category,
|
||||
docs: context.categoryUtilities.parseDocs(context.categoryData),
|
||||
subcategories: children.subcategories,
|
||||
@@ -166,10 +164,6 @@ function hasProperty(
|
||||
return Object.prototype.hasOwnProperty.call(object, propertyName);
|
||||
}
|
||||
|
||||
export type CategoryFactory = (
|
||||
...parameters: ConstructorParameters<typeof CollectionCategory>
|
||||
) => Category;
|
||||
|
||||
interface CategoryParserUtilities {
|
||||
readonly createCategory: CategoryFactory;
|
||||
readonly wrapError: ErrorWithContextWrapper;
|
||||
@@ -179,7 +173,7 @@ interface CategoryParserUtilities {
|
||||
}
|
||||
|
||||
const DefaultCategoryParserUtilities: CategoryParserUtilities = {
|
||||
createCategory: (...parameters) => new CollectionCategory(...parameters),
|
||||
createCategory,
|
||||
wrapError: wrapErrorWithAdditionalContext,
|
||||
createValidator: createExecutableDataValidator,
|
||||
parseScript,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { ScriptData, CodeScriptData, CallScriptData } from '@/application/collections/';
|
||||
import { NoEmptyLines } from '@/application/Parser/Executable/Script/Validation/Rules/NoEmptyLines';
|
||||
import type { ILanguageSyntax } from '@/application/Parser/Executable/Script/Validation/Syntax/ILanguageSyntax';
|
||||
import { CollectionScript } from '@/domain/Executables/Script/CollectionScript';
|
||||
import { RecommendationLevel } from '@/domain/Executables/Script/RecommendationLevel';
|
||||
import type { ScriptCode } from '@/domain/Executables/Script/Code/ScriptCode';
|
||||
import type { ICodeValidator } from '@/application/Parser/Executable/Script/Validation/ICodeValidator';
|
||||
@@ -11,6 +10,7 @@ import { createScriptCode } from '@/domain/Executables/Script/Code/ScriptCodeFac
|
||||
import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import { createEnumParser, type EnumParser } from '@/application/Common/Enum';
|
||||
import { filterEmptyStrings } from '@/application/Common/Text/FilterEmptyStrings';
|
||||
import { createScript, type ScriptFactory } from '@/domain/Executables/Script/ScriptFactory';
|
||||
import { parseDocs, type DocsParser } from '../DocumentationParser';
|
||||
import { ExecutableType } from '../Validation/ExecutableType';
|
||||
import { createExecutableDataValidator, type ExecutableValidator, type ExecutableValidatorFactory } from '../Validation/ExecutableValidator';
|
||||
@@ -38,6 +38,7 @@ export const parseScript: ScriptParser = (
|
||||
validateScript(data, validator);
|
||||
try {
|
||||
const script = scriptUtilities.createScript({
|
||||
executableId: data.name, // Pseudo-ID for uniqueness until real ID support
|
||||
name: data.name,
|
||||
code: parseCode(
|
||||
data,
|
||||
@@ -132,14 +133,6 @@ interface ScriptParserUtilities {
|
||||
readonly parseDocs: DocsParser;
|
||||
}
|
||||
|
||||
export type ScriptFactory = (
|
||||
...parameters: ConstructorParameters<typeof CollectionScript>
|
||||
) => Script;
|
||||
|
||||
const createScript: ScriptFactory = (...parameters) => {
|
||||
return new CollectionScript(...parameters);
|
||||
};
|
||||
|
||||
const DefaultUtilities: ScriptParserUtilities = {
|
||||
levelParser: createEnumParser(RecommendationLevel),
|
||||
createScript,
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import type { IEntity } from '@/infrastructure/Entity/IEntity';
|
||||
import type { RepositoryEntity } from './RepositoryEntity';
|
||||
|
||||
export interface ReadonlyRepository<TKey, TEntity extends IEntity<TKey>> {
|
||||
type EntityId = RepositoryEntity['id'];
|
||||
|
||||
export interface ReadonlyRepository<TEntity extends RepositoryEntity> {
|
||||
readonly length: number;
|
||||
getItems(predicate?: (entity: TEntity) => boolean): readonly TEntity[];
|
||||
getById(id: TKey): TEntity;
|
||||
exists(id: TKey): boolean;
|
||||
getById(id: EntityId): TEntity;
|
||||
exists(id: EntityId): boolean;
|
||||
}
|
||||
|
||||
export interface MutableRepository<TKey, TEntity extends IEntity<TKey>> {
|
||||
export interface MutableRepository<TEntity extends RepositoryEntity> {
|
||||
addItem(item: TEntity): void;
|
||||
addOrUpdateItem(item: TEntity): void;
|
||||
removeItem(id: TKey): void;
|
||||
removeItem(id: EntityId): void;
|
||||
}
|
||||
|
||||
export interface Repository<TKey, TEntity extends IEntity<TKey>>
|
||||
extends ReadonlyRepository<TKey, TEntity>, MutableRepository<TKey, TEntity> { }
|
||||
export interface Repository<TEntity extends RepositoryEntity>
|
||||
extends ReadonlyRepository<TEntity>, MutableRepository<TEntity> { }
|
||||
|
||||
6
src/application/Repository/RepositoryEntity.ts
Normal file
6
src/application/Repository/RepositoryEntity.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/** Aggregate root */
|
||||
export type RepositoryEntityId = string;
|
||||
|
||||
export interface RepositoryEntity {
|
||||
readonly id: RepositoryEntityId;
|
||||
}
|
||||
@@ -3207,7 +3207,7 @@ actions:
|
||||
parameters:
|
||||
appCapability: bluetoothSync
|
||||
-
|
||||
category: Disable app access to voice activation
|
||||
category: Disable app voice activation
|
||||
docs: |- # refactor-with-variable: Same • App Access Caution
|
||||
This category safeguards against unauthorized app activation via voice commands.
|
||||
|
||||
@@ -15671,7 +15671,7 @@ actions:
|
||||
data: '1'
|
||||
deleteOnRevert: 'true' # Missing by default since Windows 10 Pro (≥ 22H2) and Windows 11 Pro (≥ 23H2)
|
||||
-
|
||||
category: Minimize CPU usage during scans
|
||||
category: Disable intensive CPU usage during Defender scans
|
||||
children:
|
||||
-
|
||||
name: Minimize CPU usage during scans
|
||||
@@ -15866,7 +15866,7 @@ actions:
|
||||
category: Disable scanning archive files
|
||||
children:
|
||||
-
|
||||
name: Disable scanning archive files
|
||||
name: Disable Defender archive file scanning
|
||||
docs:
|
||||
- https://admx.help/?Category=Windows_10_2016&Policy=Microsoft.Policies.WindowsDefender::Scan_DisableArchiveScanning
|
||||
# Managing with MpPreference module:
|
||||
|
||||
Reference in New Issue
Block a user