fogui-common 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/dist/examples/extension/index.d.ts +1 -0
- package/dist/examples/extension/index.js +40 -0
- package/dist/examples/extension/index.js.map +1 -0
- package/dist/examples/parse-json-config/index.d.ts +1 -0
- package/dist/examples/parse-json-config/index.js +75 -0
- package/dist/examples/parse-json-config/index.js.map +1 -0
- package/dist/examples/parse-json-config/model/Config.d.ts +15 -0
- package/dist/examples/parse-json-config/model/Config.js +10 -0
- package/dist/examples/parse-json-config/model/Config.js.map +1 -0
- package/dist/examples/parse-json-config/model/DatabaseConnection.d.ts +26 -0
- package/dist/examples/parse-json-config/model/DatabaseConnection.js +12 -0
- package/dist/examples/parse-json-config/model/DatabaseConnection.js.map +1 -0
- package/dist/examples/parse-json-config/model/Socket.d.ts +15 -0
- package/dist/examples/parse-json-config/model/Socket.js +10 -0
- package/dist/examples/parse-json-config/model/Socket.js.map +1 -0
- package/dist/examples/parse-json-config/model/types/HostType.d.ts +4 -0
- package/dist/examples/parse-json-config/model/types/HostType.js +12 -0
- package/dist/examples/parse-json-config/model/types/HostType.js.map +1 -0
- package/dist/examples/parse-json-config/model/types/PortType.d.ts +5 -0
- package/dist/examples/parse-json-config/model/types/PortType.js +6 -0
- package/dist/examples/parse-json-config/model/types/PortType.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/model/base/Model.d.ts +15 -0
- package/dist/model/base/Model.js +46 -0
- package/dist/model/base/Model.js.map +1 -0
- package/dist/model/base/Model.spec.d.ts +1 -0
- package/dist/model/base/Model.spec.js +82 -0
- package/dist/model/base/Model.spec.js.map +1 -0
- package/dist/types/UuidType.d.ts +8 -0
- package/dist/types/UuidType.js +15 -0
- package/dist/types/UuidType.js.map +1 -0
- package/dist/types/UuidType.spec.d.ts +1 -0
- package/dist/types/UuidType.spec.js +27 -0
- package/dist/types/UuidType.spec.js.map +1 -0
- package/dist/types/base/ArrayType.d.ts +11 -0
- package/dist/types/base/ArrayType.js +40 -0
- package/dist/types/base/ArrayType.js.map +1 -0
- package/dist/types/base/ArrayType.spec.d.ts +1 -0
- package/dist/types/base/ArrayType.spec.js +51 -0
- package/dist/types/base/ArrayType.spec.js.map +1 -0
- package/dist/types/base/AttributeType.d.ts +44 -0
- package/dist/types/base/AttributeType.js +61 -0
- package/dist/types/base/AttributeType.js.map +1 -0
- package/dist/types/base/BooleanType.d.ts +10 -0
- package/dist/types/base/BooleanType.js +24 -0
- package/dist/types/base/BooleanType.js.map +1 -0
- package/dist/types/base/BooleanType.spec.d.ts +1 -0
- package/dist/types/base/BooleanType.spec.js +41 -0
- package/dist/types/base/BooleanType.spec.js.map +1 -0
- package/dist/types/base/NumberType.d.ts +13 -0
- package/dist/types/base/NumberType.js +38 -0
- package/dist/types/base/NumberType.js.map +1 -0
- package/dist/types/base/NumberType.spec.d.ts +1 -0
- package/dist/types/base/NumberType.spec.js +72 -0
- package/dist/types/base/NumberType.spec.js.map +1 -0
- package/dist/types/base/StringArrayType.d.ts +5 -0
- package/dist/types/base/StringArrayType.js +6 -0
- package/dist/types/base/StringArrayType.js.map +1 -0
- package/dist/types/base/StringType.d.ts +27 -0
- package/dist/types/base/StringType.js +59 -0
- package/dist/types/base/StringType.js.map +1 -0
- package/dist/types/base/StringType.spec.d.ts +1 -0
- package/dist/types/base/StringType.spec.js +28 -0
- package/dist/types/base/StringType.spec.js.map +1 -0
- package/dist/util/InferType.d.ts +15 -0
- package/dist/util/InferType.js +2 -0
- package/dist/util/InferType.js.map +1 -0
- package/package.json +33 -0
- package/src/examples/extension/index.ts +65 -0
- package/src/examples/parse-json-config/index.ts +81 -0
- package/src/examples/parse-json-config/model/Config.ts +10 -0
- package/src/examples/parse-json-config/model/DatabaseConnection.ts +12 -0
- package/src/examples/parse-json-config/model/Socket.ts +10 -0
- package/src/examples/parse-json-config/model/types/HostType.ts +12 -0
- package/src/examples/parse-json-config/model/types/PortType.ts +6 -0
- package/src/index.ts +8 -0
- package/src/model/base/Model.spec.ts +84 -0
- package/src/model/base/Model.ts +55 -0
- package/src/types/UuidType.spec.ts +31 -0
- package/src/types/UuidType.ts +20 -0
- package/src/types/base/ArrayType.spec.ts +62 -0
- package/src/types/base/ArrayType.ts +44 -0
- package/src/types/base/AttributeType.ts +83 -0
- package/src/types/base/BooleanType.spec.ts +48 -0
- package/src/types/base/BooleanType.ts +28 -0
- package/src/types/base/NumberType.spec.ts +86 -0
- package/src/types/base/NumberType.ts +43 -0
- package/src/types/base/StringArrayType.ts +6 -0
- package/src/types/base/StringType.spec.ts +34 -0
- package/src/types/base/StringType.ts +69 -0
- package/src/util/InferType.ts +27 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export enum ParseAndValidationCriticality {
|
|
2
|
+
Ok = 0,
|
|
3
|
+
Silly,
|
|
4
|
+
Debug,
|
|
5
|
+
Info,
|
|
6
|
+
Warn,
|
|
7
|
+
Error,
|
|
8
|
+
}
|
|
9
|
+
export type ParseAndValidationResult = {
|
|
10
|
+
criticality: ParseAndValidationCriticality
|
|
11
|
+
messages: ParseAndValidationMessage[]
|
|
12
|
+
subValidationResults?: {[key:string]:ParseAndValidationResult}
|
|
13
|
+
}
|
|
14
|
+
export type ParseAndValidationMessage = {
|
|
15
|
+
criticality: ParseAndValidationCriticality
|
|
16
|
+
message: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type AttributeTypeOptions<InternalType> = {
|
|
20
|
+
defaultValue?: InternalType
|
|
21
|
+
allowNull?: boolean
|
|
22
|
+
extensionConfigurations?: ExtensionConfiguration[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type parseResult<T>= {value: T|undefined, deepResult: ParseAndValidationResult}
|
|
26
|
+
|
|
27
|
+
export interface ExtensionConfiguration {
|
|
28
|
+
extensionName: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let globalExtensionConfigurations: Record<string, Record<string, ExtensionConfiguration>> = {}
|
|
32
|
+
|
|
33
|
+
export function registerGlobalExtensionConfiguration(typeName: string, config: ExtensionConfiguration) {
|
|
34
|
+
if(!globalExtensionConfigurations[typeName]){
|
|
35
|
+
globalExtensionConfigurations[typeName] = {}
|
|
36
|
+
}
|
|
37
|
+
globalExtensionConfigurations[typeName][config.extensionName] = config
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class AttributeType<InternalType, ExternalType = string> {
|
|
41
|
+
value?: InternalType
|
|
42
|
+
extensionsConfigurations: Record<string, ExtensionConfiguration> = {}
|
|
43
|
+
get defaultValue(): InternalType | undefined {
|
|
44
|
+
return this._defaultValue
|
|
45
|
+
}
|
|
46
|
+
_defaultValue?: InternalType | undefined
|
|
47
|
+
allowNull?: boolean = true
|
|
48
|
+
constructor(options?: AttributeTypeOptions<InternalType>) {
|
|
49
|
+
options = options || {}
|
|
50
|
+
this._defaultValue = options.defaultValue
|
|
51
|
+
this.allowNull = options.allowNull !== undefined ? options.allowNull : true
|
|
52
|
+
if (options.extensionConfigurations) {
|
|
53
|
+
for (const extConfig of options.extensionConfigurations) {
|
|
54
|
+
this.extensionsConfigurations[extConfig.extensionName] = extConfig
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
parse(value: ExternalType): parseResult<InternalType> {
|
|
59
|
+
throw new Error("Method not implemented.");
|
|
60
|
+
}
|
|
61
|
+
format(value: InternalType): ExternalType {
|
|
62
|
+
throw new Error("Method not implemented.");
|
|
63
|
+
}
|
|
64
|
+
async validate(value: InternalType, level: ParseAndValidationCriticality = ParseAndValidationCriticality.Info): Promise<ParseAndValidationResult> {
|
|
65
|
+
let validateionObject:ParseAndValidationResult = {criticality:ParseAndValidationCriticality.Ok, messages:[]}
|
|
66
|
+
if(!value && this.allowNull===false)
|
|
67
|
+
validateionObject.messages.push({criticality:ParseAndValidationCriticality.Error, message:"Feld darf nicht leer sein."})
|
|
68
|
+
return validateionObject
|
|
69
|
+
}
|
|
70
|
+
getExtensionConfiguration(extensionName: string): ExtensionConfiguration | undefined {
|
|
71
|
+
let obj = this as AttributeType<any, any>
|
|
72
|
+
while(obj){
|
|
73
|
+
if(obj.extensionsConfigurations && obj.extensionsConfigurations[extensionName]){
|
|
74
|
+
return obj.extensionsConfigurations[extensionName]
|
|
75
|
+
}
|
|
76
|
+
if( globalExtensionConfigurations[obj.constructor.name] && globalExtensionConfigurations[obj.constructor.name][extensionName]){
|
|
77
|
+
return globalExtensionConfigurations[obj.constructor.name][extensionName]
|
|
78
|
+
}
|
|
79
|
+
obj = Object.getPrototypeOf(obj)
|
|
80
|
+
}
|
|
81
|
+
return undefined
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import { BooleanType } from "./BooleanType.js";
|
|
3
|
+
|
|
4
|
+
describe("BooleanType", () => {
|
|
5
|
+
let boolType: BooleanType;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
boolType = new BooleanType();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
describe("parse", () => {
|
|
12
|
+
it("should return true for truthy values", () => {
|
|
13
|
+
const truthy = ["true", "1", "yes", "on", "x"];
|
|
14
|
+
truthy.forEach(val => {
|
|
15
|
+
expect(boolType.parse(val).value).to.be.true;
|
|
16
|
+
expect(boolType.parse(val.toUpperCase()).value).to.be.true;
|
|
17
|
+
expect(boolType.parse(val.charAt(0).toUpperCase() + val.slice(1)).value).to.be.true;
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should return false for falsy values", () => {
|
|
22
|
+
const falsy = ["false", "0", "no", "off", "", "random"];
|
|
23
|
+
falsy.forEach(val => {
|
|
24
|
+
expect(boolType.parse(val).value).to.be.false;
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should return defaultValue for undefined or null", () => {
|
|
29
|
+
boolType._defaultValue = true;
|
|
30
|
+
//expect(boolType.parse(undefined)).to.equal(true);
|
|
31
|
+
expect(boolType.parse(null as any).value).to.equal(true);
|
|
32
|
+
|
|
33
|
+
boolType._defaultValue = false;
|
|
34
|
+
//expect(boolType.parse(undefined)).to.equal(false);
|
|
35
|
+
expect(boolType.parse(null as any).value).to.equal(false);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("format", () => {
|
|
40
|
+
it("should format true as 'true'", () => {
|
|
41
|
+
expect(boolType.format(true)).to.equal("true");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should format false as 'false'", () => {
|
|
45
|
+
expect(boolType.format(false)).to.equal("false");
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AttributeType, AttributeTypeOptions, ParseAndValidationCriticality, parseResult } from "./AttributeType.js";
|
|
2
|
+
|
|
3
|
+
export type BooleanTypeOptions = AttributeTypeOptions<boolean> & {
|
|
4
|
+
truthyValues?: string[]
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class BooleanType extends AttributeType<boolean> {
|
|
8
|
+
truthyValues = ["true", "1", "yes", "on", "x"]
|
|
9
|
+
constructor(options?: BooleanTypeOptions) {
|
|
10
|
+
options = options || {}
|
|
11
|
+
super(options)
|
|
12
|
+
if (options.truthyValues) {
|
|
13
|
+
this.truthyValues = options.truthyValues
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
parse(value: string): parseResult<boolean> {
|
|
17
|
+
if (value === undefined || value === null) {
|
|
18
|
+
return {value: this.defaultValue, deepResult: { criticality: ParseAndValidationCriticality.Info, messages: [{criticality: ParseAndValidationCriticality.Info, message:'No value given using default Value!'}] }}
|
|
19
|
+
}
|
|
20
|
+
else if (this.truthyValues.includes(value.toLowerCase())) {
|
|
21
|
+
return {value: true, deepResult: { criticality: ParseAndValidationCriticality.Ok, messages: [] } }
|
|
22
|
+
}
|
|
23
|
+
return {value: false, deepResult: { criticality: ParseAndValidationCriticality.Ok, messages: [] } }
|
|
24
|
+
}
|
|
25
|
+
format(value: boolean): string {
|
|
26
|
+
return value ? "true" : "false";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import { NumberType } from "./NumberType.js";
|
|
3
|
+
import { ParseAndValidationCriticality } from "./AttributeType.js";
|
|
4
|
+
|
|
5
|
+
describe("NumberType", () => {
|
|
6
|
+
let numberType: NumberType;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
numberType = new NumberType();
|
|
10
|
+
// Optionally set a default value for testing
|
|
11
|
+
numberType._defaultValue = 42;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe("parse", () => {
|
|
15
|
+
it("should parse a valid number string", () => {
|
|
16
|
+
expect(numberType.parse("123.45").value).to.equal(123.45);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should parse a negative number string", () => {
|
|
20
|
+
expect(numberType.parse("-99.99").value).to.equal(-99.99);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return defaultValue for invalid number string", () => {
|
|
24
|
+
expect(numberType.parse("abc").value).to.equal(42);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should return defaultValue for empty string", () => {
|
|
28
|
+
expect(numberType.parse("").value).to.equal(42);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should parse zero", () => {
|
|
32
|
+
expect(numberType.parse("0").value).to.equal(0);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("should parse string with leading/trailing spaces", () => {
|
|
36
|
+
expect(numberType.parse(" 77.7 ").value).to.equal(77.7);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("format", () => {
|
|
41
|
+
it("should format a number to string", () => {
|
|
42
|
+
expect(numberType.format(123.45)).to.equal("123.45");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should format zero", () => {
|
|
46
|
+
expect(numberType.format(0)).to.equal("0");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should format a negative number", () => {
|
|
50
|
+
expect(numberType.format(-99.99)).to.equal("-99.99");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe("validate", () => {
|
|
54
|
+
it("should validate a valid number", async () => {
|
|
55
|
+
const result = await numberType.validate(123.45);
|
|
56
|
+
expect(result.criticality).to.equal(0); // Assuming 0 is Ok
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should invalidate NaN", async () => {
|
|
60
|
+
const result = await numberType.validate(NaN);
|
|
61
|
+
expect(result.criticality).to.equal(ParseAndValidationCriticality.Error);
|
|
62
|
+
expect(result.messages).to.deep.include({ criticality: ParseAndValidationCriticality.Error, message: "Not a number" });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should invalidate number less than min", async () => {
|
|
66
|
+
numberType.min = 10;
|
|
67
|
+
const result = await numberType.validate(5);
|
|
68
|
+
expect(result.criticality).to.equal(ParseAndValidationCriticality.Error);
|
|
69
|
+
expect(result.messages).to.deep.include({ criticality: ParseAndValidationCriticality.Error, message: "Value is less than minimum 10" });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should invalidate number greater than max", async () => {
|
|
73
|
+
numberType.max = 100;
|
|
74
|
+
const result = await numberType.validate(150);
|
|
75
|
+
expect(result.criticality).to.equal(ParseAndValidationCriticality.Error);
|
|
76
|
+
expect(result.messages).to.deep.include({ criticality: ParseAndValidationCriticality.Error, message: "Value is greater than maximum 100" });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("should validate number within min and max", async () => {
|
|
80
|
+
numberType.min = 10;
|
|
81
|
+
numberType.max = 100;
|
|
82
|
+
const result = await numberType.validate(50);
|
|
83
|
+
expect(result.criticality).to.equal(0); // Assuming 0 is Ok
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AttributeType, AttributeTypeOptions, ParseAndValidationCriticality, ParseAndValidationResult, parseResult } from "./AttributeType.js";
|
|
2
|
+
|
|
3
|
+
export type NumberTypeOptions = {
|
|
4
|
+
max?: number,
|
|
5
|
+
min?: number
|
|
6
|
+
} & AttributeTypeOptions<number>
|
|
7
|
+
|
|
8
|
+
export class NumberType extends AttributeType<number> {
|
|
9
|
+
max: number
|
|
10
|
+
min: number
|
|
11
|
+
constructor(options?: NumberTypeOptions) {
|
|
12
|
+
options = options || {}
|
|
13
|
+
super(options)
|
|
14
|
+
this.max = options.max || Infinity
|
|
15
|
+
this.min = options.min || -Infinity
|
|
16
|
+
}
|
|
17
|
+
parse(value: string): parseResult<number> {
|
|
18
|
+
const number = parseFloat(value)
|
|
19
|
+
if (isNaN(number)) {
|
|
20
|
+
return {value: this.defaultValue, deepResult: { criticality: ParseAndValidationCriticality.Warn, messages: [{ criticality: ParseAndValidationCriticality.Warn, message: "Not a number useing default Value" }] }}
|
|
21
|
+
}
|
|
22
|
+
return {value: number, deepResult: { criticality: ParseAndValidationCriticality.Ok, messages: [] } }
|
|
23
|
+
}
|
|
24
|
+
validate(value: number, level?: ParseAndValidationCriticality): Promise<ParseAndValidationResult> {
|
|
25
|
+
let validationObject: ParseAndValidationResult = { criticality: ParseAndValidationCriticality.Ok, messages: [] }
|
|
26
|
+
if (isNaN(value)) {
|
|
27
|
+
validationObject.criticality = ParseAndValidationCriticality.Error
|
|
28
|
+
validationObject.messages.push({ criticality: ParseAndValidationCriticality.Error, message: "Not a number" })
|
|
29
|
+
}
|
|
30
|
+
if (value < this.min) {
|
|
31
|
+
validationObject.criticality = ParseAndValidationCriticality.Error
|
|
32
|
+
validationObject.messages.push({ criticality: ParseAndValidationCriticality.Error, message: `Value is less than minimum ${this.min}` })
|
|
33
|
+
}
|
|
34
|
+
if (value > this.max) {
|
|
35
|
+
validationObject.criticality = ParseAndValidationCriticality.Error
|
|
36
|
+
validationObject.messages.push({ criticality: ParseAndValidationCriticality.Error, message: `Value is greater than maximum ${this.max}` })
|
|
37
|
+
}
|
|
38
|
+
return Promise.resolve(validationObject)
|
|
39
|
+
}
|
|
40
|
+
format(value: number): string {
|
|
41
|
+
return value.toString()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import { StringType } from "./StringType.js";
|
|
3
|
+
|
|
4
|
+
describe("StringType", () => {
|
|
5
|
+
let stringType: StringType;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
stringType = new StringType({ defaultValue: "default" });
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
describe("parse", () => {
|
|
12
|
+
it("should return the value if it is not null or undefined", () => {
|
|
13
|
+
expect(stringType.parse("hello").value).to.equal("hello");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should return defaultValue if value is null", () => {
|
|
17
|
+
expect(stringType.parse(null as any).value).to.equal("default");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should return defaultValue if value is undefined", () => {
|
|
21
|
+
expect(stringType.parse(undefined as any).value).to.equal("default");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("format", () => {
|
|
26
|
+
it("should return the value as is", () => {
|
|
27
|
+
expect(stringType.format("world")).to.equal("world");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should return empty string as is", () => {
|
|
31
|
+
expect(stringType.format("")).to.equal("");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { AttributeType, AttributeTypeOptions, ParseAndValidationCriticality, ParseAndValidationResult, parseResult } from "./AttributeType.js";
|
|
2
|
+
|
|
3
|
+
export type StringTypeOptions = AttributeTypeOptions<string> & {
|
|
4
|
+
maxLength?: number
|
|
5
|
+
minLength?: number
|
|
6
|
+
matchPattern?: RegExp
|
|
7
|
+
matchPatternMessage?: string
|
|
8
|
+
parsePattern?: RegExp
|
|
9
|
+
parseReplacement?: string
|
|
10
|
+
parsePatternMessage?: string
|
|
11
|
+
formatPattern?: RegExp
|
|
12
|
+
formatReplacement?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class StringType<ExternalType extends string = string> extends AttributeType<string, ExternalType> {
|
|
16
|
+
maxLength: number
|
|
17
|
+
minLength: number
|
|
18
|
+
parsePattern: RegExp | null
|
|
19
|
+
parseReplacement: string | null
|
|
20
|
+
parsePatternMessage: string
|
|
21
|
+
matchPattern: RegExp | null
|
|
22
|
+
matchPatternMessage: string | null
|
|
23
|
+
formatPattern: RegExp | null
|
|
24
|
+
formatReplacement: string | null
|
|
25
|
+
constructor(options?: StringTypeOptions) {
|
|
26
|
+
options = options || {}
|
|
27
|
+
super(options)
|
|
28
|
+
this.maxLength = options.maxLength || 255
|
|
29
|
+
this.minLength = options.minLength || 0
|
|
30
|
+
this.parsePattern = options.parsePattern || null
|
|
31
|
+
this.parseReplacement = options.parseReplacement || null
|
|
32
|
+
this.parsePatternMessage = options.parsePatternMessage || `Parse pattern not matched: "${this.parsePattern}"`
|
|
33
|
+
this.matchPattern = options.matchPattern || null
|
|
34
|
+
this.matchPatternMessage = options.matchPatternMessage || null
|
|
35
|
+
this.formatPattern = options.formatPattern || null
|
|
36
|
+
this.formatReplacement = options.formatReplacement || null
|
|
37
|
+
}
|
|
38
|
+
parse(value: ExternalType): parseResult<string> {
|
|
39
|
+
if(!value) return {value: this.defaultValue, deepResult: { criticality: ParseAndValidationCriticality.Info, messages: [{criticality: ParseAndValidationCriticality.Info, message:'No value given using default Value!'}] }}
|
|
40
|
+
if(this.parsePattern && this.parseReplacement){
|
|
41
|
+
if(!this.parsePattern.test(value)) throw new Error(this.parsePatternMessage)
|
|
42
|
+
value = value.replace(this.parsePattern, this.parseReplacement) as ExternalType
|
|
43
|
+
}
|
|
44
|
+
return {value, deepResult: { criticality: ParseAndValidationCriticality.Ok, messages: [] } }
|
|
45
|
+
}
|
|
46
|
+
async validate(value: string, level?: ParseAndValidationCriticality): Promise<ParseAndValidationResult> {
|
|
47
|
+
console.log("Validating string:", value)
|
|
48
|
+
let validationObject = await super.validate(value, level)
|
|
49
|
+
if(value && this.matchPattern && !this.matchPattern.test(value)){
|
|
50
|
+
validationObject.messages.push({criticality:ParseAndValidationCriticality.Error, message: this.matchPatternMessage || `Validierungsmuster nicht erfüllt: "${this.matchPattern}"`})
|
|
51
|
+
validationObject.criticality=Math.max(validationObject.criticality,ParseAndValidationCriticality.Error)
|
|
52
|
+
}
|
|
53
|
+
if(value && value.length < this.minLength){
|
|
54
|
+
validationObject.messages.push({criticality:ParseAndValidationCriticality.Error, message: `Es müssen mindesten ${this.minLength} Zeichen eingegeben werden.`})
|
|
55
|
+
validationObject.criticality=Math.max(validationObject.criticality,ParseAndValidationCriticality.Error)
|
|
56
|
+
}
|
|
57
|
+
if(value && value.length > this.maxLength){
|
|
58
|
+
validationObject.messages.push({criticality:ParseAndValidationCriticality.Error, message: `Es dürfen maximal ${this.maxLength} Zeichen eingegeben werden.`})
|
|
59
|
+
validationObject.criticality=Math.max(validationObject.criticality,ParseAndValidationCriticality.Error)
|
|
60
|
+
}
|
|
61
|
+
return validationObject
|
|
62
|
+
}
|
|
63
|
+
format(value: string): ExternalType {
|
|
64
|
+
if(this.formatPattern && this.formatReplacement){
|
|
65
|
+
value = value.replace(this.formatPattern, this.formatReplacement)
|
|
66
|
+
}
|
|
67
|
+
return value as ExternalType;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Model } from "../model/base/Model.js";
|
|
2
|
+
import { ArrayType } from "../types/base/ArrayType.js";
|
|
3
|
+
import { AttributeType } from "../types/base/AttributeType.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
type RequriedKeys<T> = {
|
|
7
|
+
[K in keyof T]: T[K] extends { required: true } ? K : never;
|
|
8
|
+
}[keyof T];
|
|
9
|
+
|
|
10
|
+
type OptionalKeys<T> = {
|
|
11
|
+
[K in keyof T]: T[K] extends { required: true } ? never : K;
|
|
12
|
+
}[keyof T];
|
|
13
|
+
|
|
14
|
+
type PartialPartial<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K> extends
|
|
15
|
+
infer O ? { [P in keyof O]: O[P] } : never;
|
|
16
|
+
|
|
17
|
+
export type InferType<T> = T extends Model
|
|
18
|
+
?
|
|
19
|
+
PartialPartial<{[K in keyof T["properties"]]: InferType<T["properties"][K]["type"]>},
|
|
20
|
+
OptionalKeys<T["properties"]>>
|
|
21
|
+
|
|
22
|
+
: T extends ArrayType<infer U, infer V>
|
|
23
|
+
? InferType<T["type"]>[]
|
|
24
|
+
:
|
|
25
|
+
T extends AttributeType<infer U>
|
|
26
|
+
? U
|
|
27
|
+
: never;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"noEmitOnError": true,
|
|
7
|
+
"lib": ["es2022", "dom"],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"allowSyntheticDefaultImports": true,
|
|
11
|
+
"experimentalDecorators": true,
|
|
12
|
+
"importHelpers": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"outDir": "dist",
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"inlineSources": true,
|
|
17
|
+
"rootDir": "./src/",
|
|
18
|
+
"incremental": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*.ts"]
|
|
21
|
+
}
|