UNPKG

@freemework/common

Version:

Common library of the Freemework Project.

366 lines (329 loc) 10.7 kB
import { FException } from "../exception/index.js"; import { FDecimal } from "../primitive/index.js"; export abstract class FConfigurationValue { /** * Factory constructor */ public static factory(key: string, value: string | null, sourceURI: URL | null, overriden: FConfigurationValue | null): FConfigurationValue { return new _FConfigurationValue(key, value, sourceURI, overriden); } /** * Configuration source URI. * * See `sourceURI` in `FConfiguration` for details. */ public abstract get sourceURI(): URL | null; /** * Reference to an overriden value in chain configuration. */ public abstract get overridden(): FConfigurationValue | null; /** * Get `true` if value is `null` (configuration key presents but no value) */ public abstract get isNull(): boolean; /** * Key of current value (from root namespace) */ public abstract get key(): string; public abstract get asBase64(): Uint8Array; public abstract get asBase64Nullable(): Uint8Array | null; public abstract get asBoolean(): boolean; public abstract get asBooleanNullable(): boolean | null; public abstract get asDateIso8601(): Date; public abstract get asDateIso8601Nullable(): Date | null; public abstract get asDateTimestamp(): Date; public abstract get asDateTimestampNullable(): Date | null; public abstract get asDecimal(): FDecimal; public abstract get asDecimalNullable(): FDecimal | null; public abstract get asInteger(): number; public abstract get asIntegerNullable(): number | null; public abstract get asIntegerNegative(): number; public abstract get asIntegerNegativeNullable(): number | null; public abstract get asIntegerPositive(): number; public abstract get asIntegerPositiveNullable(): number | null; public abstract get asNumber(): number; public abstract get asNumberNullable(): number | null; /** * Gets value representations as TCP port */ public abstract get asPortNumber(): number; /** * Gets value representations as TCP port or `null` if value empty */ public abstract get asPortNumberNullable(): number | null; public abstract get asString(): string; public abstract get asStringNullable(): string | null; public abstract get asUrl(): URL; public abstract get asUrlNullable(): URL | null; } import { FConfigurationValueException } from "./f_configuration_value_exception.js"; class _FConfigurationValue extends FConfigurationValue { public get sourceURI(): URL | null { return this._sourceURI; } public get overridden(): FConfigurationValue | null { return this._overridden; } public get key(): string { return this._key; } public get isNull(): boolean { return this._value === null; } public get asBase64(): Uint8Array { this.assertNotNullValue(this._value, "asBase64"); return this.fromBase64(this._value); } public get asBase64Nullable(): Uint8Array | null { if (this._value === null) { return null; } return this.fromBase64(this._value); } public get asBoolean(): boolean { this.assertNotNullValue(this._value, "asBoolean"); return this.fromBoolean(this._value); } public get asBooleanNullable(): boolean | null { if (this._value === null) { return null; } return this.fromBoolean(this._value); } public get asDateIso8601(): Date { this.assertNotNullValue(this._value, "asDateIso8601"); return this.fromDateIso8601(this._value); } public get asDateIso8601Nullable(): Date | null { if (this._value === null) { return null; } return this.fromDateIso8601(this._value); } public get asDateTimestamp(): Date { this.assertNotNullValue(this._value, "asDateTimestamp"); return this.fromDateTimestamp(this._value); } public get asDateTimestampNullable(): Date | null { if (this._value === null) { return null; } return this.fromDateTimestamp(this._value); } public get asDecimal(): FDecimal { this.assertNotNullValue(this._value, "asDecimal"); return this.fromDecimal(this._value); } public get asDecimalNullable(): FDecimal | null { if (this._value === null) { return null; } return this.fromDecimal(this._value); } public get asInteger(): number { this.assertNotNullValue(this._value, "asInteger"); return this.fromInteger(this._value); } public get asIntegerNullable(): number | null { if (this._value === null) { return null; } return this.fromInteger(this._value); } public get asIntegerNegative(): number { this.assertNotNullValue(this._value, "asIntegerNegative"); return this.fromIntegerNegative(this._value); } public get asIntegerNegativeNullable(): number | null { if (this._value === null) { return null; } return this.fromIntegerNegative(this._value); } public get asIntegerPositive(): number { this.assertNotNullValue(this._value, "asIntegerPositive"); return this.fromIntegerPositive(this._value); } public get asIntegerPositiveNullable(): number | null { if (this._value === null) { return null; } return this.fromIntegerPositive(this._value); } public get asNumber(): number { this.assertNotNullValue(this._value, "asNumber"); return this.fromNumber(this._value); } public get asNumberNullable(): number | null { if (this._value === null) { return null; } return this.fromNumber(this._value); } public get asPortNumber(): number { this.assertNotNullValue(this._value, "asPortNumber"); return this.fromPortNumber(this._value); } public get asPortNumberNullable(): number | null { if (this._value === null) { return null; } return this.fromPortNumber(this._value); } public get asString(): string { this.assertNotNullValue(this._value, "asString"); return this.fromString(this._value); } public get asStringNullable(): string | null { if (this._value === null) { return null; } return this.fromString(this._value); } public get asUrl(): URL { this.assertNotNullValue(this._value, "asUrl"); return this.fromUrl(this._value); } public get asUrlNullable(): URL | null { if (this._value === null) { return null; } return this.fromUrl(this._value); } public constructor( private readonly _key: string, private readonly _value: string | null, private readonly _sourceURI: URL | null, private readonly _overridden: FConfigurationValue | null ) { super(); } public toJSON() { return this._value; } private assertNotNullValue( value: string | null, callerProperty: Exclude<keyof FConfigurationValue, "sourceURI" | "overridden" | "key"> ): asserts value is string { if (value === null) { throw new FConfigurationValueException( this, `Cannot represent null value ${callerProperty}`, this.key ); } } private fromBase64(value: string): Uint8Array { const parsedData = Buffer.from(value, "base64"); const restoredValue = parsedData.toString("base64"); if (restoredValue !== value) { const partOfValue = value.slice(0, 4); const maskValue = `${partOfValue}...`; throw new FConfigurationValueException( this, `Cannot parse value '${maskValue}' as base64.`, this.key, ); } return parsedData; } private fromBoolean(value: string): boolean { const lowerCaseValue: string = value.toLowerCase(); switch (lowerCaseValue) { case "true": case "enabled": case "yes": return true; case "false": case "disabled": case "no": return false; default: throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to boolean type.`, this.key, ); } } private fromDateIso8601(value: string): Date { const date = new Date(value); if (date.toString() === "Invalid Date") { throw new FConfigurationValueException( this, `Cannot parse value '${value}' as Date ISO8601. Invalid Date.`, this.key ); } return date; } private fromDateTimestamp(value: string): Date { const friendlyValue: number = Number.parseInt(value, 10); if (friendlyValue.toString() !== value) { throw new FConfigurationValueException( this, `Cannot parse value '${value}' as Date timestamp. Unparsable timestamp.`, this.key, ); } const date = new Date(friendlyValue); if (date.toString() === "Invalid Date") { throw new FConfigurationValueException( this, `Cannot parse value '${value}' as Date timestamp. Invalid Date.`, this.key ); } return date; } private fromDecimal(value: string): FDecimal { try { return FDecimal.parse(value); } catch (e) { throw new FConfigurationValueException( this, `Cannot parse value '${value}' as FDecimal.`, this.key, FException.wrapIfNeeded(e) ); } } private fromInteger(value: string): number { const friendlyValue = Number.parseInt(value, 10); if (friendlyValue.toString() === value) { return friendlyValue; } throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to integer type.`, this.key, ); } private fromIntegerNegative(value: string): number { const friendlyValue = this.fromInteger(value); if (friendlyValue < 0) { return friendlyValue; } throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to integer negative type.`, this.key, ); } private fromIntegerPositive(value: string): number { const friendlyValue = this.fromInteger(value); if (friendlyValue > 0) { return friendlyValue; } throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to integer positive type.`, this.key, ); } private fromNumber(value: string): number { const friendlyValue = Number.parseFloat(value); if (friendlyValue.toString() === value) { return friendlyValue; } throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to float type.`, this.key ); } private fromPortNumber(value: string): number { const friendlyValue = Number.parseInt(value); if (friendlyValue.toString() !== value) { throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to TCP port number.`, this.key ); } if (friendlyValue < 0 || friendlyValue > 65535) { throw new FConfigurationValueException( this, `Cannot convert the value '${value}' to TCP port number. Value out of range 0 - 65535.`, this.key ); } return friendlyValue; } private fromString(value: string): string { return value; } private fromUrl(value: string): URL { try { return new URL(value); } catch (e) { const partOfValue = value.slice(0, 4); const maskValue = `${partOfValue}...`; throw new FConfigurationValueException( this, `Cannot parse value '${maskValue}' as URL.`, this.key, FException.wrapIfNeeded(e) ); } } }