Skip to content

Commit

Permalink
Move Most Class Properties Into Constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
BellCubeDev committed Nov 3, 2023
1 parent 77cb637 commit 4a787e2
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 187 deletions.
37 changes: 13 additions & 24 deletions src/definitions/Dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,13 @@ export abstract class Dependency<TStrict extends boolean = boolean> extends XmlR

export class Dependencies<TTagName extends 'moduleDependencies'|'dependencies', TStrict extends boolean = true> extends Dependency {
static override readonly tagName = ['moduleDependencies', 'dependencies'];
readonly tagName: TTagName;

operator: TStrict extends true ? 'And' | 'Or' : string;
dependencies: Set<Dependency<TStrict>>;

constructor(tagName: TTagName, operator?: TStrict extends true ? 'And' | 'Or' : string, dependencies?: Set<Dependency<TStrict>>) {
constructor(
public readonly tagName: TTagName,
public operator: TStrict extends true ? 'And' | 'Or' : string = 'And',
public dependencies: Set<Dependency<TStrict>> = new Set()
) {
super();

this.tagName = tagName;

this.operator = operator ?? 'And';
this.dependencies = dependencies ?? new Set();
}

isValid(): this is Dependencies<TTagName, true> {
Expand Down Expand Up @@ -105,13 +100,8 @@ export class FileDependency<TStrict extends boolean = true> extends Dependency<T
static override readonly tagName = 'fileDependency';
readonly tagName = 'fileDependency';

filePath: string;
desiredState: TStrict extends true ? 'Active'|'Inactive'|'Missing' : string;

constructor(filePath?: string, desiredState?: TStrict extends true ? 'Active'|'Inactive'|'Missing' : string) {
constructor(public filePath: string = '', public desiredState: TStrict extends true ? 'Active'|'Inactive'|'Missing' : string = 'Active') {
super();
this.filePath = filePath ?? '';
this.desiredState = desiredState ?? 'Active';
}

isValid(): this is FileDependency<true> {
Expand Down Expand Up @@ -225,15 +215,14 @@ export class FlagDependency extends Dependency {
* Version dependencies work as a minimum value dependency. [SemVer](https://semver.org/) is used for comparisons.
*/
export abstract class VersionDependency extends Dependency {
/** The version to use in the comparison
*
* Version dependencies work as a minimum value dependency. [SemVer](https://semver.org/) is used for comparisons.
*/
desiredVersion: string;

constructor(desiredVersion?: string) {
constructor(
/** The version to use in the comparison
*
* Version dependencies work as a minimum value dependency. [SemVer](https://semver.org/) is used for comparisons.
*/
public desiredVersion: string = '',
) {
super();
this.desiredVersion = desiredVersion ?? '';
}

isValid() { return true; }
Expand Down
49 changes: 25 additions & 24 deletions src/definitions/FlagInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@ interface FlagInstances {
export const FlagInstancesByDocument = new WeakMap<Document, FlagInstances>();

export class FlagInstance<TIsOption extends boolean, TWrite extends (TIsOption extends true ? false : boolean)> {
private _name: TIsOption extends true ? Option : string;

/** The name of the flag this instance refers to
*
* Automatically updates the flag instance map when changed.
*/
get name() { return this._name; }
set name(value: TIsOption extends true ? Option : string) {
if (this.name === value) {
Expand All @@ -43,31 +38,37 @@ export class FlagInstance<TIsOption extends boolean, TWrite extends (TIsOption e
this._name = value;
}


/** The value being checked/set by this instance
*
* When the flag represents a traditional key-value, this will be a string. When the flag represents an option's select state, this will be a boolean.
*/
usedValue: TIsOption extends true ? boolean : string;

/** Whether this instance is reading or writing the flag value
*
* When the flag represents an option's select state, this mist be `false` (since you cannot set the value of an option's select state)
*/
write: TWrite;

/** A list of documents this flag is a part of */
documents: Set<Document> = new Set();

constructor(name: TIsOption extends true ? never : string, usedValue: string, write: TWrite, document?: Document)
constructor(name: TIsOption extends true ? Option : never, usedValue: boolean, write: TWrite, document?: Document)
constructor(name: TIsOption extends true ? Option : string, usedValue: TIsOption extends true? boolean : string, write: TWrite, document?: Document) {
constructor(_name: TIsOption extends true ? never : string, usedValue: string, write: TWrite, document?: Document)
constructor(_name: TIsOption extends true ? Option : never, usedValue: boolean, write: TWrite, document?: Document)
constructor(
/** The name of the flag this instance refers to
*
* Automatically updates the flag instance map when changed.
*/
private _name: TIsOption extends true ? Option : string,


/** The value being checked/set by this instance
*
* When the flag represents a traditional key-value, this will be a string. When the flag represents an option's select state, this will be a boolean.
*/
public usedValue: TIsOption extends true? boolean : string,

/** Whether this instance is reading or writing the flag value
*
* When the flag represents an option's select state, this mist be `false` (since you cannot set the value of an option's select state)
*/
public write: TWrite,

document?: Document
) {
if (typeof name === 'string' && typeof usedValue !== 'string') throw new Error(`FlagInstance's 'usedValue' property must be a string when name is a string`);
else if (name instanceof Option && typeof usedValue !== 'boolean') throw new Error(`FlagInstance's 'usedValue' property must be a boolean when name is an Option`);
else if (_name instanceof Option && typeof usedValue !== 'boolean') throw new Error(`FlagInstance's 'usedValue' property must be a boolean when name is an Option`);

this._name = name;
this.usedValue = usedValue as TIsOption extends true ? boolean : string;
this.write = write;

if (document) this.attachDocument(document);
}
Expand Down
69 changes: 34 additions & 35 deletions src/definitions/Fomod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ElementObjectMap, Verifiable, XmlRepresentation } from "./_core";
export interface ModuleImageMetadata<TStrict extends boolean = true> {
showFade?: TStrict extends true ? `${boolean}` : string;
showImage?: TStrict extends true ? `${boolean}` : string;
height?: TStrict extends true ? `${bigint}` : string;
height?: TStrict extends true ? `${bigint}`|'' : string;
}

export interface ModuleNameMetadata<TStrict extends boolean = true> {
Expand All @@ -35,43 +35,43 @@ export class Fomod<TStrict extends boolean = true> extends XmlRepresentation<TSt
static override readonly tagName = 'config';
readonly tagName = 'config';

/** The name of the FOMOD. Must be specified in the installer however can be an empty string. */
moduleName: string;

/** Unused metadata for `moduleName`. Included for completeness.
*
* @deprecated
*/
moduleNameMetadata: (TStrict extends true ? Record<never, string> : Record<string, string>) & ModuleNameMetadata<TStrict> = {};

/** Default image for the FOMOD. Not required and will be removed if an empty string is specified. */
moduleImage: string|null;

/** Unused metadata for `moduleImage`. Included for completeness.
*
* @deprecated
*/
moduleImageMetadata: (TStrict extends true ? Record<never, string> : Record<Exclude<string, 'path'>, string>) & ModuleImageMetadata<TStrict> = {};

/** Dependencies required for this FOMOD to be shown to the user.
*
* Mod managers will show the user an error message if attempting to install a FOMOD that does not meet the requirements specified here.
*/
moduleDependencies: Dependencies<'moduleDependencies', TStrict>;

steps = new Set<Step<TStrict>>();

/** Top-level file installs for the FOMOD
*
* Covers both the `requiredInstallFiles` and `conditionalFileInstalls` tags.
*/
installs = new Set<Install<TStrict> | InstallPattern<TStrict>>();

constructor(moduleName: string = '', moduleImage: string|null = null, moduleDependencies?: Dependencies<'moduleDependencies', TStrict>) {
constructor(
/** The name of the FOMOD. Must be specified in the installer however can be an empty string.
*
* Note that Info.xml also has its own name.
*/
public moduleName: string = '',
public moduleImage: string|null = null,
/** Dependencies required for this FOMOD to be shown to the user.
*
* Mod managers will show the user an error message if attempting to install a FOMOD that does not meet the requirements specified here.
*/
public moduleDependencies: Dependencies<'moduleDependencies', TStrict> = new Dependencies<'moduleDependencies', TStrict>('moduleDependencies'),
/** Top-level file installs for the FOMOD
*
* Covers both the `requiredInstallFiles` and `conditionalFileInstalls` tags.
*/
public installs: Set<Install<TStrict> | InstallPattern<TStrict>> = new Set(),

public steps: Set<Step<TStrict>> = new Set(),

/** Unused metadata for `moduleName`. Included for completeness.
*
* @deprecated
*/
public moduleNameMetadata: (TStrict extends true ? Record<never, string> : Record<string, string>) & ModuleNameMetadata<TStrict> = {},

/** Unused metadata for `moduleImage`. Included for completeness.
*
* @deprecated
*/
public moduleImageMetadata: (TStrict extends true ? Record<never, string> : Record<Exclude<string, 'path'>, string>) & ModuleImageMetadata<TStrict> = {},

) {
super();
this.moduleName = moduleName;
this.moduleImage = moduleImage;
this.moduleDependencies = moduleDependencies ?? new Dependencies<'moduleDependencies', TStrict>('moduleDependencies');
}

isValid(): this is Fomod<true> {
Expand Down Expand Up @@ -229,4 +229,3 @@ export class Fomod<TStrict extends boolean = true> extends XmlRepresentation<TSt
this.installs.forEach(install => install.decommission?.(currentDocument!));
}
}

15 changes: 6 additions & 9 deletions src/definitions/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,14 @@ export class Group<TStrict extends boolean = true> extends XmlRepresentation<TSt
static override readonly tagName = 'group';
readonly tagName = 'group';

name: string;
behaviorType: TStrict extends true ? GroupBehaviorType : string;
sortingOrder: TStrict extends true ? SortingOrder : string;
options: Set<Option<TStrict>> = new Set();

constructor(name: string = '', behaviorType: TStrict extends true ? GroupBehaviorType : string = GroupBehaviorType.SelectExactlyOne, sortingOrder: TStrict extends true ? SortingOrder : string = SortingOrder.Ascending) {
constructor(
public name: string = '',
public behaviorType: TStrict extends true ? GroupBehaviorType : string = GroupBehaviorType.SelectExactlyOne,
public sortingOrder: TStrict extends true ? SortingOrder : string = SortingOrder.Ascending,
public options: Set<Option<TStrict>> = new Set(),
) {
super();

this.name = name;
this.behaviorType = behaviorType;
this.sortingOrder = sortingOrder;
}

asElement(document: Document): Element {
Expand Down
82 changes: 40 additions & 42 deletions src/definitions/Install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,36 +51,6 @@ export class Install<TStrict extends boolean = true> extends XmlRepresentation<T
static override readonly tagName = ['file', 'folder'];
tagName: 'file'|'folder' = 'file'; // Very interchangeable;

/** File path relative to the archive root to install this file from.
*
* Whether a folder is being installed or not will be determined by if the path ends with a slash. It **WILL** cause errors later down the line if the source and destination paths are not the same type.
*/
fileSource: string;

/** File path relative to the archive root to install this file from. If no destination is provided, the file will be installed to the same path as the source.
*
* Whether a folder is being installed or not will be determined by if the path ends with a slash. It **WILL** cause errors later down the line if the source and destination paths are not the same type.
*/
fileDestination: string | null;

/** Whether to always install the file, even if the user has not selected it.
*
* @deprecated Has inconsistent behavior between mod managers. Instead, you might consider removing the `dependencies` object instead. Included for completeness.
*/
alwaysInstall: TStrict extends true ? `${boolean}` : string = 'false';

/** Whether to always install the file if it is considered "usable"
*
* @deprecated Has inconsistent behavior between mod managers. Instead, you might consider duplicating the `dependencies` object to specify when a file should be installed. Included for completeness.
*/
installIfUsable: TStrict extends true ? `${boolean}` : string = 'false';

/** The priority of this file install. Higher priority files will be installed first. Must be an integer.
*
* Defaults to `0`. If the value is `0`, the value will not be written to the element.
*/
priority: TStrict extends true ? `${bigint}` : string;


/** A list of documents this install is a part of */
documents: Set<Document> = new Set();
Expand Down Expand Up @@ -112,13 +82,41 @@ export class Install<TStrict extends boolean = true> extends XmlRepresentation<T
return null;
}

constructor(fileSource: string = '', fileDestination: string | null = null, priority: TStrict extends true ? `${bigint}` : string, document?: Document) {
constructor(
/** File path relative to the archive root to install this file from.
*
* Whether a folder is being installed or not will be determined by if the path ends with a slash. It **WILL** cause errors later down the line if the source and destination paths are not the same type.
*/
public fileSource: string = '',

/** File path relative to the archive root to install this file from. If no destination is provided, the file will be installed to the same path as the source.
*
* Whether a folder is being installed or not will be determined by if the path ends with a slash. It **WILL** cause errors later down the line if the source and destination paths are not the same type.
*/
public fileDestination: string | null = null,

/** The priority of this file install. Higher priority files will be installed first. Must be an integer.
*
* Defaults to `0`. If the value is `0`, the value will not be written to the element.
*/
public priority: TStrict extends true ? `${bigint}` | '' : string = '',

document?: Document,

/** Whether to always install the file if it is considered "usable"
*
* @deprecated Has inconsistent behavior between mod managers. Instead, you might consider duplicating the `dependencies` object to specify when a file should be installed. Included for completeness.
*/
public installIfUsable: TStrict extends true ? `${boolean}` : string = 'false',

/** Whether to always install the file, even if the user has not selected it.
*
* @deprecated Has inconsistent behavior between mod managers. Instead, you might consider removing the `dependencies` object instead. Included for completeness.
*/
public alwaysInstall: TStrict extends true ? `${boolean}` : string = 'false',
) {
super();

this.fileSource = fileSource;
this.fileDestination = fileDestination;
this.priority = priority;

if (document) this.attachDocument(document);
}

Expand Down Expand Up @@ -281,9 +279,9 @@ export class InstallPatternFilesWrapper<TStrict extends boolean = true> extends
static override tagName = 'files';
readonly tagName = 'files';

installs: Set<Install<TStrict>> = new Set();

constructor() {
constructor(
public installs: Set<Install<TStrict>> = new Set(),
) {
super();
}

Expand Down Expand Up @@ -367,10 +365,10 @@ export class InstallPattern<TStrict extends boolean = true> extends XmlRepresent
static override tagName = 'pattern';
readonly tagName = 'pattern';

dependencies: Dependencies<'dependencies', TStrict>|null = null;
filesWrapper: InstallPatternFilesWrapper = new InstallPatternFilesWrapper();

constructor() {
constructor(
public dependencies: Dependencies<'dependencies', TStrict>|null = null,
public filesWrapper: InstallPatternFilesWrapper = new InstallPatternFilesWrapper(),
) {
super();
}

Expand Down
7 changes: 3 additions & 4 deletions src/definitions/Metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ export class FomodInfo extends XmlRepresentation<boolean> {
static override readonly tagName = 'fomod';
readonly tagName = 'fomod';

data: FomodInfoData;

constructor(data: FomodInfoData = {}) {
constructor(
public data: FomodInfoData = {}
) {
super();
this.data = data;
}

isValid() { return true; }
Expand Down
Loading

0 comments on commit 4a787e2

Please sign in to comment.