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.
Files changed (95) hide show
  1. package/LICENSE +674 -0
  2. package/dist/examples/extension/index.d.ts +1 -0
  3. package/dist/examples/extension/index.js +40 -0
  4. package/dist/examples/extension/index.js.map +1 -0
  5. package/dist/examples/parse-json-config/index.d.ts +1 -0
  6. package/dist/examples/parse-json-config/index.js +75 -0
  7. package/dist/examples/parse-json-config/index.js.map +1 -0
  8. package/dist/examples/parse-json-config/model/Config.d.ts +15 -0
  9. package/dist/examples/parse-json-config/model/Config.js +10 -0
  10. package/dist/examples/parse-json-config/model/Config.js.map +1 -0
  11. package/dist/examples/parse-json-config/model/DatabaseConnection.d.ts +26 -0
  12. package/dist/examples/parse-json-config/model/DatabaseConnection.js +12 -0
  13. package/dist/examples/parse-json-config/model/DatabaseConnection.js.map +1 -0
  14. package/dist/examples/parse-json-config/model/Socket.d.ts +15 -0
  15. package/dist/examples/parse-json-config/model/Socket.js +10 -0
  16. package/dist/examples/parse-json-config/model/Socket.js.map +1 -0
  17. package/dist/examples/parse-json-config/model/types/HostType.d.ts +4 -0
  18. package/dist/examples/parse-json-config/model/types/HostType.js +12 -0
  19. package/dist/examples/parse-json-config/model/types/HostType.js.map +1 -0
  20. package/dist/examples/parse-json-config/model/types/PortType.d.ts +5 -0
  21. package/dist/examples/parse-json-config/model/types/PortType.js +6 -0
  22. package/dist/examples/parse-json-config/model/types/PortType.js.map +1 -0
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.js +9 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/model/base/Model.d.ts +15 -0
  27. package/dist/model/base/Model.js +46 -0
  28. package/dist/model/base/Model.js.map +1 -0
  29. package/dist/model/base/Model.spec.d.ts +1 -0
  30. package/dist/model/base/Model.spec.js +82 -0
  31. package/dist/model/base/Model.spec.js.map +1 -0
  32. package/dist/types/UuidType.d.ts +8 -0
  33. package/dist/types/UuidType.js +15 -0
  34. package/dist/types/UuidType.js.map +1 -0
  35. package/dist/types/UuidType.spec.d.ts +1 -0
  36. package/dist/types/UuidType.spec.js +27 -0
  37. package/dist/types/UuidType.spec.js.map +1 -0
  38. package/dist/types/base/ArrayType.d.ts +11 -0
  39. package/dist/types/base/ArrayType.js +40 -0
  40. package/dist/types/base/ArrayType.js.map +1 -0
  41. package/dist/types/base/ArrayType.spec.d.ts +1 -0
  42. package/dist/types/base/ArrayType.spec.js +51 -0
  43. package/dist/types/base/ArrayType.spec.js.map +1 -0
  44. package/dist/types/base/AttributeType.d.ts +44 -0
  45. package/dist/types/base/AttributeType.js +61 -0
  46. package/dist/types/base/AttributeType.js.map +1 -0
  47. package/dist/types/base/BooleanType.d.ts +10 -0
  48. package/dist/types/base/BooleanType.js +24 -0
  49. package/dist/types/base/BooleanType.js.map +1 -0
  50. package/dist/types/base/BooleanType.spec.d.ts +1 -0
  51. package/dist/types/base/BooleanType.spec.js +41 -0
  52. package/dist/types/base/BooleanType.spec.js.map +1 -0
  53. package/dist/types/base/NumberType.d.ts +13 -0
  54. package/dist/types/base/NumberType.js +38 -0
  55. package/dist/types/base/NumberType.js.map +1 -0
  56. package/dist/types/base/NumberType.spec.d.ts +1 -0
  57. package/dist/types/base/NumberType.spec.js +72 -0
  58. package/dist/types/base/NumberType.spec.js.map +1 -0
  59. package/dist/types/base/StringArrayType.d.ts +5 -0
  60. package/dist/types/base/StringArrayType.js +6 -0
  61. package/dist/types/base/StringArrayType.js.map +1 -0
  62. package/dist/types/base/StringType.d.ts +27 -0
  63. package/dist/types/base/StringType.js +59 -0
  64. package/dist/types/base/StringType.js.map +1 -0
  65. package/dist/types/base/StringType.spec.d.ts +1 -0
  66. package/dist/types/base/StringType.spec.js +28 -0
  67. package/dist/types/base/StringType.spec.js.map +1 -0
  68. package/dist/util/InferType.d.ts +15 -0
  69. package/dist/util/InferType.js +2 -0
  70. package/dist/util/InferType.js.map +1 -0
  71. package/package.json +33 -0
  72. package/src/examples/extension/index.ts +65 -0
  73. package/src/examples/parse-json-config/index.ts +81 -0
  74. package/src/examples/parse-json-config/model/Config.ts +10 -0
  75. package/src/examples/parse-json-config/model/DatabaseConnection.ts +12 -0
  76. package/src/examples/parse-json-config/model/Socket.ts +10 -0
  77. package/src/examples/parse-json-config/model/types/HostType.ts +12 -0
  78. package/src/examples/parse-json-config/model/types/PortType.ts +6 -0
  79. package/src/index.ts +8 -0
  80. package/src/model/base/Model.spec.ts +84 -0
  81. package/src/model/base/Model.ts +55 -0
  82. package/src/types/UuidType.spec.ts +31 -0
  83. package/src/types/UuidType.ts +20 -0
  84. package/src/types/base/ArrayType.spec.ts +62 -0
  85. package/src/types/base/ArrayType.ts +44 -0
  86. package/src/types/base/AttributeType.ts +83 -0
  87. package/src/types/base/BooleanType.spec.ts +48 -0
  88. package/src/types/base/BooleanType.ts +28 -0
  89. package/src/types/base/NumberType.spec.ts +86 -0
  90. package/src/types/base/NumberType.ts +43 -0
  91. package/src/types/base/StringArrayType.ts +6 -0
  92. package/src/types/base/StringType.spec.ts +34 -0
  93. package/src/types/base/StringType.ts +69 -0
  94. package/src/util/InferType.ts +27 -0
  95. 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,6 @@
1
+ import { ArrayType } from "./ArrayType.js";
2
+ import { StringType } from "./StringType.js";
3
+
4
+ export class StringArrayType extends ArrayType<string, string>{
5
+ type = new StringType()
6
+ }
@@ -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
+ }