diff --git a/common/static-xlrs/src/core/xlr/Asset.json b/common/static-xlrs/src/core/xlr/Asset.json index 2398e4d..d5a4e36 100644 --- a/common/static-xlrs/src/core/xlr/Asset.json +++ b/common/static-xlrs/src/core/xlr/Asset.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "Asset", "type": "object", - "source": "src/index.ts", "properties": { "id": { "required": true, diff --git a/common/static-xlrs/src/core/xlr/AssetBinding.json b/common/static-xlrs/src/core/xlr/AssetBinding.json index ba2dd31..f4de5bc 100644 --- a/common/static-xlrs/src/core/xlr/AssetBinding.json +++ b/common/static-xlrs/src/core/xlr/AssetBinding.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "AssetBinding", "type": "object", - "source": "src/index.ts", "properties": { "binding": { "required": true, diff --git a/common/static-xlrs/src/core/xlr/AssetSwitch.json b/common/static-xlrs/src/core/xlr/AssetSwitch.json index 3f0f4ba..18f73f9 100644 --- a/common/static-xlrs/src/core/xlr/AssetSwitch.json +++ b/common/static-xlrs/src/core/xlr/AssetSwitch.json @@ -1,23 +1,23 @@ { - "name": "AssetSwitch", "source": "src/index.ts", + "name": "AssetSwitch", "type": "or", "or": [ { - "name": "StaticSwitch", - "type": "object", "source": "src/index.ts", + "name": "StaticSwitch", + "type": "object", "properties": { "staticSwitch": { "required": true, "node": { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -40,8 +40,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", @@ -101,20 +100,20 @@ ] }, { - "name": "DynamicSwitch", - "type": "object", "source": "src/index.ts", + "name": "DynamicSwitch", + "type": "object", "properties": { "dynamicSwitch": { "required": true, "node": { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -137,8 +136,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", diff --git a/common/static-xlrs/src/core/xlr/AssetWrapper.json b/common/static-xlrs/src/core/xlr/AssetWrapper.json index 74be978..7b6a206 100644 --- a/common/static-xlrs/src/core/xlr/AssetWrapper.json +++ b/common/static-xlrs/src/core/xlr/AssetWrapper.json @@ -1,6 +1,6 @@ { - "name": "AssetWrapper", "source": "src/index.ts", + "name": "AssetWrapper", "type": "object", "properties": { "asset": { diff --git a/common/static-xlrs/src/core/xlr/AssetWrapperOrSwitch.json b/common/static-xlrs/src/core/xlr/AssetWrapperOrSwitch.json index c7fb328..bd688c1 100644 --- a/common/static-xlrs/src/core/xlr/AssetWrapperOrSwitch.json +++ b/common/static-xlrs/src/core/xlr/AssetWrapperOrSwitch.json @@ -1,6 +1,6 @@ { - "name": "AssetWrapperOrSwitch", "source": "src/index.ts", + "name": "AssetWrapperOrSwitch", "type": "or", "or": [ { @@ -44,20 +44,20 @@ "type": "and", "and": [ { - "name": "StaticSwitch", - "type": "object", "source": "src/index.ts", + "name": "StaticSwitch", + "type": "object", "properties": { "staticSwitch": { "required": true, "node": { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -80,8 +80,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", @@ -168,20 +167,20 @@ "type": "and", "and": [ { - "name": "DynamicSwitch", - "type": "object", "source": "src/index.ts", + "name": "DynamicSwitch", + "type": "object", "properties": { "dynamicSwitch": { "required": true, "node": { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -204,8 +203,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", diff --git a/common/static-xlrs/src/core/xlr/Binding.json b/common/static-xlrs/src/core/xlr/Binding.json index 025f515..16f0053 100644 --- a/common/static-xlrs/src/core/xlr/Binding.json +++ b/common/static-xlrs/src/core/xlr/Binding.json @@ -1,6 +1,6 @@ { - "name": "Binding", "source": "src/index.ts", + "name": "Binding", "type": "string", "title": "Binding", "description": "Bindings describe locations in the data model." diff --git a/common/static-xlrs/src/core/xlr/BindingRef.json b/common/static-xlrs/src/core/xlr/BindingRef.json index d79e4ed..8af7d73 100644 --- a/common/static-xlrs/src/core/xlr/BindingRef.json +++ b/common/static-xlrs/src/core/xlr/BindingRef.json @@ -1,6 +1,6 @@ { - "name": "BindingRef", "source": "src/index.ts", + "name": "BindingRef", "type": "template", "format": "{{.*}}", "title": "BindingRef" diff --git a/common/static-xlrs/src/core/xlr/DataModel.json b/common/static-xlrs/src/core/xlr/DataModel.json index c545c9a..6c12404 100644 --- a/common/static-xlrs/src/core/xlr/DataModel.json +++ b/common/static-xlrs/src/core/xlr/DataModel.json @@ -1,6 +1,6 @@ { - "name": "DataModel", "source": "src/index.ts", + "name": "DataModel", "type": "record", "keyType": { "type": "any" diff --git a/common/static-xlrs/src/core/xlr/DynamicSwitch.json b/common/static-xlrs/src/core/xlr/DynamicSwitch.json index 1b05ee9..2be5b9b 100644 --- a/common/static-xlrs/src/core/xlr/DynamicSwitch.json +++ b/common/static-xlrs/src/core/xlr/DynamicSwitch.json @@ -1,18 +1,18 @@ { + "source": "src/index.ts", "name": "DynamicSwitch", "type": "object", - "source": "src/index.ts", "properties": { "dynamicSwitch": { "required": true, "node": { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -35,8 +35,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", diff --git a/common/static-xlrs/src/core/xlr/Expression.json b/common/static-xlrs/src/core/xlr/Expression.json index 215a7bc..f1892bb 100644 --- a/common/static-xlrs/src/core/xlr/Expression.json +++ b/common/static-xlrs/src/core/xlr/Expression.json @@ -1,6 +1,6 @@ { - "name": "Expression", "source": "src/index.ts", + "name": "Expression", "type": "or", "or": [ { diff --git a/common/static-xlrs/src/core/xlr/ExpressionObject.json b/common/static-xlrs/src/core/xlr/ExpressionObject.json index b0ca2b7..7926901 100644 --- a/common/static-xlrs/src/core/xlr/ExpressionObject.json +++ b/common/static-xlrs/src/core/xlr/ExpressionObject.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, diff --git a/common/static-xlrs/src/core/xlr/ExpressionRef.json b/common/static-xlrs/src/core/xlr/ExpressionRef.json index 1c24855..2a339fd 100644 --- a/common/static-xlrs/src/core/xlr/ExpressionRef.json +++ b/common/static-xlrs/src/core/xlr/ExpressionRef.json @@ -1,6 +1,6 @@ { - "name": "ExpressionRef", "source": "src/index.ts", + "name": "ExpressionRef", "type": "template", "format": "@[.*]@", "title": "ExpressionRef" diff --git a/common/static-xlrs/src/core/xlr/Flow.json b/common/static-xlrs/src/core/xlr/Flow.json index 963bb54..f031613 100644 --- a/common/static-xlrs/src/core/xlr/Flow.json +++ b/common/static-xlrs/src/core/xlr/Flow.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "Flow", "type": "object", - "source": "src/index.ts", "properties": { "id": { "required": true, @@ -16,8 +16,8 @@ "node": { "type": "array", "elementType": { - "name": "View", "source": "src/index.ts", + "name": "View", "type": "conditional", "check": { "left": { @@ -45,7 +45,7 @@ "node": { "type": "array", "elementType": { - "name": "CrossfieldReference", + "name": "Validation.CrossfieldReference", "type": "object", "properties": { "type": { @@ -72,13 +72,11 @@ "or": [ { "type": "string", - "const": "error", - "title": "Severity" + "const": "error" }, { "type": "string", - "const": "warning", - "title": "Severity" + "const": "warning" } ], "title": "Reference.severity", @@ -93,18 +91,15 @@ "or": [ { "type": "string", - "const": "navigation", - "title": "Trigger" + "const": "navigation" }, { "type": "string", - "const": "change", - "title": "Trigger" + "const": "change" }, { "type": "string", - "const": "load", - "title": "Trigger" + "const": "load" } ], "title": "Reference.trigger", @@ -127,24 +122,40 @@ "or": [ { "type": "string", - "const": "page", - "title": "DisplayTarget" + "const": "page" }, { "type": "string", - "const": "section", - "title": "DisplayTarget" + "const": "section" }, { "type": "string", - "const": "field", - "title": "DisplayTarget" + "const": "field" } ], "title": "Reference.displayTarget", "description": "Where the error should be displayed" } }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + }, "ref": { "required": false, "node": { @@ -196,7 +207,7 @@ "schema": { "required": false, "node": { - "name": "Schema", + "name": "Schema.Schema", "type": "object", "properties": { "ROOT": { @@ -206,166 +217,989 @@ "type": "object", "properties": {}, "additionalProperties": { - "name": "DataType", - "type": "object", - "properties": { - "type": { - "required": true, - "node": { - "type": "string", - "title": "DataType.type", - "description": "The reference of the base type to use" - } - }, - "isArray": { - "required": false, - "node": { - "type": "boolean", - "title": "DataType.isArray", - "description": "The referenced object represents an array rather than an object" - } - }, - "validation": { - "required": false, - "node": { - "type": "array", - "elementType": { - "name": "Reference", - "type": "object", - "properties": { - "type": { - "required": true, - "node": { - "type": "string", - "title": "Reference.type", - "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" - } - }, - "message": { - "required": false, - "node": { - "type": "string", - "title": "Reference.message", - "description": "An optional means of overriding the default message if the validation is triggered" - } - }, - "severity": { - "required": false, - "node": { - "name": "Severity", - "type": "or", - "or": [ - { - "type": "string", - "const": "error", - "title": "Severity" - }, - { + "name": "DataTypes", + "type": "or", + "or": [ + { + "name": "DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { "type": "string", - "const": "warning", - "title": "Severity" + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" } - ], - "title": "Reference.severity", - "description": "An optional means of overriding the default severity of the validation if triggered" - } - }, - "trigger": { - "required": false, - "node": { - "name": "Trigger", - "type": "or", - "or": [ - { - "type": "string", - "const": "navigation", - "title": "Trigger" - }, - { - "type": "string", - "const": "change", - "title": "Trigger" - }, - { + }, + "message": { + "required": false, + "node": { "type": "string", - "const": "load", - "title": "Trigger" + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" } - ], - "title": "Reference.trigger", - "description": "When to run this particular validation" - } - }, - "dataTarget": { - "required": false, - "node": { - "type": "or", - "or": [ - { - "type": "string", - "const": "formatted", - "title": "Reference.dataTarget" - }, - { - "type": "string", - "const": "deformatted", - "title": "Reference.dataTarget" + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" } - ], - "title": "Reference.dataTarget", - "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" - } - }, - "displayTarget": { - "required": false, - "node": { - "name": "DisplayTarget", - "type": "or", - "or": [ - { - "type": "string", - "const": "page", - "title": "DisplayTarget" - }, - { - "type": "string", - "const": "section", - "title": "DisplayTarget" - }, - { - "type": "string", - "const": "field", - "title": "DisplayTarget" + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" } - ], - "title": "Reference.displayTarget", - "description": "Where the error should be displayed" + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } } - } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" }, - "additionalProperties": { + "default": { "type": "unknown" - }, - "title": "Reference", - "description": "A reference to a validation object" - }, - "title": "DataType.validation", - "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" - } + } + } + ] }, - "format": { - "required": false, - "node": { - "name": "Reference", - "type": "object", - "properties": { - "type": { - "required": true, - "node": { - "type": "string", - "title": "Reference.type", - "description": "The name of the formatter (and de-formatter) to use" - } + { + "name": "RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "RecordType", + "description": "Determines if the Datatype is a record object" + }, + { + "name": "ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } + }, + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" + } + ], + "title": "DataTypes" + }, + "title": "Schema.ROOT", + "description": "The ROOT object is the top level object to use" + } + } + }, + "additionalProperties": { + "name": "Node", + "type": "object", + "properties": {}, + "additionalProperties": { + "name": "DataTypes", + "type": "or", + "or": [ + { + "name": "DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" + }, + "default": { + "type": "unknown" + } + } + ] + }, + { + "name": "RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } } }, "additionalProperties": { @@ -383,230 +1217,235 @@ "title": "DataType.default", "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } } }, "additionalProperties": { "type": "unknown" }, - "title": "DataType", - "description": "Each prop in the object can have a specific DataType", - "genericTokens": [ - { - "symbol": "T", - "constraints": { - "type": "any" - }, - "default": { - "type": "unknown" - } - } - ] - }, - "title": "Schema.ROOT", - "description": "The ROOT object is the top level object to use" - } - } - }, - "additionalProperties": { - "name": "Node", - "type": "object", - "properties": {}, - "additionalProperties": { - "name": "DataType", - "type": "object", - "properties": { - "type": { - "required": true, - "node": { - "type": "string", - "title": "DataType.type", - "description": "The reference of the base type to use" - } - }, - "isArray": { - "required": false, - "node": { - "type": "boolean", - "title": "DataType.isArray", - "description": "The referenced object represents an array rather than an object" - } + "title": "RecordType", + "description": "Determines if the Datatype is a record object" }, - "validation": { - "required": false, - "node": { - "type": "array", - "elementType": { - "name": "Reference", - "type": "object", - "properties": { - "type": { - "required": true, - "node": { - "type": "string", - "title": "Reference.type", - "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" - } - }, - "message": { - "required": false, - "node": { - "type": "string", - "title": "Reference.message", - "description": "An optional means of overriding the default message if the validation is triggered" - } - }, - "severity": { - "required": false, - "node": { - "name": "Severity", - "type": "or", - "or": [ - { - "type": "string", - "const": "error", - "title": "Severity" - }, - { + { + "name": "ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { "type": "string", - "const": "warning", - "title": "Severity" + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" } - ], - "title": "Reference.severity", - "description": "An optional means of overriding the default severity of the validation if triggered" - } - }, - "trigger": { - "required": false, - "node": { - "name": "Trigger", - "type": "or", - "or": [ - { - "type": "string", - "const": "navigation", - "title": "Trigger" - }, - { - "type": "string", - "const": "change", - "title": "Trigger" - }, - { + }, + "message": { + "required": false, + "node": { "type": "string", - "const": "load", - "title": "Trigger" + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" } - ], - "title": "Reference.trigger", - "description": "When to run this particular validation" + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } } }, - "dataTarget": { - "required": false, - "node": { - "type": "or", - "or": [ - { - "type": "string", - "const": "formatted", - "title": "Reference.dataTarget" - }, - { - "type": "string", - "const": "deformatted", - "title": "Reference.dataTarget" - } - ], - "title": "Reference.dataTarget", - "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" - } + "additionalProperties": { + "type": "unknown" }, - "displayTarget": { - "required": false, - "node": { - "name": "DisplayTarget", - "type": "or", - "or": [ - { - "type": "string", - "const": "page", - "title": "DisplayTarget" - }, - { - "type": "string", - "const": "section", - "title": "DisplayTarget" - }, - { - "type": "string", - "const": "field", - "title": "DisplayTarget" - } - ], - "title": "Reference.displayTarget", - "description": "Where the error should be displayed" - } - } - }, - "additionalProperties": { - "type": "unknown" - }, - "title": "Reference", - "description": "A reference to a validation object" + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } }, - "title": "DataType.validation", - "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" - } - }, - "format": { - "required": false, - "node": { - "name": "Reference", - "type": "object", - "properties": { - "type": { - "required": true, - "node": { - "type": "string", - "title": "Reference.type", - "description": "The name of the formatter (and de-formatter) to use" - } + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." } }, - "additionalProperties": { - "type": "unknown" + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } }, - "title": "DataType.format", - "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" - } - }, - "default": { - "required": false, - "node": { - "type": "ref", - "ref": "T", - "title": "DataType.default", - "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." - } - } - }, - "additionalProperties": { - "type": "unknown" - }, - "title": "DataType", - "description": "Each prop in the object can have a specific DataType", - "genericTokens": [ - { - "symbol": "T", - "constraints": { - "type": "any" + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } }, - "default": { + "additionalProperties": { "type": "unknown" - } + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" } - ] + ], + "title": "DataTypes" }, "title": "Node", "description": "A Node describes a specific object in the tree" @@ -618,8 +1457,8 @@ "data": { "required": false, "node": { - "name": "DataModel", "source": "src/index.ts", + "name": "DataModel", "type": "record", "keyType": { "type": "any" @@ -634,8 +1473,8 @@ "navigation": { "required": true, "node": { - "name": "Navigation", "source": "src/index.ts", + "name": "Navigation", "type": "and", "and": [ { @@ -664,9 +1503,9 @@ "type": "string" }, { + "source": "src/index.ts", "name": "NavigationFlow", "type": "object", - "source": "src/index.ts", "properties": { "startState": { "required": true, @@ -687,9 +1526,9 @@ "title": "NavigationFlow.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -721,9 +1560,9 @@ "title": "NavigationFlow.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -759,9 +1598,9 @@ "ref": "Expression" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -778,14 +1617,14 @@ "description": "An object with an expression in it" }, { - "name": "NavigationFlowState", "source": "src/index.ts", + "name": "NavigationFlowState", "type": "or", "or": [ { + "source": "src/index.ts", "name": "NavigationFlowViewState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -815,9 +1654,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -849,9 +1688,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -882,8 +1721,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -916,14 +1755,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowViewState", "description": "A state representing a view" }, { + "source": "src/index.ts", "name": "NavigationFlowEndState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -953,9 +1794,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -987,9 +1828,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1026,14 +1867,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowEndState", "description": "An END state of the flow." }, { + "source": "src/index.ts", "name": "NavigationFlowFlowState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -1063,9 +1906,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1097,9 +1940,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1130,8 +1973,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -1156,9 +1999,9 @@ "title": "NavigationFlowFlowState" }, { + "source": "src/index.ts", "name": "NavigationFlowActionState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -1188,9 +2031,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1222,9 +2065,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1257,8 +2100,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -1276,9 +2119,137 @@ "description": "Action states execute an expression to determine the next state to transition to" }, { - "name": "NavigationFlowExternalState", + "source": "src/index.ts", + "name": "NavigationFlowAsyncActionState", "type": "object", + "properties": { + "_comment": { + "required": false, + "node": { + "type": "string", + "title": "CommentBase._comment", + "description": "Add comments that will not be processing, but are useful for code explanation" + } + }, + "state_type": { + "required": true, + "node": { + "type": "string", + "const": "ASYNC_ACTION", + "title": "NavigationBaseState.state_type", + "description": "A property to determine the type of state this is" + } + }, + "onStart": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onStart" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onStart", + "description": "An optional expression to run when this view renders" + } + }, + "onEnd": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onEnd" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onEnd", + "description": "An optional expression to run before view transition" + } + }, + "exp": { + "required": true, + "node": { + "type": "ref", + "ref": "Expression", + "title": "NavigationFlowAsyncActionState.exp", + "description": "An expression to execute.\nThe return value determines the transition to take" + } + }, + "transitions": { + "required": true, + "node": { + "source": "src/index.ts", + "name": "NavigationFlowTransition", + "type": "record", + "keyType": { + "type": "string" + }, + "valueType": { + "type": "string" + }, + "title": "NavigationFlowTransitionableState.transitions", + "description": "A mapping of transition-name to FlowState name" + } + }, + "await": { + "required": true, + "node": { + "type": "boolean", + "title": "NavigationFlowAsyncActionState.await", + "description": "Whether the expression(s) should be awaited before transitioning" + } + } + }, + "additionalProperties": false, + "title": "NavigationFlowAsyncActionState", + "description": "Action states execute an expression to determine the next state to transition to" + }, + { "source": "src/index.ts", + "name": "NavigationFlowExternalState", + "type": "object", "properties": { "_comment": { "required": false, @@ -1308,9 +2279,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1342,9 +2313,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -1375,8 +2346,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -1397,7 +2368,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowExternalState", "description": "External Flow states represent states in the FSM that can't be resolved internally in Player.\nThe flow will wait for the embedded application to manage moving to the next state via a transition" } diff --git a/common/static-xlrs/src/core/xlr/FlowResult.json b/common/static-xlrs/src/core/xlr/FlowResult.json index 0c3706b..a1d3f6f 100644 --- a/common/static-xlrs/src/core/xlr/FlowResult.json +++ b/common/static-xlrs/src/core/xlr/FlowResult.json @@ -1,14 +1,14 @@ { + "source": "src/index.ts", "name": "FlowResult", "type": "object", - "source": "src/index.ts", "properties": { "endState": { "required": true, "node": { + "source": "src/index.ts", "name": "NavigationFlowEndState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -38,9 +38,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -72,9 +72,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -111,7 +111,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "FlowResult.endState", "description": "The outcome describes _how_ the flow ended (forwards, backwards, etc)" } diff --git a/common/static-xlrs/src/core/xlr/Formatting.Reference.json b/common/static-xlrs/src/core/xlr/Formatting.Reference.json new file mode 100644 index 0000000..b0ba867 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Formatting.Reference.json @@ -0,0 +1,19 @@ +{ + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a specific formatter" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Language.DataTypeRef.json b/common/static-xlrs/src/core/xlr/Language.DataTypeRef.json new file mode 100644 index 0000000..c7b0463 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Language.DataTypeRef.json @@ -0,0 +1,17 @@ +{ + "name": "Language.DataTypeRef", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataTypeRef.type", + "description": "Name of the type in Player Core" + } + } + }, + "additionalProperties": false, + "title": "DataTypeRef", + "description": "Helper to compliment `Schema.DataType` to provide a way to export a reference to a data type instead of the whole object" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Navigation.json b/common/static-xlrs/src/core/xlr/Navigation.json index f9cb37b..5bfa13c 100644 --- a/common/static-xlrs/src/core/xlr/Navigation.json +++ b/common/static-xlrs/src/core/xlr/Navigation.json @@ -1,6 +1,6 @@ { - "name": "Navigation", "source": "src/index.ts", + "name": "Navigation", "type": "and", "and": [ { @@ -29,9 +29,9 @@ "type": "string" }, { + "source": "src/index.ts", "name": "NavigationFlow", "type": "object", - "source": "src/index.ts", "properties": { "startState": { "required": true, @@ -52,9 +52,9 @@ "title": "NavigationFlow.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -86,9 +86,9 @@ "title": "NavigationFlow.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -124,9 +124,9 @@ "ref": "Expression" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -143,14 +143,14 @@ "description": "An object with an expression in it" }, { - "name": "NavigationFlowState", "source": "src/index.ts", + "name": "NavigationFlowState", "type": "or", "or": [ { + "source": "src/index.ts", "name": "NavigationFlowViewState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -180,9 +180,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -214,9 +214,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -247,8 +247,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -281,14 +281,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowViewState", "description": "A state representing a view" }, { + "source": "src/index.ts", "name": "NavigationFlowEndState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -318,9 +320,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -352,9 +354,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -391,14 +393,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowEndState", "description": "An END state of the flow." }, { + "source": "src/index.ts", "name": "NavigationFlowFlowState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -428,9 +432,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -462,9 +466,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -495,8 +499,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -521,9 +525,9 @@ "title": "NavigationFlowFlowState" }, { + "source": "src/index.ts", "name": "NavigationFlowActionState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -553,9 +557,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -587,9 +591,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -622,8 +626,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -641,9 +645,137 @@ "description": "Action states execute an expression to determine the next state to transition to" }, { - "name": "NavigationFlowExternalState", + "source": "src/index.ts", + "name": "NavigationFlowAsyncActionState", "type": "object", + "properties": { + "_comment": { + "required": false, + "node": { + "type": "string", + "title": "CommentBase._comment", + "description": "Add comments that will not be processing, but are useful for code explanation" + } + }, + "state_type": { + "required": true, + "node": { + "type": "string", + "const": "ASYNC_ACTION", + "title": "NavigationBaseState.state_type", + "description": "A property to determine the type of state this is" + } + }, + "onStart": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onStart" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onStart", + "description": "An optional expression to run when this view renders" + } + }, + "onEnd": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onEnd" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onEnd", + "description": "An optional expression to run before view transition" + } + }, + "exp": { + "required": true, + "node": { + "type": "ref", + "ref": "Expression", + "title": "NavigationFlowAsyncActionState.exp", + "description": "An expression to execute.\nThe return value determines the transition to take" + } + }, + "transitions": { + "required": true, + "node": { + "source": "src/index.ts", + "name": "NavigationFlowTransition", + "type": "record", + "keyType": { + "type": "string" + }, + "valueType": { + "type": "string" + }, + "title": "NavigationFlowTransitionableState.transitions", + "description": "A mapping of transition-name to FlowState name" + } + }, + "await": { + "required": true, + "node": { + "type": "boolean", + "title": "NavigationFlowAsyncActionState.await", + "description": "Whether the expression(s) should be awaited before transitioning" + } + } + }, + "additionalProperties": false, + "title": "NavigationFlowAsyncActionState", + "description": "Action states execute an expression to determine the next state to transition to" + }, + { "source": "src/index.ts", + "name": "NavigationFlowExternalState", + "type": "object", "properties": { "_comment": { "required": false, @@ -673,9 +805,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -707,9 +839,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -740,8 +872,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -762,7 +894,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowExternalState", "description": "External Flow states represent states in the FSM that can't be resolved internally in Player.\nThe flow will wait for the embedded application to manage moving to the next state via a transition" } diff --git a/common/static-xlrs/src/core/xlr/NavigationBaseState.json b/common/static-xlrs/src/core/xlr/NavigationBaseState.json index afae752..3ec3565 100644 --- a/common/static-xlrs/src/core/xlr/NavigationBaseState.json +++ b/common/static-xlrs/src/core/xlr/NavigationBaseState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationBaseState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -98,8 +98,17 @@ "ref": "T" }, "right": { - "type": "string", - "const": "ACTION" + "type": "or", + "or": [ + { + "type": "string", + "const": "ACTION" + }, + { + "type": "string", + "const": "ASYNC_ACTION" + } + ] } }, "value": { diff --git a/common/static-xlrs/src/core/xlr/NavigationFlow.json b/common/static-xlrs/src/core/xlr/NavigationFlow.json index c177364..83ec4dd 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlow.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlow.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlow", "type": "object", - "source": "src/index.ts", "properties": { "startState": { "required": true, @@ -22,9 +22,9 @@ "title": "NavigationFlow.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -56,9 +56,9 @@ "title": "NavigationFlow.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -94,9 +94,9 @@ "ref": "Expression" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -113,14 +113,14 @@ "description": "An object with an expression in it" }, { - "name": "NavigationFlowState", "source": "src/index.ts", + "name": "NavigationFlowState", "type": "or", "or": [ { + "source": "src/index.ts", "name": "NavigationFlowViewState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -150,9 +150,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -184,9 +184,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -217,8 +217,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -251,14 +251,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowViewState", "description": "A state representing a view" }, { + "source": "src/index.ts", "name": "NavigationFlowEndState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -288,9 +290,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -322,9 +324,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -361,14 +363,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowEndState", "description": "An END state of the flow." }, { + "source": "src/index.ts", "name": "NavigationFlowFlowState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -398,9 +402,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -432,9 +436,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -465,8 +469,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -491,9 +495,9 @@ "title": "NavigationFlowFlowState" }, { + "source": "src/index.ts", "name": "NavigationFlowActionState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -523,9 +527,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -557,9 +561,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -592,8 +596,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -611,9 +615,137 @@ "description": "Action states execute an expression to determine the next state to transition to" }, { - "name": "NavigationFlowExternalState", + "source": "src/index.ts", + "name": "NavigationFlowAsyncActionState", "type": "object", + "properties": { + "_comment": { + "required": false, + "node": { + "type": "string", + "title": "CommentBase._comment", + "description": "Add comments that will not be processing, but are useful for code explanation" + } + }, + "state_type": { + "required": true, + "node": { + "type": "string", + "const": "ASYNC_ACTION", + "title": "NavigationBaseState.state_type", + "description": "A property to determine the type of state this is" + } + }, + "onStart": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onStart" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onStart", + "description": "An optional expression to run when this view renders" + } + }, + "onEnd": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onEnd" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onEnd", + "description": "An optional expression to run before view transition" + } + }, + "exp": { + "required": true, + "node": { + "type": "ref", + "ref": "Expression", + "title": "NavigationFlowAsyncActionState.exp", + "description": "An expression to execute.\nThe return value determines the transition to take" + } + }, + "transitions": { + "required": true, + "node": { + "source": "src/index.ts", + "name": "NavigationFlowTransition", + "type": "record", + "keyType": { + "type": "string" + }, + "valueType": { + "type": "string" + }, + "title": "NavigationFlowTransitionableState.transitions", + "description": "A mapping of transition-name to FlowState name" + } + }, + "await": { + "required": true, + "node": { + "type": "boolean", + "title": "NavigationFlowAsyncActionState.await", + "description": "Whether the expression(s) should be awaited before transitioning" + } + } + }, + "additionalProperties": false, + "title": "NavigationFlowAsyncActionState", + "description": "Action states execute an expression to determine the next state to transition to" + }, + { "source": "src/index.ts", + "name": "NavigationFlowExternalState", + "type": "object", "properties": { "_comment": { "required": false, @@ -643,9 +775,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -677,9 +809,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -710,8 +842,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -732,7 +864,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowExternalState", "description": "External Flow states represent states in the FSM that can't be resolved internally in Player.\nThe flow will wait for the embedded application to manage moving to the next state via a transition" } diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowActionState.json b/common/static-xlrs/src/core/xlr/NavigationFlowActionState.json index 3b35f38..3d2ea61 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowActionState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowActionState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlowActionState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -100,8 +100,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowAsyncActionState.json b/common/static-xlrs/src/core/xlr/NavigationFlowAsyncActionState.json new file mode 100644 index 0000000..ac18c13 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/NavigationFlowAsyncActionState.json @@ -0,0 +1,128 @@ +{ + "source": "src/index.ts", + "name": "NavigationFlowAsyncActionState", + "type": "object", + "properties": { + "_comment": { + "required": false, + "node": { + "type": "string", + "title": "CommentBase._comment", + "description": "Add comments that will not be processing, but are useful for code explanation" + } + }, + "state_type": { + "required": true, + "node": { + "type": "string", + "const": "ASYNC_ACTION", + "title": "NavigationBaseState.state_type", + "description": "A property to determine the type of state this is" + } + }, + "onStart": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onStart" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onStart", + "description": "An optional expression to run when this view renders" + } + }, + "onEnd": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onEnd" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onEnd", + "description": "An optional expression to run before view transition" + } + }, + "exp": { + "required": true, + "node": { + "type": "ref", + "ref": "Expression", + "title": "NavigationFlowAsyncActionState.exp", + "description": "An expression to execute.\nThe return value determines the transition to take" + } + }, + "transitions": { + "required": true, + "node": { + "source": "src/index.ts", + "name": "NavigationFlowTransition", + "type": "record", + "keyType": { + "type": "string" + }, + "valueType": { + "type": "string" + }, + "title": "NavigationFlowTransitionableState.transitions", + "description": "A mapping of transition-name to FlowState name" + } + }, + "await": { + "required": true, + "node": { + "type": "boolean", + "title": "NavigationFlowAsyncActionState.await", + "description": "Whether the expression(s) should be awaited before transitioning" + } + } + }, + "additionalProperties": false, + "title": "NavigationFlowAsyncActionState", + "description": "Action states execute an expression to determine the next state to transition to" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowEndState.json b/common/static-xlrs/src/core/xlr/NavigationFlowEndState.json index d0883fc..7a834a9 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowEndState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowEndState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlowEndState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -104,7 +104,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowEndState", "description": "An END state of the flow." } \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowExternalState.json b/common/static-xlrs/src/core/xlr/NavigationFlowExternalState.json index 57f503e..2a51f8f 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowExternalState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowExternalState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlowExternalState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -98,8 +98,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -120,7 +120,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowExternalState", "description": "External Flow states represent states in the FSM that can't be resolved internally in Player.\nThe flow will wait for the embedded application to manage moving to the next state via a transition" } \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowFlowState.json b/common/static-xlrs/src/core/xlr/NavigationFlowFlowState.json index dcf6209..9f7abf5 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowFlowState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowFlowState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlowFlowState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -98,8 +98,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowState.json b/common/static-xlrs/src/core/xlr/NavigationFlowState.json index 01070f2..b1fcf29 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowState.json @@ -1,12 +1,12 @@ { - "name": "NavigationFlowState", "source": "src/index.ts", + "name": "NavigationFlowState", "type": "or", "or": [ { + "source": "src/index.ts", "name": "NavigationFlowViewState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -36,9 +36,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -70,9 +70,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -103,8 +103,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -137,14 +137,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowViewState", "description": "A state representing a view" }, { + "source": "src/index.ts", "name": "NavigationFlowEndState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -174,9 +176,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -208,9 +210,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -247,14 +249,16 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowEndState", "description": "An END state of the flow." }, { + "source": "src/index.ts", "name": "NavigationFlowFlowState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -284,9 +288,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -318,9 +322,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -351,8 +355,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -377,9 +381,9 @@ "title": "NavigationFlowFlowState" }, { + "source": "src/index.ts", "name": "NavigationFlowActionState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -409,9 +413,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -443,9 +447,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -478,8 +482,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -497,9 +501,137 @@ "description": "Action states execute an expression to determine the next state to transition to" }, { - "name": "NavigationFlowExternalState", + "source": "src/index.ts", + "name": "NavigationFlowAsyncActionState", "type": "object", + "properties": { + "_comment": { + "required": false, + "node": { + "type": "string", + "title": "CommentBase._comment", + "description": "Add comments that will not be processing, but are useful for code explanation" + } + }, + "state_type": { + "required": true, + "node": { + "type": "string", + "const": "ASYNC_ACTION", + "title": "NavigationBaseState.state_type", + "description": "A property to determine the type of state this is" + } + }, + "onStart": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onStart" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onStart", + "description": "An optional expression to run when this view renders" + } + }, + "onEnd": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "ref", + "ref": "Expression", + "title": "NavigationBaseState.onEnd" + }, + { + "source": "src/index.ts", + "name": "ExpressionObject", + "type": "object", + "properties": { + "exp": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ExpressionObject.exp", + "description": "The expression to run" + } + } + }, + "additionalProperties": false, + "title": "ExpressionObject", + "description": "An object with an expression in it" + } + ], + "title": "NavigationBaseState.onEnd", + "description": "An optional expression to run before view transition" + } + }, + "exp": { + "required": true, + "node": { + "type": "ref", + "ref": "Expression", + "title": "NavigationFlowAsyncActionState.exp", + "description": "An expression to execute.\nThe return value determines the transition to take" + } + }, + "transitions": { + "required": true, + "node": { + "source": "src/index.ts", + "name": "NavigationFlowTransition", + "type": "record", + "keyType": { + "type": "string" + }, + "valueType": { + "type": "string" + }, + "title": "NavigationFlowTransitionableState.transitions", + "description": "A mapping of transition-name to FlowState name" + } + }, + "await": { + "required": true, + "node": { + "type": "boolean", + "title": "NavigationFlowAsyncActionState.await", + "description": "Whether the expression(s) should be awaited before transitioning" + } + } + }, + "additionalProperties": false, + "title": "NavigationFlowAsyncActionState", + "description": "Action states execute an expression to determine the next state to transition to" + }, + { "source": "src/index.ts", + "name": "NavigationFlowExternalState", + "type": "object", "properties": { "_comment": { "required": false, @@ -529,9 +661,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -563,9 +695,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -596,8 +728,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -618,7 +750,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowExternalState", "description": "External Flow states represent states in the FSM that can't be resolved internally in Player.\nThe flow will wait for the embedded application to manage moving to the next state via a transition" } diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowTransition.json b/common/static-xlrs/src/core/xlr/NavigationFlowTransition.json index a93e368..7470a21 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowTransition.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowTransition.json @@ -1,6 +1,6 @@ { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowTransitionableState.json b/common/static-xlrs/src/core/xlr/NavigationFlowTransitionableState.json index 484899a..daeb712 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowTransitionableState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowTransitionableState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlowTransitionableState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -98,8 +98,17 @@ "ref": "T" }, "right": { - "type": "string", - "const": "ACTION" + "type": "or", + "or": [ + { + "type": "string", + "const": "ACTION" + }, + { + "type": "string", + "const": "ASYNC_ACTION" + } + ] } }, "value": { @@ -118,8 +127,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" diff --git a/common/static-xlrs/src/core/xlr/NavigationFlowViewState.json b/common/static-xlrs/src/core/xlr/NavigationFlowViewState.json index cd381b2..9cec0c3 100644 --- a/common/static-xlrs/src/core/xlr/NavigationFlowViewState.json +++ b/common/static-xlrs/src/core/xlr/NavigationFlowViewState.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "NavigationFlowViewState", "type": "object", - "source": "src/index.ts", "properties": { "_comment": { "required": false, @@ -31,9 +31,9 @@ "title": "NavigationBaseState.onStart" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -65,9 +65,9 @@ "title": "NavigationBaseState.onEnd" }, { + "source": "src/index.ts", "name": "ExpressionObject", "type": "object", - "source": "src/index.ts", "properties": { "exp": { "required": false, @@ -98,8 +98,8 @@ "transitions": { "required": true, "node": { - "name": "NavigationFlowTransition", "source": "src/index.ts", + "name": "NavigationFlowTransition", "type": "record", "keyType": { "type": "string" @@ -132,7 +132,9 @@ } } }, - "additionalProperties": false, + "additionalProperties": { + "type": "unknown" + }, "title": "NavigationFlowViewState", "description": "A state representing a view" } \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Schema.ArrayType.json b/common/static-xlrs/src/core/xlr/Schema.ArrayType.json new file mode 100644 index 0000000..f63a7b6 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Schema.ArrayType.json @@ -0,0 +1,203 @@ +{ + "name": "Schema.ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } + }, + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Schema.DataType.json b/common/static-xlrs/src/core/xlr/Schema.DataType.json new file mode 100644 index 0000000..9bce05d --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Schema.DataType.json @@ -0,0 +1,198 @@ +{ + "name": "Schema.DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" + }, + "default": { + "type": "unknown" + } + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Schema.DataTypes.json b/common/static-xlrs/src/core/xlr/Schema.DataTypes.json new file mode 100644 index 0000000..4e778f9 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Schema.DataTypes.json @@ -0,0 +1,611 @@ +{ + "name": "Schema.DataTypes", + "type": "or", + "or": [ + { + "name": "DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" + }, + "default": { + "type": "unknown" + } + } + ] + }, + { + "name": "RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "RecordType", + "description": "Determines if the Datatype is a record object" + }, + { + "name": "ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } + }, + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" + } + ], + "title": "DataTypes" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Schema.Node.json b/common/static-xlrs/src/core/xlr/Schema.Node.json new file mode 100644 index 0000000..3a80aa1 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Schema.Node.json @@ -0,0 +1,618 @@ +{ + "name": "Schema.Node", + "type": "object", + "properties": {}, + "additionalProperties": { + "name": "DataTypes", + "type": "or", + "or": [ + { + "name": "DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" + }, + "default": { + "type": "unknown" + } + } + ] + }, + { + "name": "RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "RecordType", + "description": "Determines if the Datatype is a record object" + }, + { + "name": "ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } + }, + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" + } + ], + "title": "DataTypes" + }, + "title": "Node", + "description": "A Node describes a specific object in the tree" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Schema.RecordType.json b/common/static-xlrs/src/core/xlr/Schema.RecordType.json new file mode 100644 index 0000000..76692f6 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Schema.RecordType.json @@ -0,0 +1,203 @@ +{ + "name": "Schema.RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "RecordType", + "description": "Determines if the Datatype is a record object" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Schema.Schema.json b/common/static-xlrs/src/core/xlr/Schema.Schema.json new file mode 100644 index 0000000..78e060d --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Schema.Schema.json @@ -0,0 +1,1247 @@ +{ + "name": "Schema.Schema", + "type": "object", + "properties": { + "ROOT": { + "required": true, + "node": { + "name": "Node", + "type": "object", + "properties": {}, + "additionalProperties": { + "name": "DataTypes", + "type": "or", + "or": [ + { + "name": "DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" + }, + "default": { + "type": "unknown" + } + } + ] + }, + { + "name": "RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "RecordType", + "description": "Determines if the Datatype is a record object" + }, + { + "name": "ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } + }, + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" + } + ], + "title": "DataTypes" + }, + "title": "Schema.ROOT", + "description": "The ROOT object is the top level object to use" + } + } + }, + "additionalProperties": { + "name": "Node", + "type": "object", + "properties": {}, + "additionalProperties": { + "name": "DataTypes", + "type": "or", + "or": [ + { + "name": "DataType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType", + "description": "Each prop in the object can have a specific DataType", + "genericTokens": [ + { + "symbol": "T", + "constraints": { + "type": "any" + }, + "default": { + "type": "unknown" + } + } + ] + }, + { + "name": "RecordType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isRecord": { + "required": true, + "node": { + "type": "boolean", + "title": "RecordType.isRecord", + "description": "boolean to define if its a record" + } + }, + "isArray": { + "required": false, + "node": { + "type": "never", + "title": "RecordType.isArray", + "description": "This property is mutually exclusive with RecordType and can not be used with ArrayType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "RecordType", + "description": "Determines if the Datatype is a record object" + }, + { + "name": "ArrayType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "DataType.type", + "description": "The reference of the base type to use" + } + }, + "validation": { + "required": false, + "node": { + "type": "array", + "elementType": { + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" + }, + "title": "DataType.validation", + "description": "Any additional validations that are associated with this property\nThese will add to any base validations associated with the \"type\"" + } + }, + "format": { + "required": false, + "node": { + "name": "Formatting.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the formatter (and de-formatter) to use" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "DataType.format", + "description": "A reference to a specific data format to use.\nIf none is specified, will fallback to that of the base type" + } + }, + "default": { + "required": false, + "node": { + "type": "ref", + "ref": "T", + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "isArray": { + "required": true, + "node": { + "type": "boolean", + "title": "ArrayType.isArray", + "description": "boolean to define if its an array" + } + }, + "isRecord": { + "required": false, + "node": { + "type": "never", + "title": "ArrayType.isRecord", + "description": "This property is mutually exclusive with ArrayType and can not be used with RecordType" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "ArrayType", + "description": "Determines if the DataType is an Array Object" + } + ], + "title": "DataTypes" + }, + "title": "Node", + "description": "A Node describes a specific object in the tree" + }, + "title": "Schema", + "description": "The authored schema object in the JSON payload" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/StaticSwitch.json b/common/static-xlrs/src/core/xlr/StaticSwitch.json index 3a8904f..b7cd02f 100644 --- a/common/static-xlrs/src/core/xlr/StaticSwitch.json +++ b/common/static-xlrs/src/core/xlr/StaticSwitch.json @@ -1,18 +1,18 @@ { + "source": "src/index.ts", "name": "StaticSwitch", "type": "object", - "source": "src/index.ts", "properties": { "staticSwitch": { "required": true, "node": { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -35,8 +35,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", diff --git a/common/static-xlrs/src/core/xlr/Switch.json b/common/static-xlrs/src/core/xlr/Switch.json index 467f893..34de887 100644 --- a/common/static-xlrs/src/core/xlr/Switch.json +++ b/common/static-xlrs/src/core/xlr/Switch.json @@ -1,11 +1,11 @@ { - "name": "Switch", "source": "src/index.ts", + "name": "Switch", "type": "array", "elementType": { - "name": "SwitchCase", - "type": "object", "source": "src/index.ts", + "name": "SwitchCase", + "type": "object", "properties": { "asset": { "required": true, @@ -28,8 +28,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", diff --git a/common/static-xlrs/src/core/xlr/SwitchCase.json b/common/static-xlrs/src/core/xlr/SwitchCase.json index 0c144fb..8c7c7f8 100644 --- a/common/static-xlrs/src/core/xlr/SwitchCase.json +++ b/common/static-xlrs/src/core/xlr/SwitchCase.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "SwitchCase", "type": "object", - "source": "src/index.ts", "properties": { "asset": { "required": true, @@ -24,8 +24,7 @@ }, { "type": "boolean", - "const": true, - "title": "SwitchCase.case" + "const": true } ], "title": "SwitchCase.case", diff --git a/common/static-xlrs/src/core/xlr/Templatable.json b/common/static-xlrs/src/core/xlr/Templatable.json index d7cf4bf..7fad7b6 100644 --- a/common/static-xlrs/src/core/xlr/Templatable.json +++ b/common/static-xlrs/src/core/xlr/Templatable.json @@ -1,16 +1,16 @@ { + "source": "src/index.ts", "name": "Templatable", "type": "object", - "source": "src/index.ts", "properties": { "template": { "required": false, "node": { "type": "array", "elementType": { + "source": "src/index.ts", "name": "Template", "type": "object", - "source": "src/index.ts", "properties": { "data": { "required": true, @@ -46,6 +46,24 @@ "title": "Template.output", "description": "A property on the parent object to store the new map under.\nIf it already exists, values are appended to the end." } + }, + "placement": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "prepend" + }, + { + "type": "string", + "const": "append" + } + ], + "title": "Template.placement", + "description": "Specifies the template placement in relation to existing elements" + } } }, "additionalProperties": false, diff --git a/common/static-xlrs/src/core/xlr/Template.json b/common/static-xlrs/src/core/xlr/Template.json index 934b202..ff9952c 100644 --- a/common/static-xlrs/src/core/xlr/Template.json +++ b/common/static-xlrs/src/core/xlr/Template.json @@ -1,7 +1,7 @@ { + "source": "src/index.ts", "name": "Template", "type": "object", - "source": "src/index.ts", "properties": { "data": { "required": true, @@ -37,6 +37,24 @@ "title": "Template.output", "description": "A property on the parent object to store the new map under.\nIf it already exists, values are appended to the end." } + }, + "placement": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "prepend" + }, + { + "type": "string", + "const": "append" + } + ], + "title": "Template.placement", + "description": "Specifies the template placement in relation to existing elements" + } } }, "additionalProperties": false, diff --git a/common/static-xlrs/src/core/xlr/Validation.CrossfieldReference.json b/common/static-xlrs/src/core/xlr/Validation.CrossfieldReference.json new file mode 100644 index 0000000..3718981 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Validation.CrossfieldReference.json @@ -0,0 +1,127 @@ +{ + "name": "Validation.CrossfieldReference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "never", + "title": "CrossfieldReference.dataTarget", + "description": "Cross-field references and validation must run against the default (deformatted) value" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + }, + "ref": { + "required": false, + "node": { + "type": "ref", + "ref": "Binding", + "title": "CrossfieldReference.ref", + "description": "The binding to associate this validation with" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "CrossfieldReference" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Validation.DisplayTarget.json b/common/static-xlrs/src/core/xlr/Validation.DisplayTarget.json new file mode 100644 index 0000000..03cf8aa --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Validation.DisplayTarget.json @@ -0,0 +1,20 @@ +{ + "name": "Validation.DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "DisplayTarget", + "description": "Where the error/warning should be displayed.\n- `field` is the default display target. This renders the error/warning directly underneath the field.\n- `section` is used to display a message at a parent node that is designated as a \"section\"\n- `page` a special section used to display a message at the top of the page." +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Validation.Reference.json b/common/static-xlrs/src/core/xlr/Validation.Reference.json new file mode 100644 index 0000000..5bb834e --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Validation.Reference.json @@ -0,0 +1,129 @@ +{ + "name": "Validation.Reference", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "title": "Reference.type", + "description": "The name of the referenced validation type\nThis will be used to lookup the proper handler" + } + }, + "message": { + "required": false, + "node": { + "type": "string", + "title": "Reference.message", + "description": "An optional means of overriding the default message if the validation is triggered" + } + }, + "severity": { + "required": false, + "node": { + "name": "Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Reference.severity", + "description": "An optional means of overriding the default severity of the validation if triggered" + } + }, + "trigger": { + "required": false, + "node": { + "name": "Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Reference.trigger", + "description": "When to run this particular validation" + } + }, + "dataTarget": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "string", + "const": "formatted" + }, + { + "type": "string", + "const": "deformatted" + } + ], + "title": "Reference.dataTarget", + "description": "Each validation is passed the value of the data to run it's validation against.\nBy default, this is the value stored in the data-model (deformatted).\nIn the off chance you'd like this validator to run against the formatted value (the one the user sees), set this option" + } + }, + "displayTarget": { + "required": false, + "node": { + "name": "DisplayTarget", + "type": "or", + "or": [ + { + "type": "string", + "const": "page" + }, + { + "type": "string", + "const": "section" + }, + { + "type": "string", + "const": "field" + } + ], + "title": "Reference.displayTarget", + "description": "Where the error should be displayed" + } + }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + } + }, + "additionalProperties": { + "type": "unknown" + }, + "title": "Reference", + "description": "A reference to a validation object" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Validation.Severity.json b/common/static-xlrs/src/core/xlr/Validation.Severity.json new file mode 100644 index 0000000..bbdee62 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Validation.Severity.json @@ -0,0 +1,16 @@ +{ + "name": "Validation.Severity", + "type": "or", + "or": [ + { + "type": "string", + "const": "error" + }, + { + "type": "string", + "const": "warning" + } + ], + "title": "Severity", + "description": "How serious are you about this error?\nWarning validations are reserved for errors that could be ignored by the user without consequence\nErrors must be fixed before proceeding" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/Validation.Trigger.json b/common/static-xlrs/src/core/xlr/Validation.Trigger.json new file mode 100644 index 0000000..40f15f9 --- /dev/null +++ b/common/static-xlrs/src/core/xlr/Validation.Trigger.json @@ -0,0 +1,20 @@ +{ + "name": "Validation.Trigger", + "type": "or", + "or": [ + { + "type": "string", + "const": "navigation" + }, + { + "type": "string", + "const": "change" + }, + { + "type": "string", + "const": "load" + } + ], + "title": "Trigger", + "description": "When to _first_ start caring about a validation of a data-val.\n\nload - only check once the first time the binding appears on screen\nchange - check anytime the data changes\nnavigation - check once the user attempts to navigate away from a view" +} \ No newline at end of file diff --git a/common/static-xlrs/src/core/xlr/View.json b/common/static-xlrs/src/core/xlr/View.json index 5267003..5d88c9d 100644 --- a/common/static-xlrs/src/core/xlr/View.json +++ b/common/static-xlrs/src/core/xlr/View.json @@ -1,6 +1,6 @@ { - "name": "View", "source": "src/index.ts", + "name": "View", "type": "conditional", "check": { "left": { @@ -28,7 +28,7 @@ "node": { "type": "array", "elementType": { - "name": "CrossfieldReference", + "name": "Validation.CrossfieldReference", "type": "object", "properties": { "type": { @@ -55,13 +55,11 @@ "or": [ { "type": "string", - "const": "error", - "title": "Severity" + "const": "error" }, { "type": "string", - "const": "warning", - "title": "Severity" + "const": "warning" } ], "title": "Reference.severity", @@ -76,18 +74,15 @@ "or": [ { "type": "string", - "const": "navigation", - "title": "Trigger" + "const": "navigation" }, { "type": "string", - "const": "change", - "title": "Trigger" + "const": "change" }, { "type": "string", - "const": "load", - "title": "Trigger" + "const": "load" } ], "title": "Reference.trigger", @@ -110,24 +105,40 @@ "or": [ { "type": "string", - "const": "page", - "title": "DisplayTarget" + "const": "page" }, { "type": "string", - "const": "section", - "title": "DisplayTarget" + "const": "section" }, { "type": "string", - "const": "field", - "title": "DisplayTarget" + "const": "field" } ], "title": "Reference.displayTarget", "description": "Where the error should be displayed" } }, + "blocking": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "boolean", + "title": "Reference.blocking" + }, + { + "type": "string", + "const": "once" + } + ], + "title": "Reference.blocking", + "description": "If the validation blocks navigation\ntrue/false - always/never block navigation\nonce - only block navigation if the validation has not been triggered before", + "default": "- true for errors, 'once' for warnings" + } + }, "ref": { "required": false, "node": { diff --git a/common/static-xlrs/src/core/xlr/manifest.js b/common/static-xlrs/src/core/xlr/manifest.js index 0a18eb1..7f0fbeb 100644 --- a/common/static-xlrs/src/core/xlr/manifest.js +++ b/common/static-xlrs/src/core/xlr/manifest.js @@ -1,78 +1,55 @@ -const Asset = require("./Asset.json"); -const AssetBinding = require("./AssetBinding.json"); -const SwitchCase = require("./SwitchCase.json"); -const Switch = require("./Switch.json"); -const AssetWrapper = require("./AssetWrapper.json"); -const AssetWrapperOrSwitch = require("./AssetWrapperOrSwitch.json"); -const AssetSwitch = require("./AssetSwitch.json"); -const StaticSwitch = require("./StaticSwitch.json"); -const DynamicSwitch = require("./DynamicSwitch.json"); -const Expression = require("./Expression.json"); -const ExpressionRef = require("./ExpressionRef.json"); -const Binding = require("./Binding.json"); -const BindingRef = require("./BindingRef.json"); -const DataModel = require("./DataModel.json"); -const Navigation = require("./Navigation.json"); -const ExpressionObject = require("./ExpressionObject.json"); -const NavigationFlow = require("./NavigationFlow.json"); -const NavigationFlowTransition = require("./NavigationFlowTransition.json"); -const NavigationBaseState = require("./NavigationBaseState.json"); -const NavigationFlowTransitionableState = require("./NavigationFlowTransitionableState.json"); -const NavigationFlowViewState = require("./NavigationFlowViewState.json"); -const NavigationFlowEndState = require("./NavigationFlowEndState.json"); -const NavigationFlowActionState = require("./NavigationFlowActionState.json"); -const NavigationFlowExternalState = require("./NavigationFlowExternalState.json"); -const NavigationFlowFlowState = require("./NavigationFlowFlowState.json"); -const NavigationFlowState = require("./NavigationFlowState.json"); -const FlowResult = require("./FlowResult.json"); -const Templatable = require("./Templatable.json"); -const Template = require("./Template.json"); -const View = require("./View.json"); -const Flow = require("./Flow.json"); +const Asset = require("./Asset.json") +const AssetBinding = require("./AssetBinding.json") +const SwitchCase = require("./SwitchCase.json") +const Switch = require("./Switch.json") +const AssetWrapper = require("./AssetWrapper.json") +const AssetWrapperOrSwitch = require("./AssetWrapperOrSwitch.json") +const AssetSwitch = require("./AssetSwitch.json") +const StaticSwitch = require("./StaticSwitch.json") +const DynamicSwitch = require("./DynamicSwitch.json") +const Expression = require("./Expression.json") +const ExpressionRef = require("./ExpressionRef.json") +const Binding = require("./Binding.json") +const BindingRef = require("./BindingRef.json") +const DataModel = require("./DataModel.json") +const Navigation = require("./Navigation.json") +const ExpressionObject = require("./ExpressionObject.json") +const NavigationFlow = require("./NavigationFlow.json") +const NavigationFlowTransition = require("./NavigationFlowTransition.json") +const NavigationBaseState = require("./NavigationBaseState.json") +const NavigationFlowTransitionableState = require("./NavigationFlowTransitionableState.json") +const NavigationFlowViewState = require("./NavigationFlowViewState.json") +const NavigationFlowEndState = require("./NavigationFlowEndState.json") +const NavigationFlowActionState = require("./NavigationFlowActionState.json") +const NavigationFlowAsyncActionState = require("./NavigationFlowAsyncActionState.json") +const NavigationFlowExternalState = require("./NavigationFlowExternalState.json") +const NavigationFlowFlowState = require("./NavigationFlowFlowState.json") +const NavigationFlowState = require("./NavigationFlowState.json") +const FlowResult = require("./FlowResult.json") +const Templatable = require("./Templatable.json") +const Template = require("./Template.json") +const View = require("./View.json") +const Flow = require("./Flow.json") +const Schema_Schema = require("./Schema.Schema.json") +const Schema_Node = require("./Schema.Node.json") +const Schema_DataTypes = require("./Schema.DataTypes.json") +const Schema_DataType = require("./Schema.DataType.json") +const Schema_RecordType = require("./Schema.RecordType.json") +const Schema_ArrayType = require("./Schema.ArrayType.json") +const Language_DataTypeRef = require("./Language.DataTypeRef.json") +const Formatting_Reference = require("./Formatting.Reference.json") +const Validation_Severity = require("./Validation.Severity.json") +const Validation_Trigger = require("./Validation.Trigger.json") +const Validation_DisplayTarget = require("./Validation.DisplayTarget.json") +const Validation_Reference = require("./Validation.Reference.json") +const Validation_CrossfieldReference = require("./Validation.CrossfieldReference.json") -module.exports = { - pluginName: "Types", - capabilities: { - Types: [ - Asset, - AssetBinding, - SwitchCase, - Switch, - AssetWrapper, - AssetWrapperOrSwitch, - AssetSwitch, - StaticSwitch, - DynamicSwitch, - Expression, - ExpressionRef, - Binding, - BindingRef, - DataModel, - Navigation, - ExpressionObject, - NavigationFlow, - NavigationFlowTransition, - NavigationBaseState, - NavigationFlowTransitionableState, - NavigationFlowViewState, - NavigationFlowEndState, - NavigationFlowActionState, - NavigationFlowExternalState, - NavigationFlowFlowState, - NavigationFlowState, - FlowResult, - Templatable, - Template, - View, - Flow, - ], - }, - customPrimitives: [ - "Expression", - "Asset", - "Binding", - "AssetWrapper", - "Schema.DataType", - "ExpressionHandler", - ], -}; + module.exports = { + "pluginName": "Types", + "capabilities": { + "Types":[Asset,AssetBinding,SwitchCase,Switch,AssetWrapper,AssetWrapperOrSwitch,AssetSwitch,StaticSwitch,DynamicSwitch,Expression,ExpressionRef,Binding,BindingRef,DataModel,Navigation,ExpressionObject,NavigationFlow,NavigationFlowTransition,NavigationBaseState,NavigationFlowTransitionableState,NavigationFlowViewState,NavigationFlowEndState,NavigationFlowActionState,NavigationFlowAsyncActionState,NavigationFlowExternalState,NavigationFlowFlowState,NavigationFlowState,FlowResult,Templatable,Template,View,Flow,Schema_Schema,Schema_Node,Schema_DataTypes,Schema_DataType,Schema_RecordType,Schema_ArrayType,Language_DataTypeRef,Formatting_Reference,Validation_Severity,Validation_Trigger,Validation_DisplayTarget,Validation_Reference,Validation_CrossfieldReference], + }, + "customPrimitives": [ + "Expression","Asset","Binding","AssetWrapper","Schema.DataType","ExpressionHandler","FormatType","ValidatorFunction" + ] + } diff --git a/common/static-xlrs/src/core/xlr/manifest.json b/common/static-xlrs/src/core/xlr/manifest.json index f3534f4..4612215 100644 --- a/common/static-xlrs/src/core/xlr/manifest.json +++ b/common/static-xlrs/src/core/xlr/manifest.json @@ -25,6 +25,7 @@ "NavigationFlowViewState", "NavigationFlowEndState", "NavigationFlowActionState", + "NavigationFlowAsyncActionState", "NavigationFlowExternalState", "NavigationFlowFlowState", "NavigationFlowState", @@ -32,7 +33,30 @@ "Templatable", "Template", "View", - "Flow" + "Flow", + "Schema.Schema", + "Schema.Node", + "Schema.DataTypes", + "Schema.DataType", + "Schema.RecordType", + "Schema.ArrayType", + "Language.DataTypeRef", + "Formatting.Reference", + "Validation.Severity", + "Validation.Trigger", + "Validation.DisplayTarget", + "Validation.Reference", + "Validation.CrossfieldReference" ] - } + }, + "customPrimitives": [ + "Expression", + "Asset", + "Binding", + "AssetWrapper", + "Schema.DataType", + "ExpressionHandler", + "FormatType", + "ValidatorFunction" + ] } \ No newline at end of file diff --git a/common/static-xlrs/src/expression/xlr/ceil.json b/common/static-xlrs/src/expression/xlr/ceil.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/concat.json b/common/static-xlrs/src/expression/xlr/concat.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/containsAny.json b/common/static-xlrs/src/expression/xlr/containsAny.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/findProperty.json b/common/static-xlrs/src/expression/xlr/findProperty.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/findPropertyIndex.json b/common/static-xlrs/src/expression/xlr/findPropertyIndex.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/floor.json b/common/static-xlrs/src/expression/xlr/floor.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/isEmpty.json b/common/static-xlrs/src/expression/xlr/isEmpty.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/isNotEmpty.json b/common/static-xlrs/src/expression/xlr/isNotEmpty.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/length.json b/common/static-xlrs/src/expression/xlr/length.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/expression/xlr/lowerCase.json b/common/static-xlrs/src/expression/xlr/lowerCase.json old mode 100755 new mode 100644 diff --git a/common/static-xlrs/src/index.d.ts b/common/static-xlrs/src/index.d.ts index 2232e8a..f549fb3 100644 --- a/common/static-xlrs/src/index.d.ts +++ b/common/static-xlrs/src/index.d.ts @@ -1,7 +1,9 @@ import type { Types } from "./core/xlr/manifest"; import type { CommonExpressions } from "./expression/xlr/manifest"; +import type { CommonTypes } from "./types/xlr/manifest"; import type { ReferenceAssetsWebPluginManifest } from "./plugin/xlr/manifest"; export const Types: Types; export const CommonExpressions: CommonExpressions; +export const CommonTypes: CommonTypes; export const ReferenceAssetsWebPluginManifest: ReferenceAssetsWebPluginManifest; diff --git a/common/static-xlrs/src/index.js b/common/static-xlrs/src/index.js index 530e449..799d782 100644 --- a/common/static-xlrs/src/index.js +++ b/common/static-xlrs/src/index.js @@ -1,9 +1,11 @@ const Types = require("./core/xlr/manifest"); const CommonExpressions = require("./expression/xlr/manifest"); +const CommonTypes = require("./types/xlr/manifest"); const ReferenceAssetsWebPluginManifest = require("./plugin/xlr/manifest"); module.exports = { Types, CommonExpressions, + CommonTypes, ReferenceAssetsWebPluginManifest, }; diff --git a/common/static-xlrs/src/types/xlr/DataTypes.BooleanType.json b/common/static-xlrs/src/types/xlr/DataTypes.BooleanType.json new file mode 100644 index 0000000..856618e --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.BooleanType.json @@ -0,0 +1,72 @@ +{ + "source": "/some/path/types.ts", + "name": "BooleanType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "BooleanType" + } + }, + "default": { + "required": true, + "node": { + "type": "boolean", + "const": false + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "oneOf" + } + }, + "message": { + "required": true, + "node": { + "type": "string", + "const": "Value must be true or false" + } + }, + "options": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "boolean", + "const": true + }, + { + "type": "boolean", + "const": false + } + ] + } + } + }, + "additionalProperties": false + } + ] + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.CollectionType.json b/common/static-xlrs/src/types/xlr/DataTypes.CollectionType.json new file mode 100644 index 0000000..c37bd78 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.CollectionType.json @@ -0,0 +1,55 @@ +{ + "source": "/some/path/types.ts", + "name": "CollectionType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "CollectionType" + } + }, + "default": { + "required": false, + "node": { + "type": "or", + "or": [ + { + "type": "number" + }, + { + "type": "string" + } + ], + "title": "DataType.default", + "description": "A default value for this property.\nAny reads for this property will result in this default value being written to the model." + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "collection" + } + } + }, + "additionalProperties": false + } + ] + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.DateType.json b/common/static-xlrs/src/types/xlr/DataTypes.DateType.json new file mode 100644 index 0000000..4d3039a --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.DateType.json @@ -0,0 +1,55 @@ +{ + "source": "/some/path/types.ts", + "name": "DateType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "DateType" + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "string" + } + } + }, + "additionalProperties": false + } + ] + } + }, + "format": { + "required": true, + "node": { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "date" + } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.IntegerNNType.json b/common/static-xlrs/src/types/xlr/DataTypes.IntegerNNType.json new file mode 100644 index 0000000..64285b6 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.IntegerNNType.json @@ -0,0 +1,75 @@ +{ + "source": "/some/path/types.ts", + "name": "IntegerNNType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "IntegerNNType" + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "integer" + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "min" + } + }, + "value": { + "required": true, + "node": { + "type": "number", + "const": 0 + } + } + }, + "additionalProperties": false + } + ] + } + }, + "format": { + "required": true, + "node": { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "integer" + } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.IntegerPosType.json b/common/static-xlrs/src/types/xlr/DataTypes.IntegerPosType.json new file mode 100644 index 0000000..79ec868 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.IntegerPosType.json @@ -0,0 +1,75 @@ +{ + "source": "/some/path/types.ts", + "name": "IntegerPosType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "IntegerPosType" + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "integer" + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "min" + } + }, + "value": { + "required": true, + "node": { + "type": "number", + "const": 1 + } + } + }, + "additionalProperties": false + } + ] + } + }, + "format": { + "required": true, + "node": { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "integer" + } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.IntegerType.json b/common/static-xlrs/src/types/xlr/DataTypes.IntegerType.json new file mode 100644 index 0000000..32d846b --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.IntegerType.json @@ -0,0 +1,55 @@ +{ + "source": "/some/path/types.ts", + "name": "IntegerType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "IntegerType" + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "integer" + } + } + }, + "additionalProperties": false + } + ] + } + }, + "format": { + "required": true, + "node": { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "integer" + } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.PhoneType.json b/common/static-xlrs/src/types/xlr/DataTypes.PhoneType.json new file mode 100644 index 0000000..8668818 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.PhoneType.json @@ -0,0 +1,55 @@ +{ + "source": "/some/path/types.ts", + "name": "PhoneType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "PhoneType" + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "phone" + } + } + }, + "additionalProperties": false + } + ] + } + }, + "format": { + "required": true, + "node": { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "phone" + } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/DataTypes.StringType.json b/common/static-xlrs/src/types/xlr/DataTypes.StringType.json new file mode 100644 index 0000000..2b0e3e5 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/DataTypes.StringType.json @@ -0,0 +1,62 @@ +{ + "source": "/some/path/types.ts", + "name": "StringType", + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "StringType" + } + }, + "default": { + "required": true, + "node": { + "type": "string", + "const": "" + } + }, + "validation": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "any" + }, + "const": [ + { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "string" + } + } + }, + "additionalProperties": false + } + ] + } + }, + "format": { + "required": true, + "node": { + "type": "object", + "properties": { + "type": { + "required": true, + "node": { + "type": "string", + "const": "string" + } + } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Formatters.commaNumber.json b/common/static-xlrs/src/types/xlr/Formatters.commaNumber.json new file mode 100644 index 0000000..07b3e71 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Formatters.commaNumber.json @@ -0,0 +1,28 @@ +{ + "source": "/some/path/types.ts", + "name": "commaNumber", + "type": "ref", + "ref": "FormatType<\n number,\n string,\n {\n /** The number of decimal places to show */\n precision?: number;\n }\n>", + "genericArguments": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "object", + "properties": { + "precision": { + "required": false, + "node": { + "type": "number", + "title": "precision", + "description": "The number of decimal places to show" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Formatters.currency.json b/common/static-xlrs/src/types/xlr/Formatters.currency.json new file mode 100644 index 0000000..1750945 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Formatters.currency.json @@ -0,0 +1,44 @@ +{ + "source": "/some/path/types.ts", + "name": "currency", + "type": "ref", + "ref": "FormatType<\n number,\n string,\n {\n /** The symbol to use for currency */\n currencySymbol?: string;\n\n /** Use parenthesis instead of a - sign for negative values */\n useParensForNeg?: boolean;\n\n /** The number of decimal places to show */\n precision?: number;\n }\n>", + "genericArguments": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "object", + "properties": { + "currencySymbol": { + "required": false, + "node": { + "type": "string", + "title": "currencySymbol", + "description": "The symbol to use for currency" + } + }, + "useParensForNeg": { + "required": false, + "node": { + "type": "boolean", + "title": "useParensForNeg", + "description": "Use parenthesis instead of a - sign for negative values" + } + }, + "precision": { + "required": false, + "node": { + "type": "number", + "title": "precision", + "description": "The number of decimal places to show" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Formatters.date.json b/common/static-xlrs/src/types/xlr/Formatters.date.json new file mode 100644 index 0000000..44e12ac --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Formatters.date.json @@ -0,0 +1,28 @@ +{ + "source": "/some/path/types.ts", + "name": "date", + "type": "ref", + "ref": "FormatType<\n string,\n string,\n {\n /** The mask to use to format the date */\n mask?: string;\n }\n>", + "genericArguments": [ + { + "type": "string" + }, + { + "type": "string" + }, + { + "type": "object", + "properties": { + "mask": { + "required": false, + "node": { + "type": "string", + "title": "mask", + "description": "The mask to use to format the date" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Formatters.integer.json b/common/static-xlrs/src/types/xlr/Formatters.integer.json new file mode 100644 index 0000000..e33df67 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Formatters.integer.json @@ -0,0 +1,14 @@ +{ + "source": "/some/path/types.ts", + "name": "integer", + "type": "ref", + "ref": "FormatType", + "genericArguments": [ + { + "type": "number" + }, + { + "type": "string" + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Formatters.phone.json b/common/static-xlrs/src/types/xlr/Formatters.phone.json new file mode 100644 index 0000000..c3d706d --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Formatters.phone.json @@ -0,0 +1,11 @@ +{ + "source": "/some/path/types.ts", + "name": "phone", + "type": "ref", + "ref": "FormatType", + "genericArguments": [ + { + "type": "string" + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.collection.json b/common/static-xlrs/src/types/xlr/Validators.collection.json new file mode 100644 index 0000000..0e14ec6 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.collection.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "collection", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.email.json b/common/static-xlrs/src/types/xlr/Validators.email.json new file mode 100644 index 0000000..53bf552 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.email.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "email", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.expression.json b/common/static-xlrs/src/types/xlr/Validators.expression.json new file mode 100644 index 0000000..ec281dc --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.expression.json @@ -0,0 +1,23 @@ +{ + "source": "/some/path/types.ts", + "name": "expression", + "type": "ref", + "ref": "ValidatorFunction<{\n /**\n * The expression to evaluate.\n * Falsy values indicate an invalid response\n */\n exp: Expression;\n}>", + "genericArguments": [ + { + "type": "object", + "properties": { + "exp": { + "required": true, + "node": { + "type": "ref", + "ref": "Expression", + "title": "exp", + "description": "The expression to evaluate.\nFalsy values indicate an invalid response" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.integer.json b/common/static-xlrs/src/types/xlr/Validators.integer.json new file mode 100644 index 0000000..8f3e7ac --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.integer.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "integer", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.length.json b/common/static-xlrs/src/types/xlr/Validators.length.json new file mode 100644 index 0000000..0a85e83 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.length.json @@ -0,0 +1,49 @@ +{ + "source": "/some/path/types.ts", + "name": "length", + "type": "ref", + "ref": "ValidatorFunction<\n | {\n /** The minimum length to check against */\n min?: number;\n\n /** The maximum length to check against */\n max?: number;\n }\n | {\n /** The exact length to match against */\n exact: number;\n }\n>", + "genericArguments": [ + { + "type": "or", + "or": [ + { + "type": "object", + "properties": { + "min": { + "required": false, + "node": { + "type": "number", + "title": "min", + "description": "The minimum length to check against" + } + }, + "max": { + "required": false, + "node": { + "type": "number", + "title": "max", + "description": "The maximum length to check against" + } + } + }, + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "exact": { + "required": true, + "node": { + "type": "number", + "title": "exact", + "description": "The exact length to match against" + } + } + }, + "additionalProperties": false + } + ] + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.max.json b/common/static-xlrs/src/types/xlr/Validators.max.json new file mode 100644 index 0000000..6a7327d --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.max.json @@ -0,0 +1,22 @@ +{ + "source": "/some/path/types.ts", + "name": "max", + "type": "ref", + "ref": "ValidatorFunction<{\n /** The minimum value */\n value: number;\n}>", + "genericArguments": [ + { + "type": "object", + "properties": { + "value": { + "required": true, + "node": { + "type": "number", + "title": "value", + "description": "The minimum value" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.min.json b/common/static-xlrs/src/types/xlr/Validators.min.json new file mode 100644 index 0000000..a2743b8 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.min.json @@ -0,0 +1,22 @@ +{ + "source": "/some/path/types.ts", + "name": "min", + "type": "ref", + "ref": "ValidatorFunction<{\n /** The minimum value */\n value: number;\n}>", + "genericArguments": [ + { + "type": "object", + "properties": { + "value": { + "required": true, + "node": { + "type": "number", + "title": "value", + "description": "The minimum value" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.oneOf.json b/common/static-xlrs/src/types/xlr/Validators.oneOf.json new file mode 100644 index 0000000..57fbd9f --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.oneOf.json @@ -0,0 +1,25 @@ +{ + "source": "/some/path/types.ts", + "name": "oneOf", + "type": "ref", + "ref": "ValidatorFunction<{\n /** The enum values that are acceptable */\n options: Array;\n}>", + "genericArguments": [ + { + "type": "object", + "properties": { + "options": { + "required": true, + "node": { + "type": "array", + "elementType": { + "type": "unknown" + }, + "title": "options", + "description": "The enum values that are acceptable" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.phone.json b/common/static-xlrs/src/types/xlr/Validators.phone.json new file mode 100644 index 0000000..30bee99 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.phone.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "phone", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.readonly.json b/common/static-xlrs/src/types/xlr/Validators.readonly.json new file mode 100644 index 0000000..dc2981f --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.readonly.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "readonly", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.regex.json b/common/static-xlrs/src/types/xlr/Validators.regex.json new file mode 100644 index 0000000..e75748b --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.regex.json @@ -0,0 +1,22 @@ +{ + "source": "/some/path/types.ts", + "name": "regex", + "type": "ref", + "ref": "ValidatorFunction<{\n /**\n * The regular expression to test: /pattern/\n * Can optionally include flags after the pattern: /pattern/flags\n */\n regex: string;\n}>", + "genericArguments": [ + { + "type": "object", + "properties": { + "regex": { + "required": true, + "node": { + "type": "string", + "title": "regex", + "description": "The regular expression to test: /pattern/\nCan optionally include flags after the pattern: /pattern/flags" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.required.json b/common/static-xlrs/src/types/xlr/Validators.required.json new file mode 100644 index 0000000..13ec55e --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.required.json @@ -0,0 +1,32 @@ +{ + "source": "/some/path/types.ts", + "name": "required", + "type": "ref", + "ref": "ValidatorFunction<{\n /** An optional expression to limit the required check only if true */\n if?: Expression;\n\n /** An optional expression to limit the required check only if false */\n ifNot?: Expression;\n}>", + "genericArguments": [ + { + "type": "object", + "properties": { + "if": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "if", + "description": "An optional expression to limit the required check only if true" + } + }, + "ifNot": { + "required": false, + "node": { + "type": "ref", + "ref": "Expression", + "title": "ifNot", + "description": "An optional expression to limit the required check only if false" + } + } + }, + "additionalProperties": false + } + ] +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.string.json b/common/static-xlrs/src/types/xlr/Validators.string.json new file mode 100644 index 0000000..e1bb6d1 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.string.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "string", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/Validators.zip.json b/common/static-xlrs/src/types/xlr/Validators.zip.json new file mode 100644 index 0000000..9519135 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/Validators.zip.json @@ -0,0 +1,6 @@ +{ + "source": "/some/path/types.ts", + "name": "zip", + "type": "ref", + "ref": "ValidatorFunction" +} \ No newline at end of file diff --git a/common/static-xlrs/src/types/xlr/manifest.d.ts b/common/static-xlrs/src/types/xlr/manifest.d.ts new file mode 100644 index 0000000..b055bf0 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/manifest.d.ts @@ -0,0 +1,3 @@ +import type { TSManifest } from "@player-tools/xlr"; + +export type CommonTypes = TSManifest; diff --git a/common/static-xlrs/src/types/xlr/manifest.js b/common/static-xlrs/src/types/xlr/manifest.js new file mode 100644 index 0000000..26bdcb7 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/manifest.js @@ -0,0 +1,42 @@ +const DataTypes_BooleanType = require("./DataTypes.BooleanType.json") +const DataTypes_IntegerType = require("./DataTypes.IntegerType.json") +const DataTypes_IntegerPosType = require("./DataTypes.IntegerPosType.json") +const DataTypes_IntegerNNType = require("./DataTypes.IntegerNNType.json") +const DataTypes_StringType = require("./DataTypes.StringType.json") +const DataTypes_CollectionType = require("./DataTypes.CollectionType.json") +const DataTypes_DateType = require("./DataTypes.DateType.json") +const DataTypes_PhoneType = require("./DataTypes.PhoneType.json") +const Formatters_commaNumber = require("./Formatters.commaNumber.json") +const Formatters_currency = require("./Formatters.currency.json") +const Formatters_date = require("./Formatters.date.json") +const Formatters_integer = require("./Formatters.integer.json") +const Formatters_phone = require("./Formatters.phone.json") +const Validators_collection = require("./Validators.collection.json") +const Validators_email = require("./Validators.email.json") +const Validators_expression = require("./Validators.expression.json") +const Validators_integer = require("./Validators.integer.json") +const Validators_length = require("./Validators.length.json") +const Validators_max = require("./Validators.max.json") +const Validators_min = require("./Validators.min.json") +const Validators_oneOf = require("./Validators.oneOf.json") +const Validators_phone = require("./Validators.phone.json") +const Validators_readonly = require("./Validators.readonly.json") +const Validators_regex = require("./Validators.regex.json") +const Validators_required = require("./Validators.required.json") +const Validators_string = require("./Validators.string.json") +const Validators_zip = require("./Validators.zip.json") + + module.exports = { + "pluginName": "CommonTypes", + "capabilities": { + "Assets":[], + "Views":[], + "Expressions":[], + "DataTypes":[DataTypes_BooleanType,DataTypes_IntegerType,DataTypes_IntegerPosType,DataTypes_IntegerNNType,DataTypes_StringType,DataTypes_CollectionType,DataTypes_DateType,DataTypes_PhoneType], + "Formatters":[Formatters_commaNumber,Formatters_currency,Formatters_date,Formatters_integer,Formatters_phone], + "Validators":[Validators_collection,Validators_email,Validators_expression,Validators_integer,Validators_length,Validators_max,Validators_min,Validators_oneOf,Validators_phone,Validators_readonly,Validators_regex,Validators_required,Validators_string,Validators_zip], + }, + "customPrimitives": [ + "Expression","Asset","Binding","AssetWrapper","Schema.DataType","ExpressionHandler","FormatType","ValidatorFunction" + ] + } diff --git a/common/static-xlrs/src/types/xlr/manifest.json b/common/static-xlrs/src/types/xlr/manifest.json new file mode 100644 index 0000000..5172d20 --- /dev/null +++ b/common/static-xlrs/src/types/xlr/manifest.json @@ -0,0 +1,51 @@ +{ + "pluginName": "CommonTypes", + "capabilities": { + "Assets": [], + "Views": [], + "Expressions": [], + "DataTypes": [ + "DataTypes.BooleanType", + "DataTypes.IntegerType", + "DataTypes.IntegerPosType", + "DataTypes.IntegerNNType", + "DataTypes.StringType", + "DataTypes.CollectionType", + "DataTypes.DateType", + "DataTypes.PhoneType" + ], + "Formatters": [ + "Formatters.commaNumber", + "Formatters.currency", + "Formatters.date", + "Formatters.integer", + "Formatters.phone" + ], + "Validators": [ + "Validators.collection", + "Validators.email", + "Validators.expression", + "Validators.integer", + "Validators.length", + "Validators.max", + "Validators.min", + "Validators.oneOf", + "Validators.phone", + "Validators.readonly", + "Validators.regex", + "Validators.required", + "Validators.string", + "Validators.zip" + ] + }, + "customPrimitives": [ + "Expression", + "Asset", + "Binding", + "AssetWrapper", + "Schema.DataType", + "ExpressionHandler", + "FormatType", + "ValidatorFunction" + ] +} \ No newline at end of file diff --git a/lsp/json-language-service/src/__tests__/__snapshots__/service.test.ts.snap b/lsp/json-language-service/src/__tests__/__snapshots__/service.test.ts.snap index 3a334d3..1ef67fa 100644 --- a/lsp/json-language-service/src/__tests__/__snapshots__/service.test.ts.snap +++ b/lsp/json-language-service/src/__tests__/__snapshots__/service.test.ts.snap @@ -58,6 +58,10 @@ exports[`player language service > completion > basic value completions 1`] = ` "kind": 12, "label": "ACTION", }, + { + "kind": 12, + "label": "ASYNC_ACTION", + }, { "kind": 12, "label": "EXTERNAL", @@ -111,20 +115,6 @@ exports[`player language service > hover > basic hover docs 3`] = ` exports[`player language service > validation > throws AssetWrapper errors 1`] = ` [ - { - "message": "Content Validation Error - type: Expected type "string" but got "null"", - "range": { - "end": { - "character": 28, - "line": 20, - }, - "start": { - "character": 16, - "line": 20, - }, - }, - "severity": 1, - }, { "message": "Content Validation Error - missing: Property "BEGIN" missing from type "Navigation"", "range": { @@ -182,7 +172,7 @@ exports[`player language service > validation > throws AssetWrapper errors 1`] = "severity": 1, }, { - "message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", + "message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", "range": { "end": { "character": 16, diff --git a/lsp/json-language-service/src/__tests__/service.test.ts b/lsp/json-language-service/src/__tests__/service.test.ts index 9a21ea2..e12dda9 100644 --- a/lsp/json-language-service/src/__tests__/service.test.ts +++ b/lsp/json-language-service/src/__tests__/service.test.ts @@ -71,34 +71,7 @@ describe("player language service", () => { "data": {}, "navigation": {}, "schema": { - "ROOT": { - "application": { - "type": null - }, - "foo": { - "type": "fooType" - } - }, - "fooType": { - "bar": { - "type": "barType", - "validation": [ - { - "type": "required", - "severity": "error" - } - ] - }, - "baz": { - "type": "bazType", - "validation": [ - { - "type": "required", - "message": "this is my own message" - } - ] - } - } + "ROOT": {} } } `, diff --git a/lsp/json-language-service/src/constants.ts b/lsp/json-language-service/src/constants.ts index 9580ff0..6e472a7 100644 --- a/lsp/json-language-service/src/constants.ts +++ b/lsp/json-language-service/src/constants.ts @@ -9,6 +9,7 @@ import { DuplicateIDPlugin } from "./plugins/duplicate-id-plugin"; import { MissingAssetWrapperPlugin } from "./plugins/missing-asset-wrapper-plugin"; import { NavStatePlugin } from "./plugins/nav-state-plugin"; import { ViewNodePlugin } from "./plugins/view-node-plugin"; +import { SchemaValidationPlugin } from "./plugins/schema-validation-plugin"; import { applyAssetWrapperOrSwitch, applyCommonProps, @@ -20,6 +21,7 @@ export const PLUGINS: Array = [ new DuplicateIDPlugin(), new ViewNodePlugin(), new SchemaInfoPlugin(), + new SchemaValidationPlugin(), new AssetWrapperArrayPlugin(), new NavStatePlugin(), new MissingAssetWrapperPlugin(), diff --git a/lsp/json-language-service/src/plugins/__tests__/asset-wrapper-array-plugin.test.ts b/lsp/json-language-service/src/plugins/__tests__/asset-wrapper-array-plugin.test.ts index afef828..d7616fc 100644 --- a/lsp/json-language-service/src/plugins/__tests__/asset-wrapper-array-plugin.test.ts +++ b/lsp/json-language-service/src/plugins/__tests__/asset-wrapper-array-plugin.test.ts @@ -57,7 +57,7 @@ describe("asset-wrapper-array-plugin", () => { expect(diags?.map((d) => d.message)).toMatchInlineSnapshot(` [ "View Validation Error - value: Does not match any of the expected types for type: 'AssetWrapperOrSwitch'", - "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", + "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", "Implicit Array -> "collection" assets is not supported.", ] `); @@ -79,7 +79,7 @@ describe("asset-wrapper-array-plugin", () => { "severity": 1, }, { - "message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", + "message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", "range": { "end": { "character": 7, diff --git a/lsp/json-language-service/src/plugins/__tests__/missing-asset-wrapper-plugin.test.ts b/lsp/json-language-service/src/plugins/__tests__/missing-asset-wrapper-plugin.test.ts index 8ce4205..9e38311 100644 --- a/lsp/json-language-service/src/plugins/__tests__/missing-asset-wrapper-plugin.test.ts +++ b/lsp/json-language-service/src/plugins/__tests__/missing-asset-wrapper-plugin.test.ts @@ -60,7 +60,7 @@ describe("missing-asset-wrapper", () => { expect(validations?.map((v) => v.message)).toMatchInlineSnapshot(` [ "View Validation Error - value: Does not match any of the expected types for type: 'AssetWrapperOrSwitch'", - "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", + "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", ] `); }); @@ -87,7 +87,7 @@ describe("missing-asset-wrapper", () => { "severity": 1, }, { - "message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", + "message": "Expected: AssetWrapper & object literal | StaticSwitch & object literal | DynamicSwitch & object literal", "range": { "end": { "character": 7, diff --git a/lsp/json-language-service/src/plugins/__tests__/schema-validation-plugin.test.ts b/lsp/json-language-service/src/plugins/__tests__/schema-validation-plugin.test.ts new file mode 100644 index 0000000..f57dd76 --- /dev/null +++ b/lsp/json-language-service/src/plugins/__tests__/schema-validation-plugin.test.ts @@ -0,0 +1,1923 @@ +import { test, expect, describe, beforeEach } from "vitest"; +import { CommonTypes, Types } from "@player-lang/static-xlrs"; +import { PlayerLanguageService } from "../.."; +import { toTextDocument } from "../../utils"; + +describe("SchemaValidationPlugin", () => { + let service: PlayerLanguageService; + + beforeEach(async () => { + service = new PlayerLanguageService(); + await service.setAssetTypesFromModule([Types, CommonTypes]); + }); + + describe("schema structure validation", () => { + test("reports error when schema is missing ROOT", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + SomeType: { + foo: { type: "SomeType" }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - missing: Property "ROOT" missing from type "Schema.Schema"", + "range": { + "end": { + "character": 3, + "line": 12, + }, + "start": { + "character": 12, + "line": 6, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Schema must have a "ROOT" key.", + "range": { + "end": { + "character": 3, + "line": 12, + }, + "start": { + "character": 12, + "line": 6, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when DataType is missing type property", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + application: { + validation: [], + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 10, + }, + "start": { + "character": 21, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Schema.DataType must have a "type" property (reference to schema or XLR type).", + "range": { + "end": { + "character": 7, + "line": 10, + }, + "start": { + "character": 21, + "line": 8, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when type is not a string", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + application: { + type: 123, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 10, + }, + "start": { + "character": 21, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Schema "type" must be a string (schema type name or XLR type name).", + "range": { + "end": { + "character": 19, + "line": 9, + }, + "start": { + "character": 16, + "line": 9, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when isArray is not a boolean", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + items: { + type: "StringType", + isArray: "yes", + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Schema.DataType "isArray" must be a boolean.", + "range": { + "end": { + "character": 24, + "line": 10, + }, + "start": { + "character": 19, + "line": 10, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when validation is not an array", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "TypeA", + validation: "not-an-array", + }, + }, + TypeA: { + nested: { type: "StringType" }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 11, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when format is not an object", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "TypeA", + format: "not-an-object", + }, + }, + TypeA: { + nested: { type: "StringType" }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 11, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when isRecord is not a boolean", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + isRecord: "yes", + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Schema.DataType "isRecord" must be a boolean.", + "range": { + "end": { + "character": 25, + "line": 10, + }, + "start": { + "character": 20, + "line": 10, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when both isArray and isRecord are true", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + isArray: true, + isRecord: true, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Schema.DataType cannot have both "isArray" and "isRecord" true.", + "range": { + "end": { + "character": 7, + "line": 12, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + ] + `); + }); + }); + + describe("schema type reference validation", () => { + test("reports error for unknown type reference (not in schema, not in XLR)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + foo: { + type: "NonExistentXLRType", + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Unknown schema type "NonExistentXLRType". Type must be a schema type (key in this schema) or an XLR type loaded in the SDK.", + "range": { + "end": { + "character": 36, + "line": 9, + }, + "start": { + "character": 16, + "line": 9, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("accepts type reference to XLR-loaded type when that type is in the SDK", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + name: { type: "StringType" }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(`[]`); + }); + + test("reports errors for multiple unknown type references", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + a: { type: "UnknownA" }, + b: { type: "UnknownB" }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Unknown schema type "UnknownA". Type must be a schema type (key in this schema) or an XLR type loaded in the SDK.", + "range": { + "end": { + "character": 26, + "line": 9, + }, + "start": { + "character": 16, + "line": 9, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Unknown schema type "UnknownB". Type must be a schema type (key in this schema) or an XLR type loaded in the SDK.", + "range": { + "end": { + "character": 26, + "line": 12, + }, + "start": { + "character": 16, + "line": 12, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports no Schema DataType errors when DataType conforms to XLR (StringType)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + name: { + type: "StringType", + default: "", + validation: [], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(`[]`); + }); + + test("reports Schema DataType error when BooleanType payload has wrong type for property", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + flag: { + type: "BooleanType", + default: "not-a-boolean", + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Default value doesn't match the expected type of boolean for type BooleanType", + "range": { + "end": { + "character": 34, + "line": 10, + }, + "start": { + "character": 19, + "line": 10, + }, + }, + "severity": 1, + }, + ] + `); + }); + + describe("default property validation (CollectionType / Or type)", () => { + test("accepts CollectionType with valid default (number)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + items: { + type: "CollectionType", + default: 0, + validation: [{ type: "collection" }], + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts CollectionType with valid default (string)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + items: { + type: "CollectionType", + default: "", + validation: [{ type: "collection" }], + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("reports error when CollectionType default is boolean (not in Or type)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + items: { + type: "CollectionType", + default: true, + validation: [{ type: "collection" }], + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(1); + expect(schemaErrors[0].message).toBe( + "Schema Validation Error: Default value doesn't match any of the expected types number, string for type CollectionType", + ); + }); + + test("reports error when CollectionType default is array (not in Or type)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + items: { + type: "CollectionType", + default: [], + validation: [{ type: "collection" }], + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(1); + expect(schemaErrors[0].message).toBe( + "Schema Validation Error: Default value doesn't match any of the expected types number, string for type CollectionType", + ); + }); + + test("reports error when CollectionType default is object (not in Or type)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + items: { + type: "CollectionType", + default: {}, + validation: [{ type: "collection" }], + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(1); + expect(schemaErrors[0].message).toBe( + "Schema Validation Error: Default value doesn't match any of the expected types number, string for type CollectionType", + ); + }); + }); + }); + + describe("flow without schema", () => { + test("does not add schema errors when schema is absent", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(`[]`); + }); + }); + + describe("validation object logic branches", () => { + test('reports error when validation entry is missing "type" property', async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [{}], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 16, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Validation object missing "type" property", + "range": { + "end": { + "character": 12, + "line": 11, + }, + "start": { + "character": 10, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when validation type is not a string", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [{ type: 123 }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 18, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Validation type must be a string", + "range": { + "end": { + "character": 23, + "line": 12, + }, + "start": { + "character": 20, + "line": 12, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when validation type is not a registered validator", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [{ type: "NonExistentValidator" }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Validation Function [object Object] is not a registered validator", + "range": { + "end": { + "character": 11, + "line": 13, + }, + "start": { + "character": 10, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when registered validator has invalid props (min expects number)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + score: { + type: "IntegerType", + validation: [{ type: "min", value: "not-a-number" }], + format: { type: "integer" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Expected type "number" but got "string"", + "range": { + "end": { + "character": 11, + "line": 14, + }, + "start": { + "character": 10, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when validation array element is not an object", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: ["not-an-object"], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 16, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Schema.DataType "validation" must be an object.", + "range": { + "end": { + "character": 9, + "line": 12, + }, + "start": { + "character": 22, + "line": 10, + }, + }, + "severity": 1, + }, + ] + `); + }); + }); + + describe("format object logic branches", () => { + test('reports error when format object is missing "type" property', async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [], + format: {}, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 12, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Format object missing "type" property", + "range": { + "end": { + "character": 20, + "line": 11, + }, + "start": { + "character": 18, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when format type is not a string", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [], + format: { type: 42 }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 7, + "line": 14, + }, + "start": { + "character": 15, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Format type must be a string", + "range": { + "end": { + "character": 20, + "line": 12, + }, + "start": { + "character": 18, + "line": 12, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when format type is not a registered formatter", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [], + format: { type: "NonExistentFormatter" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Formatter [object Object] is not a registered formatter", + "range": { + "end": { + "character": 9, + "line": 13, + }, + "start": { + "character": 18, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when formatter with 3 args has invalid props (date mask must be string)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + birthDate: { + type: "DateType", + validation: [], + format: { type: "date", mask: 123 }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Expected type "string" but got "number"", + "range": { + "end": { + "character": 9, + "line": 14, + }, + "start": { + "character": 18, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("accepts formatter with 3 args and valid props (date with mask string)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + birthDate: { + type: "DateType", + validation: [], + format: { type: "date", mask: "MM/DD/YYYY" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + }); + + describe("schema and flow structure branches", () => { + test("reports error when flow schema is not an object (string)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: "not-an-object", + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - type: Expected an object but got an "string"", + "range": { + "end": { + "character": 27, + "line": 6, + }, + "start": { + "character": 12, + "line": 6, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Flow "schema" must be an object with at least a "ROOT" key.", + "range": { + "end": { + "character": 27, + "line": 6, + }, + "start": { + "character": 12, + "line": 6, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when flow schema is not an object (array)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: [], + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - type: Expected an object but got an "array"", + "range": { + "end": { + "character": 14, + "line": 6, + }, + "start": { + "character": 12, + "line": 6, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Flow "schema" must be an object with at least a "ROOT" key.", + "range": { + "end": { + "character": 14, + "line": 6, + }, + "start": { + "character": 12, + "line": 6, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when schema node (ROOT) value is not an object", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: "not-an-object", + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - type: Expected an object but got an "string"", + "range": { + "end": { + "character": 27, + "line": 7, + }, + "start": { + "character": 12, + "line": 7, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Schema node "ROOT" must be an object.", + "range": { + "end": { + "character": 27, + "line": 7, + }, + "start": { + "character": 12, + "line": 7, + }, + }, + "severity": 1, + }, + ] + `); + }); + + test("reports error when schema property value is not an object (DataType)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + application: "must-be-DataType-object", + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Content Validation Error - value: Does not match any of the expected types for type: 'DataTypes'", + "range": { + "end": { + "character": 46, + "line": 8, + }, + "start": { + "character": 21, + "line": 8, + }, + }, + "severity": 1, + }, + { + "message": "Schema Validation Error: Schema property "application" must be an object (Schema.DataType) with a "type" field.", + "range": { + "end": { + "character": 46, + "line": 8, + }, + "start": { + "character": 21, + "line": 8, + }, + }, + "severity": 1, + }, + ] + `); + }); + }); + + describe("specific DataTypes from CommonTypes", () => { + test("accepts IntegerType with valid validation and format", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + count: { + type: "IntegerType", + validation: [{ type: "integer" }], + format: { type: "integer" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts BooleanType with valid default and validation", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + flag: { + type: "BooleanType", + default: false, + validation: [ + { + type: "oneOf", + message: "Value must be true or false", + options: [true, false], + }, + ], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts DateType with valid format", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + start: { + type: "DateType", + validation: [], + format: { type: "date" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts formatter with 2 generic args (integer) without prop validation", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + num: { + type: "IntegerType", + validation: [], + format: { type: "integer" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + }); + + describe("specific Validators from CommonTypes", () => { + test("accepts required validator with no props", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + name: { + type: "StringType", + validation: [{ type: "required" }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts string validator (no props)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + name: { + type: "StringType", + validation: [{ type: "string" }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts min validator with valid number prop", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + score: { + type: "IntegerType", + validation: [{ type: "min", value: 0 }], + format: { type: "integer" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + describe("length validator (OrType / union params)", () => { + test("accepts length validator with min/max variant (valid props)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + title: { + type: "StringType", + validation: [{ type: "length", min: 1, max: 100 }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts length validator with min only (first Or variant)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + title: { + type: "StringType", + validation: [{ type: "length", min: 0 }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts length validator with max only (first Or variant)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + code: { + type: "StringType", + validation: [{ type: "length", max: 10 }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("accepts length validator with exact variant (second Or variant)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + pin: { + type: "StringType", + validation: [{ type: "length", exact: 6 }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("reports error when length validator has invalid prop type (min must be number)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + title: { + type: "StringType", + validation: [{ type: "length", min: "five" }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors.length).toBeGreaterThan(0); + expect( + schemaErrors.some( + (d) => + d.message.includes("Expected type") || + d.message.includes("invalid function parameters"), + ), + ).toBe(true); + }); + + test("reports error when length validator has invalid function parameters (no Or variant matches)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + title: { + type: "StringType", + validation: [ + { type: "length", min: "not-a-number", max: "also-not" }, + ], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors.length).toBeGreaterThan(0); + expect( + schemaErrors.some( + (d) => + d.message.includes("invalid function parameters") || + d.message.includes("Expected type"), + ), + ).toBe(true); + }); + + test("reports error when length validator matches multiple Or variants (ambiguous params)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + field: { + type: "StringType", + validation: [{ type: "length", min: 1, exact: 5 }], + format: { type: "string" }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(1); + expect(schemaErrors[0].message).toContain( + "Validation function invalid function parameters for type length", + ); + }); + }); + }); + + describe("specific Formatters from CommonTypes", () => { + test("accepts currency formatter with valid optional props", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + price: { + type: "StringType", + validation: [], + format: { + type: "currency", + currencySymbol: "$", + precision: 2, + useParensForNeg: false, + }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + const schemaErrors = (diagnostics ?? []).filter((d) => + d.message.includes("Schema Validation Error:"), + ); + expect(schemaErrors).toHaveLength(0); + }); + + test("reports error when currency formatter has invalid prop type (precision must be number)", async () => { + const document = toTextDocument( + JSON.stringify( + { + id: "foo", + views: [], + navigation: { BEGIN: "FLOW1" }, + schema: { + ROOT: { + price: { + type: "StringType", + validation: [], + format: { + type: "currency", + precision: "two", + }, + }, + }, + }, + }, + null, + 2, + ), + ); + const diagnostics = await service.validateTextDocument(document); + expect(diagnostics).toMatchInlineSnapshot(` + [ + { + "message": "Schema Validation Error: Expected type "number" but got "string"", + "range": { + "end": { + "character": 9, + "line": 14, + }, + "start": { + "character": 18, + "line": 11, + }, + }, + "severity": 1, + }, + ] + `); + }); + }); +}); diff --git a/lsp/json-language-service/src/plugins/schema-validation-plugin.ts b/lsp/json-language-service/src/plugins/schema-validation-plugin.ts new file mode 100644 index 0000000..ec995e8 --- /dev/null +++ b/lsp/json-language-service/src/plugins/schema-validation-plugin.ts @@ -0,0 +1,508 @@ +import { DiagnosticSeverity } from "vscode-languageserver-types"; +import type { PlayerLanguageService, PlayerLanguageServicePlugin } from ".."; +import type { ValidationContext, ASTVisitor } from "../types"; +import type { ContentASTNode, ObjectASTNode, StringASTNode } from "../parser"; +import { getProperty } from "../utils"; +import type { ValidationMessage, XLRSDK } from "@xlr-lib/xlr-sdk"; +import { NamedType, ObjectType, OrType, RefType } from "@xlr-lib/xlr"; +import { translateSeverity } from "./xlr-plugin"; +import { isObjectType, isPrimitiveTypeNode } from "@xlr-lib/xlr-utils"; + +function formatErrorMessage(message: string): string { + return `Schema Validation Error: ${message}`; +} + +function makeValidationRefObject( + baseObject: ObjectType, + validationFunction: ObjectType, +): ObjectType { + return { + ...baseObject, + properties: { + ...baseObject.properties, + ...validationFunction.properties, + }, + additionalProperties: false, + } as ObjectType; +} + +/** + * Validate that all claimed validations are registered and pass the correct props + */ +function validateSchemaValidations( + validationNode: ObjectASTNode, + sdk: XLRSDK, + validationContext: ValidationContext, +) { + const claimedValidator = getProperty(validationNode, "type"); + if (!claimedValidator) { + validationContext.addViolation({ + node: validationNode, + message: formatErrorMessage('Validation object missing "type" property'), + severity: DiagnosticSeverity.Error, + }); + } else if (claimedValidator.valueNode?.type !== "string") { + validationContext.addViolation({ + node: claimedValidator.valueNode ?? validationNode, + message: formatErrorMessage("Validation type must be a string"), + severity: DiagnosticSeverity.Error, + }); + } else { + const validationXLR = sdk.getType(claimedValidator.valueNode.value, { + getRawType: true, + }) as NamedType; + if (!validationXLR) { + validationContext.addViolation({ + node: validationNode, + message: formatErrorMessage( + `Validation Function ${claimedValidator} is not a registered validator`, + ), + severity: DiagnosticSeverity.Error, + }); + } else { + const valRef = sdk.getType("Validation.Reference", { + getRawType: true, + }) as NamedType | undefined; + if (valRef) { + let validationIssues: ValidationMessage[]; + const validatorFunctionProps = validationXLR.genericArguments?.[0] as + | ObjectType + | OrType + | undefined; + + if (!validatorFunctionProps || isObjectType(validatorFunctionProps)) { + validationIssues = sdk.validateByType( + makeValidationRefObject( + valRef, + validatorFunctionProps ?? ({} as ObjectType), + ), + validationNode.jsonNode, + ); + validationIssues.forEach((issue) => { + validationContext.addViolation({ + node: validationNode, + message: formatErrorMessage(issue.message), + severity: translateSeverity(issue.severity), + }); + }); + } else { + // need to make sure that only one of the arg groups is right + const validationResults = validatorFunctionProps.or + .map((node) => { + if (isObjectType(node)) { + return sdk.validateByType( + makeValidationRefObject(valRef, node), + validationNode.jsonNode, + ); + } else { + validationIssues.forEach((issue) => { + validationContext.addViolation({ + node: validationNode, + message: formatErrorMessage( + `Internal Error - Validation function ${validationXLR.name} type argument is not an object`, + ), + severity: DiagnosticSeverity.Error, + }); + }); + return null; + } + }) + .filter((o) => o !== null && Array.isArray(o) && o.length === 0); + + if (validationResults.length !== 1) { + validationContext.addViolation({ + node: validationNode, + message: formatErrorMessage( + `Validation function invalid function parameters for type ${validationXLR.name}`, + ), + severity: DiagnosticSeverity.Error, + }); + } + } + } else { + validationContext.addViolation({ + node: validationNode, + message: formatErrorMessage( + "Validation.Reference from @player-ui/types is not loaded into SDK", + ), + severity: DiagnosticSeverity.Error, + }); + } + } + } +} + +/** + * Validate that the format function is registered and passes the correct props + */ +function validateSchemaFormat( + formatNode: ObjectASTNode, + sdk: XLRSDK, + validationContext: ValidationContext, +) { + const claimedFormatter = getProperty(formatNode, "type"); + if (!claimedFormatter) { + validationContext.addViolation({ + node: formatNode, + message: formatErrorMessage('Format object missing "type" property'), + severity: DiagnosticSeverity.Error, + }); + } else if (claimedFormatter.valueNode?.type !== "string") { + validationContext.addViolation({ + node: claimedFormatter.valueNode ?? claimedFormatter, + message: formatErrorMessage("Format type must be a string"), + severity: DiagnosticSeverity.Error, + }); + } else { + const formatterXLR = sdk.getType(claimedFormatter.valueNode.value, { + getRawType: true, + }) as RefType; + if (!formatterXLR) { + validationContext.addViolation({ + node: formatNode, + message: formatErrorMessage( + `Formatter ${claimedFormatter} is not a registered formatter`, + ), + severity: DiagnosticSeverity.Error, + }); + } else if ( + formatterXLR.genericArguments && + formatterXLR.genericArguments.length === 3 + ) { + const otherArgsXLR = formatterXLR.genericArguments[2] as ObjectType; + const validationIssues = sdk.validateByType( + { + ...otherArgsXLR, + properties: { + ...otherArgsXLR.properties, + type: { + required: true, + node: { + type: "string", + const: claimedFormatter.valueNode.value, + }, + }, + }, + }, + formatNode.jsonNode, + ); + + validationIssues.forEach((issue) => { + validationContext.addViolation({ + node: formatNode, + message: formatErrorMessage(issue.message), + severity: translateSeverity(issue.severity), + }); + }); + } + } +} + +/** + * Collects all type names defined at the top level of the schema (ROOT and + * any custom type names). Used to validate that "type" references either + * point to a schema type or an XLR-loaded type. + */ +function getSchemaTypeNames(schemaObj: ObjectASTNode): Set { + const names = new Set(); + for (const prop of schemaObj.properties) { + const key = prop.keyNode?.value; + if (typeof key === "string") { + names.add(key); + } + } + return names; +} + +/** + * Validates that a Schema.DataType object has the proper structure + */ +function validateDataTypeStructure( + dataTypeNode: ObjectASTNode, + claimedDataType: NamedType, + sdk: XLRSDK, + validationContext: ValidationContext, +): void { + // Basic Structural Tests + const validationProp = getProperty(dataTypeNode, "validation"); + if (validationProp?.valueNode && validationProp.valueNode.type !== "array") { + validationContext.addViolation({ + node: validationProp.valueNode, + message: formatErrorMessage( + 'Schema.DataType "validation" must be an array.', + ), + severity: DiagnosticSeverity.Error, + }); + } else if (validationProp?.valueNode) { + validationProp.valueNode.children?.forEach((valRef) => { + if (valRef && valRef.type === "object") { + validateSchemaValidations(valRef, sdk, validationContext); + } else { + validationContext.addViolation({ + node: validationProp.valueNode ?? dataTypeNode, + message: formatErrorMessage( + 'Schema.DataType "validation" must be an object.', + ), + severity: DiagnosticSeverity.Error, + }); + } + }); + } + + const formatProp = getProperty(dataTypeNode, "format"); + if (formatProp?.valueNode?.type === "object") { + validateSchemaFormat(formatProp.valueNode, sdk, validationContext); + } else { + if (formatProp) { + validationContext.addViolation({ + node: formatProp?.valueNode ?? dataTypeNode, + message: formatErrorMessage( + 'Schema.DataType "format" must be an object.', + ), + severity: DiagnosticSeverity.Error, + }); + } + } + + // Check if default value conforms to the expected value + const defaultNode = claimedDataType.properties?.["default"]?.node; + const defaultProp = getProperty(dataTypeNode, "default"); + if (defaultNode && defaultProp?.valueNode) { + if (isPrimitiveTypeNode(defaultNode)) { + if (defaultProp.valueNode.type !== defaultNode.type) { + validationContext.addViolation({ + node: defaultProp.valueNode, + message: formatErrorMessage( + `Default value doesn't match the expected type of ${defaultNode.type} for type ${claimedDataType.name}`, + ), + severity: DiagnosticSeverity.Error, + }); + } + } else if (defaultNode.type === "or") { + if (!defaultNode.or.some((n) => n.type === defaultProp.valueNode?.type)) { + validationContext.addViolation({ + node: defaultProp.valueNode, + message: formatErrorMessage( + `Default value doesn't match any of the expected types ${defaultNode.or.map((t) => t.type).join(", ")} for type ${claimedDataType.name}`, + ), + severity: DiagnosticSeverity.Error, + }); + } + } else { + validationContext.addViolation({ + node: defaultProp.valueNode, + message: formatErrorMessage( + `Unknown default node type ${defaultNode.type}`, + ), + severity: DiagnosticSeverity.Error, + }); + } + } + + // RecordType/ArrayType Checks + const isArrayProp = getProperty(dataTypeNode, "isArray"); + const isRecordProp = getProperty(dataTypeNode, "isRecord"); + if (isArrayProp?.valueNode && isArrayProp.valueNode.type !== "boolean") { + validationContext.addViolation({ + node: isArrayProp.valueNode, + message: formatErrorMessage( + 'Schema.DataType "isArray" must be a boolean.', + ), + severity: DiagnosticSeverity.Error, + }); + } + if (isRecordProp?.valueNode && isRecordProp.valueNode.type !== "boolean") { + validationContext.addViolation({ + node: isRecordProp.valueNode, + message: formatErrorMessage( + 'Schema.DataType "isRecord" must be a boolean.', + ), + severity: DiagnosticSeverity.Error, + }); + } + + if ( + isArrayProp?.valueNode && + isRecordProp?.valueNode && + (isArrayProp.valueNode as { value?: boolean }).value === true && + (isRecordProp.valueNode as { value?: boolean }).value === true + ) { + validationContext.addViolation({ + node: dataTypeNode, + message: formatErrorMessage( + 'Schema.DataType cannot have both "isArray" and "isRecord" true.', + ), + severity: DiagnosticSeverity.Error, + }); + } +} + +/** + * Validates a single schema node (e.g. ROOT or a custom type): each property + * must be an object with a "type" field (Schema.DataType), full structure + * validation, known type reference (schema or XLR), and when the type is an + * XLR type, validates the DataType object against the XLR definition via the SDK. + */ +function validateSchemaNode( + node: ObjectASTNode, + schemaTypeNames: Set, + sdk: XLRSDK, + validationContext: ValidationContext, +): void { + for (const prop of node.properties) { + const valueNode = prop.valueNode; + if (!(valueNode && valueNode.type === "object")) { + if (valueNode) { + validationContext.addViolation({ + node: valueNode, + message: formatErrorMessage( + `Schema property "${prop.keyNode.value}" must be an object (Schema.DataType) with a "type" field.`, + ), + severity: DiagnosticSeverity.Error, + }); + } + continue; + } + + const dataTypeNode = valueNode as ObjectASTNode; + const typeProp = getProperty(dataTypeNode, "type"); + if (!typeProp) { + validationContext.addViolation({ + node: valueNode, + message: formatErrorMessage( + 'Schema.DataType must have a "type" property (reference to schema or XLR type).', + ), + severity: DiagnosticSeverity.Error, + }); + continue; + } + + const typeValueNode = typeProp.valueNode; + if (!typeValueNode || typeValueNode.type !== "string") { + validationContext.addViolation({ + node: typeValueNode ?? typeProp, + message: formatErrorMessage( + 'Schema "type" must be a string (schema type name or XLR type name).', + ), + severity: DiagnosticSeverity.Error, + }); + continue; + } + + const typeName = (typeValueNode as StringASTNode).value; + const isSchemaType = schemaTypeNames.has(typeName); + const XLRType = sdk.getType(typeName, { getRawType: true }); + + if (!isSchemaType && !XLRType) { + validationContext.addViolation({ + node: typeValueNode, + message: formatErrorMessage( + `Unknown schema type "${typeName}". Type must be a schema type (key in this schema) or an XLR type loaded in the SDK.`, + ), + severity: DiagnosticSeverity.Error, + }); + } else if (XLRType) { + /** Full DataType structure per @player-ui/types */ + validateDataTypeStructure( + dataTypeNode, + XLRType as NamedType, + sdk, + validationContext, + ); + } + } +} + +/** + * Validates the Flow's schema property: structure per Schema.Schema, + * type references, full DataType structure, and XLR shape when type is an XLR type. + */ +function validateFlowSchema( + contentNode: ContentASTNode, + sdk: XLRSDK, + validationContext: ValidationContext, +): void { + const schemaProp = getProperty(contentNode, "schema"); + if (!schemaProp?.valueNode) { + return; + } + + const schemaValue = schemaProp.valueNode; + if (schemaValue.type !== "object") { + validationContext.addViolation({ + node: schemaValue, + message: formatErrorMessage( + 'Flow "schema" must be an object with at least a "ROOT" key.', + ), + severity: DiagnosticSeverity.Error, + }); + return; + } + + const schemaObj = schemaValue as ObjectASTNode; + const hasRoot = schemaObj.properties.some((p) => p.keyNode.value === "ROOT"); + + if (!hasRoot) { + validationContext.addViolation({ + node: schemaValue, + message: formatErrorMessage('Schema must have a "ROOT" key.'), + severity: DiagnosticSeverity.Error, + }); + } + + const schemaTypeNames = getSchemaTypeNames(schemaObj); + + for (const prop of schemaObj.properties) { + const nodeValue = prop.valueNode; + if (!nodeValue || nodeValue.type !== "object") { + if (nodeValue) { + validationContext.addViolation({ + node: nodeValue, + message: formatErrorMessage( + `Schema node "${prop.keyNode.value}" must be an object.`, + ), + severity: DiagnosticSeverity.Error, + }); + } + continue; + } + + validateSchemaNode( + nodeValue as ObjectASTNode, + schemaTypeNames, + sdk, + validationContext, + ); + } +} + +/** + * Plugin that registers schema validation with the Player Language Service. + */ +export class SchemaValidationPlugin implements PlayerLanguageServicePlugin { + name = "schema-validation"; + + /** Resolved when CommonTypes have been loaded into the XLR SDK (once per plugin apply) */ + private commonTypesLoaded: Promise | null = null; + + apply(service: PlayerLanguageService): void { + service.hooks.validate.tap(this.name, async (_ctx, validationContext) => { + await this.commonTypesLoaded; + validationContext.useASTVisitor( + this.createValidationVisitor(service, validationContext), + ); + }); + } + + private createValidationVisitor( + service: PlayerLanguageService, + validationContext: ValidationContext, + ): ASTVisitor { + const sdk = service.XLRService.XLRSDK; + return { + ContentNode: (contentNode) => { + validateFlowSchema(contentNode, sdk, validationContext); + }, + }; + } +} diff --git a/lsp/json-language-service/src/plugins/xlr-plugin.ts b/lsp/json-language-service/src/plugins/xlr-plugin.ts index 6e346ae..0d570ec 100644 --- a/lsp/json-language-service/src/plugins/xlr-plugin.ts +++ b/lsp/json-language-service/src/plugins/xlr-plugin.ts @@ -14,7 +14,7 @@ import type { PlayerLanguageServicePlugin, ValidationContext, } from ".."; -import { mapFlowStateToType } from "../utils"; +import { findErrorNode, mapFlowStateToType } from "../utils"; import type { ASTNode, ObjectASTNode } from "../parser"; import type { EnhancedDocumentContextWithPosition } from "../types"; @@ -22,30 +22,11 @@ function isError(issue: ValidationMessage): boolean { return issue.severity === DiagnosticSeverity.Error; } -/** BFS search to find a JSONC node in children of some AST Node */ -const findErrorNode = (rootNode: ASTNode, nodeToFind: Node): ASTNode => { - const children: Array = [rootNode]; - - while (children.length > 0) { - const child = children.pop() as ASTNode; - if (child.jsonNode === nodeToFind) { - return child; - } - - if (child.children) { - children.push(...child.children); - } - } - - // if the node can't be found return the original - return rootNode; -}; - /** * Translates an SDK severity level to an LSP severity level * Relies on both levels having the values associated to the underlying levels */ -const translateSeverity = ( +export const translateSeverity = ( severity: ValidationSeverity, ): DiagnosticSeverity => { return severity as DiagnosticSeverity; diff --git a/lsp/json-language-service/src/utils.ts b/lsp/json-language-service/src/utils.ts index 9d33ac3..df43085 100644 --- a/lsp/json-language-service/src/utils.ts +++ b/lsp/json-language-service/src/utils.ts @@ -7,6 +7,7 @@ import type { ObjectASTNode, PropertyASTNode, } from "./parser"; +import type { Node } from "jsonc-parser"; import type { ASTVisitor } from "./types"; export const typeToVisitorMap: Record = { @@ -141,3 +142,22 @@ export function mapFlowStateToType( return flowXLR; } + +/** BFS search to find a JSONC node in children of some AST Node */ +export const findErrorNode = (rootNode: ASTNode, nodeToFind: Node): ASTNode => { + const children: Array = [rootNode]; + + while (children.length > 0) { + const child = children.pop() as ASTNode; + if (child.jsonNode === nodeToFind) { + return child; + } + + if (child.children) { + children.push(...child.children); + } + } + + // if the node can't be found return the original + return rootNode; +}; diff --git a/lsp/json-language-service/src/xlr/registry.ts b/lsp/json-language-service/src/xlr/registry.ts index 2878a08..0ad385a 100644 --- a/lsp/json-language-service/src/xlr/registry.ts +++ b/lsp/json-language-service/src/xlr/registry.ts @@ -2,6 +2,9 @@ import type { Filters, TypeMetadata } from "@xlr-lib/xlr-sdk"; import { BasicXLRRegistry } from "@xlr-lib/xlr-sdk"; import type { NamedType, NodeType } from "@xlr-lib/xlr"; +/** Capabilities that can only exist once */ +const SINGLE_INSTANCE_CAPABILITIES = ["DataTypes", "Formatters", "Validators"]; + /** * Player specific implementation of a XLRs Registry */ @@ -47,7 +50,10 @@ export class PlayerXLRRegistry extends BasicXLRRegistry { registeredName = type.extends.genericArguments[0].const; } - if (this.registrationMap.has(registeredName)) { + if ( + this.registrationMap.has(registeredName) && + !SINGLE_INSTANCE_CAPABILITIES.includes(capability) + ) { const current = this.registrationMap.get(registeredName) as | string | string[]; diff --git a/package.json b/package.json index 7b0d241..e80985d 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,10 @@ "@types/node": "^18.18.0", "@types/react": "^18.3.3", "@typescript/vfs": "^1.4.0", - "@xlr-lib/xlr": "0.1.1-next.1", - "@xlr-lib/xlr-converters": "0.1.1-next.1", - "@xlr-lib/xlr-sdk": "0.1.1-next.1", - "@xlr-lib/xlr-utils": "0.1.1-next.1", + "@xlr-lib/xlr": "0.1.1-next.4", + "@xlr-lib/xlr-converters": "0.1.1-next.4", + "@xlr-lib/xlr-sdk": "0.1.1-next.4", + "@xlr-lib/xlr-utils": "0.1.1-next.4", "detect-indent": "^6.0.0", "dequal": "^2.0.2", "fs-extra": "^10.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 919d690..be44b35 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,17 +28,17 @@ importers: specifier: ^1.4.0 version: 1.6.2(typescript@5.5.4) '@xlr-lib/xlr': - specifier: 0.1.1-next.1 - version: 0.1.1-next.1 + specifier: 0.1.1-next.4 + version: 0.1.1-next.4 '@xlr-lib/xlr-converters': - specifier: 0.1.1-next.1 - version: 0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4) + specifier: 0.1.1-next.4 + version: 0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4) '@xlr-lib/xlr-sdk': - specifier: 0.1.1-next.1 - version: 0.1.1-next.1(typescript@5.5.4) + specifier: 0.1.1-next.4 + version: 0.1.1-next.4(typescript@5.5.4) '@xlr-lib/xlr-utils': - specifier: 0.1.1-next.1 - version: 0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4) + specifier: 0.1.1-next.4 + version: 0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4) dequal: specifier: ^2.0.2 version: 2.0.3 @@ -1011,24 +1011,25 @@ packages: '@vitest/utils@2.1.9': resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==, tarball: https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz} - '@xlr-lib/xlr-converters@0.1.1-next.1': - resolution: {integrity: sha512-uFxVj5J9atsz/vNW+Tw1IFoPKO7DFgj4PqqUz5734e5THFCBJ8ZPo4gw6cYNqhwOkVQ6HfKsVPeWF9zmoSt9PA==, tarball: https://registry.npmjs.org/@xlr-lib/xlr-converters/-/xlr-converters-0.1.1-next.1.tgz} + '@xlr-lib/xlr-converters@0.1.1-next.4': + resolution: {integrity: sha512-D5Sag7X2dQbya/l4DBqr/lyUDmu7ADDtKQotRdA8KixZE7JMJoI9CW5itera0PAo3WvIA7lTPTN1CrEvlTCe1A==, tarball: https://registry.npmjs.org/@xlr-lib/xlr-converters/-/xlr-converters-0.1.1-next.4.tgz} + hasBin: true peerDependencies: typescript: 5.5.4 - '@xlr-lib/xlr-sdk@0.1.1-next.1': - resolution: {integrity: sha512-8RbAwyR9iVwcUpjmjfekCm1OCwQ/aYs+XxuwEE/d7M1o07Eb/bYUovEMRiAr9DhiRwR6VshbW2yMv/blyz94Ag==, tarball: https://registry.npmjs.org/@xlr-lib/xlr-sdk/-/xlr-sdk-0.1.1-next.1.tgz} + '@xlr-lib/xlr-sdk@0.1.1-next.4': + resolution: {integrity: sha512-q46qn+7yzMJHT09+hHj0hej2t/p+IpIBT48BptlsKpEugENpFihrK4ITGJA6TO7QgtG58AKZsgTx95z8ebisyg==, tarball: https://registry.npmjs.org/@xlr-lib/xlr-sdk/-/xlr-sdk-0.1.1-next.4.tgz} peerDependencies: typescript: 5.5.4 - '@xlr-lib/xlr-utils@0.1.1-next.1': - resolution: {integrity: sha512-NqmvM/hpROJzYKPiXaSDO8D6W+Zcgp8CIL/7xE9WiRliGKzCZau9Zou80KIepkxgq6o1s5X4PDPxR1pGWNK5Pw==, tarball: https://registry.npmjs.org/@xlr-lib/xlr-utils/-/xlr-utils-0.1.1-next.1.tgz} + '@xlr-lib/xlr-utils@0.1.1-next.4': + resolution: {integrity: sha512-BDCQnfHy1SVY0bB6BByshpsSihgJ7imqNV9uhuk2OD003uhawOFa5WH4HRjmWnvXXuWp/5asjB9ObIwkNh3m4g==, tarball: https://registry.npmjs.org/@xlr-lib/xlr-utils/-/xlr-utils-0.1.1-next.4.tgz} peerDependencies: jsonc-parser: 2.3.1 typescript: 5.5.4 - '@xlr-lib/xlr@0.1.1-next.1': - resolution: {integrity: sha512-AybUJPSW1Vdpq8FsXzAUnPvbTavzD2NYqiR+EDBqOEVchnDXrtiNG2vsjMmzooxaaa+/JYps8vlTbgG9n2Dflw==, tarball: https://registry.npmjs.org/@xlr-lib/xlr/-/xlr-0.1.1-next.1.tgz} + '@xlr-lib/xlr@0.1.1-next.4': + resolution: {integrity: sha512-FCi+Fc0KQHUbKO+OTUp291aFcC/t7pmjtMYM6lQdXB55Lu+EV47jE3PjHqxZuS3LSitGxonXMEOrprQDrqL9MQ==, tarball: https://registry.npmjs.org/@xlr-lib/xlr/-/xlr-0.1.1-next.4.tgz} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, tarball: https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz} @@ -3907,35 +3908,35 @@ snapshots: loupe: 3.2.1 tinyrainbow: 1.2.0 - '@xlr-lib/xlr-converters@0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4)': + '@xlr-lib/xlr-converters@0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4)': dependencies: - '@xlr-lib/xlr': 0.1.1-next.1 - '@xlr-lib/xlr-utils': 0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4) + '@xlr-lib/xlr': 0.1.1-next.4 + '@xlr-lib/xlr-utils': 0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4) tslib: 2.8.1 typescript: 5.5.4 transitivePeerDependencies: - jsonc-parser - '@xlr-lib/xlr-sdk@0.1.1-next.1(typescript@5.5.4)': + '@xlr-lib/xlr-sdk@0.1.1-next.4(typescript@5.5.4)': dependencies: '@types/fs-extra': 9.0.13 '@types/node': 18.19.130 - '@xlr-lib/xlr': 0.1.1-next.1 - '@xlr-lib/xlr-converters': 0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4) - '@xlr-lib/xlr-utils': 0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4) + '@xlr-lib/xlr': 0.1.1-next.4 + '@xlr-lib/xlr-converters': 0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4) + '@xlr-lib/xlr-utils': 0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4) fs-extra: 10.1.0 jsonc-parser: 2.3.1 tslib: 2.8.1 typescript: 5.5.4 - '@xlr-lib/xlr-utils@0.1.1-next.1(jsonc-parser@2.3.1)(typescript@5.5.4)': + '@xlr-lib/xlr-utils@0.1.1-next.4(jsonc-parser@2.3.1)(typescript@5.5.4)': dependencies: - '@xlr-lib/xlr': 0.1.1-next.1 + '@xlr-lib/xlr': 0.1.1-next.4 jsonc-parser: 2.3.1 tslib: 2.8.1 typescript: 5.5.4 - '@xlr-lib/xlr@0.1.1-next.1': + '@xlr-lib/xlr@0.1.1-next.4': dependencies: tslib: 2.8.1 diff --git a/vitest.config.mts b/vitest.config.mts index 07c932a..03fd4b4 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -10,7 +10,7 @@ export default defineConfig({ "helpers", "bazel-bin", "bazel-out", - "bazel-tools", + "bazel-language", "bazel-testlogs", ], reporters: [