@mat3ra/esse 2026.7.14-0 → 2026.8.13-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.cursor/rules/resolve-generated-merge-conflicts.mdc +36 -0
  2. package/dist/js/esse/JSONSchemasInterface.d.ts +4 -0
  3. package/dist/js/esse/JSONSchemasInterface.js +10 -0
  4. package/dist/js/example/properties_directory/scalar/defect_formation_energy.json +5 -0
  5. package/dist/js/schema/job.json +147 -176
  6. package/dist/js/schema/material/material_properties.json +0 -4
  7. package/dist/js/schema/material.json +0 -4
  8. package/dist/js/schema/material_enhanced.json +889 -0
  9. package/dist/js/schema/material_enhanced_hashed.json +898 -0
  10. package/dist/js/schema/material_hashed.json +858 -0
  11. package/dist/js/schema/materials_category/compound_pristine_structures/two_dimensional/interface/configuration.json +0 -36
  12. package/dist/js/schema/materials_category/defective_structures/one_dimensional/grain_boundary_linear/configuration.json +0 -36
  13. package/dist/js/schema/materials_category/defective_structures/three_dimensional/solid_solution/configuration.json +0 -12
  14. package/dist/js/schema/materials_category/defective_structures/two_dimensional/adatom/configuration.json +0 -16
  15. package/dist/js/schema/materials_category/defective_structures/two_dimensional/grain_boundary_planar/configuration.json +0 -36
  16. package/dist/js/schema/materials_category/defective_structures/two_dimensional/island/configuration.json +0 -24
  17. package/dist/js/schema/materials_category/defective_structures/two_dimensional/terrace/configuration.json +0 -24
  18. package/dist/js/schema/materials_category/defective_structures/zero_dimensional/point_defect/base_configuration.json +0 -4
  19. package/dist/js/schema/materials_category/defective_structures/zero_dimensional/point_defect/interstitial.json +0 -8
  20. package/dist/js/schema/materials_category/defective_structures/zero_dimensional/point_defect/substitutional.json +0 -8
  21. package/dist/js/schema/materials_category/defective_structures/zero_dimensional/point_defect/vacancy.json +0 -4
  22. package/dist/js/schema/materials_category/pristine_structures/three_dimensional/ideal_crystal.json +0 -4
  23. package/dist/js/schema/materials_category/pristine_structures/two_dimensional/nanoribbon.json +0 -12
  24. package/dist/js/schema/materials_category/pristine_structures/two_dimensional/nanotape.json +0 -8
  25. package/dist/js/schema/materials_category/pristine_structures/two_dimensional/slab.json +0 -8
  26. package/dist/js/schema/materials_category/pristine_structures/two_dimensional/slab_strained_supercell.json +0 -8
  27. package/dist/js/schema/materials_category/processed_structures/two_dimensional/passivation/configuration.json +0 -8
  28. package/dist/js/schema/materials_category_components/entities/auxiliary/zero_dimensional/crystal_site.json +0 -4
  29. package/dist/js/schema/materials_category_components/entities/auxiliary/zero_dimensional/point_defect_site.json +0 -4
  30. package/dist/js/schema/materials_category_components/entities/auxiliary/zero_dimensional/void_region.json +0 -4
  31. package/dist/js/schema/materials_category_components/entities/core/three_dimensional/crystal.json +0 -4
  32. package/dist/js/schema/materials_category_components/entities/core/two_dimensional/vacuum.json +0 -4
  33. package/dist/js/schema/materials_category_components/entities/reusable/one_dimensional/crystal_lattice_lines.json +0 -4
  34. package/dist/js/schema/materials_category_components/entities/reusable/one_dimensional/crystal_lattice_lines_unique_repeated.json +0 -4
  35. package/dist/js/schema/materials_category_components/entities/reusable/three_dimensional/crystal_lattice_base.json +0 -4
  36. package/dist/js/schema/materials_category_components/entities/reusable/three_dimensional/strained_non_uniform.json +0 -4
  37. package/dist/js/schema/materials_category_components/entities/reusable/three_dimensional/strained_uniform.json +0 -4
  38. package/dist/js/schema/materials_category_components/entities/reusable/three_dimensional/supercell.json +0 -4
  39. package/dist/js/schema/materials_category_components/entities/reusable/two_dimensional/atomic_layers.json +0 -4
  40. package/dist/js/schema/materials_category_components/entities/reusable/two_dimensional/atomic_layers_unique.json +0 -4
  41. package/dist/js/schema/materials_category_components/entities/reusable/two_dimensional/atomic_layers_unique_repeated.json +0 -4
  42. package/dist/js/schema/materials_category_components/entities/reusable/two_dimensional/crystal_lattice_planes.json +0 -4
  43. package/dist/js/schema/materials_category_components/entities/reusable/two_dimensional/slab_stack_configuration.json +0 -12
  44. package/dist/js/schema/materials_category_components/operations/core/modifications/perturb.json +0 -4
  45. package/dist/js/schema/properties_directory/enum_options.json +1 -0
  46. package/dist/js/schema/properties_directory/non_scalar/workflow.json +147 -176
  47. package/dist/js/schema/properties_directory/scalar/defect_formation_energy.json +43 -0
  48. package/dist/js/schema/properties_directory/structural/basis_constrained.json +292 -0
  49. package/dist/js/schema/property/holder.json +189 -176
  50. package/dist/js/schema/software_directory/modeling/unit/execution.json +14 -16
  51. package/dist/js/schema/software_directory/scripting/unit/execution.json +14 -16
  52. package/dist/js/schema/system/bankable.json +1 -6
  53. package/dist/js/schema/system/hashed.json +15 -0
  54. package/dist/js/schema/system/status_track.json +29 -0
  55. package/dist/js/schema/workflow/base.json +147 -176
  56. package/dist/js/schema/workflow/subworkflow/mixin.json +88 -105
  57. package/dist/js/schema/workflow/subworkflow/unit.json +88 -105
  58. package/dist/js/schema/workflow/subworkflow.json +88 -105
  59. package/dist/js/schema/workflow/unit/assertion.json +15 -18
  60. package/dist/js/schema/workflow/unit/assignment.json +14 -17
  61. package/dist/js/schema/workflow/unit/base.json +12 -17
  62. package/dist/js/schema/workflow/unit/condition.json +15 -18
  63. package/dist/js/schema/workflow/unit/error.json +15 -18
  64. package/dist/js/schema/workflow/unit/execution.json +14 -16
  65. package/dist/js/schema/workflow/unit/io.json +15 -18
  66. package/dist/js/schema/workflow/unit/map.json +14 -17
  67. package/dist/js/schema/workflow/unit/mixins/base.json +11 -20
  68. package/dist/js/schema/workflow/unit/reduce.json +15 -18
  69. package/dist/js/schema/workflow/unit/subworkflow.json +15 -18
  70. package/dist/js/schema/workflow/unit.json +59 -71
  71. package/dist/js/schema/workflow.json +147 -176
  72. package/dist/js/schemas.json +1 -1
  73. package/dist/js/types.d.ts +1603 -1247
  74. package/dist/js/utils/ajv.d.ts +6 -5
  75. package/dist/js/utils/ajv.js +22 -9
  76. package/dist/js/utils/ajvKeywords/jsonSchemaToTypescriptKeywords.d.ts +7 -0
  77. package/dist/js/utils/ajvKeywords/jsonSchemaToTypescriptKeywords.js +21 -0
  78. package/dist/js/utils/removeEmptyAndNullProperties.d.ts +9 -0
  79. package/dist/js/utils/removeEmptyAndNullProperties.js +29 -0
  80. package/example/properties_directory/scalar/defect_formation_energy.json +5 -0
  81. package/manifest/properties.yaml +6 -0
  82. package/package.json +1 -1
  83. package/schema/material/material_properties.json +0 -4
  84. package/schema/material_enhanced.json +18 -0
  85. package/schema/material_enhanced_hashed.json +14 -0
  86. package/schema/material_hashed.json +22 -0
  87. package/schema/properties_directory/enum_options.json +1 -0
  88. package/schema/properties_directory/scalar/defect_formation_energy.json +21 -0
  89. package/schema/properties_directory/structural/basis_constrained.json +19 -0
  90. package/schema/property/holder.json +3 -0
  91. package/schema/system/bankable.json +1 -6
  92. package/schema/system/hashed.json +15 -0
  93. package/schema/system/status.json +5 -21
  94. package/schema/system/status_track.json +29 -0
  95. package/schema/workflow/unit/base.json +1 -1
  96. package/schema/workflow/unit/mixins/base.json +11 -20
  97. package/src/js/esse/JSONSchemasInterface.ts +11 -0
  98. package/src/js/utils/ajv.ts +22 -9
  99. package/src/js/utils/ajvKeywords/jsonSchemaToTypescriptKeywords.ts +22 -0
  100. package/src/js/utils/removeEmptyAndNullProperties.ts +32 -0
@@ -18,10 +18,11 @@ export declare function validate(data: AnyObject, jsonSchema: SchemaObject): {
18
18
  errors: import("ajv").ErrorObject<string, Record<string, any>, unknown>[] | null | undefined;
19
19
  };
20
20
  /**
21
- * Validates and clean a given example against the schema
22
- * @param example example to validate.
23
- * @param schema schema to validate the example with.
24
- * @returns whether example is valid.
21
+ * Validates and cleans data against the schema.
22
+ * Drops null properties first (empty strings kept for entity placeholders), then AJV removeAdditional.
23
+ * @param data data to validate (mutated in place).
24
+ * @param jsonSchema schema to validate the data with.
25
+ * @returns whether data is valid.
25
26
  */
26
27
  export declare function validateAndClean(data: AnyObject, jsonSchema: SchemaObject, { coerceTypes, useDefaults }?: {
27
28
  coerceTypes?: boolean | undefined;
@@ -30,4 +31,4 @@ export declare function validateAndClean(data: AnyObject, jsonSchema: SchemaObje
30
31
  isValid: boolean | Promise<any>;
31
32
  errors: import("ajv").ErrorObject<string, Record<string, any>, unknown>[] | null | undefined;
32
33
  };
33
- export {};
34
+ export { removeEmptyAndNullProperties } from "./removeEmptyAndNullProperties";
@@ -3,12 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.removeEmptyAndNullProperties = void 0;
6
7
  exports.getValidator = getValidator;
7
8
  exports.validate = validate;
8
9
  exports.validateAndClean = validateAndClean;
9
10
  const ajv_1 = __importDefault(require("ajv"));
10
11
  const ajv_formats_1 = __importDefault(require("ajv-formats"));
11
12
  const schemaUtils_1 = require("../esse/schemaUtils");
13
+ const jsonSchemaToTypescriptKeywords_1 = __importDefault(require("./ajvKeywords/jsonSchemaToTypescriptKeywords"));
14
+ const removeEmptyAndNullProperties_1 = require("./removeEmptyAndNullProperties");
12
15
  function addAdditionalPropertiesToSchema(schema, additionalProperties = false) {
13
16
  return (0, schemaUtils_1.mapObjectDeep)(schema, (object) => {
14
17
  const schema = object;
@@ -51,11 +54,17 @@ const ajvValidatorAndCleanerWithCoercingTypesNoDefaults = new ajv_1.default({
51
54
  coerceTypes: true,
52
55
  useDefaults: false,
53
56
  });
54
- (0, ajv_formats_1.default)(ajvValidator);
55
- (0, ajv_formats_1.default)(ajvValidatorAndCleaner);
56
- (0, ajv_formats_1.default)(ajvValidatorAndCleanerNoDefaults);
57
- (0, ajv_formats_1.default)(ajvValidatorAndCleanerWithCoercingTypes);
58
- (0, ajv_formats_1.default)(ajvValidatorAndCleanerWithCoercingTypesNoDefaults);
57
+ const ajvInstances = [
58
+ ajvValidator,
59
+ ajvValidatorAndCleaner,
60
+ ajvValidatorAndCleanerNoDefaults,
61
+ ajvValidatorAndCleanerWithCoercingTypes,
62
+ ajvValidatorAndCleanerWithCoercingTypesNoDefaults,
63
+ ];
64
+ ajvInstances.forEach((instance) => {
65
+ (0, ajv_formats_1.default)(instance);
66
+ (0, jsonSchemaToTypescriptKeywords_1.default)(instance);
67
+ });
59
68
  function getAjvInstance({ clean, coerceTypes, useDefaults }) {
60
69
  if (clean && coerceTypes) {
61
70
  return useDefaults
@@ -97,12 +106,14 @@ function validate(data, jsonSchema) {
97
106
  };
98
107
  }
99
108
  /**
100
- * Validates and clean a given example against the schema
101
- * @param example example to validate.
102
- * @param schema schema to validate the example with.
103
- * @returns whether example is valid.
109
+ * Validates and cleans data against the schema.
110
+ * Drops null properties first (empty strings kept for entity placeholders), then AJV removeAdditional.
111
+ * @param data data to validate (mutated in place).
112
+ * @param jsonSchema schema to validate the data with.
113
+ * @returns whether data is valid.
104
114
  */
105
115
  function validateAndClean(data, jsonSchema, { coerceTypes = false, useDefaults = true } = {}) {
116
+ (0, removeEmptyAndNullProperties_1.removeEmptyAndNullProperties)(data);
106
117
  const validator = getValidator(jsonSchema, { clean: true, coerceTypes, useDefaults });
107
118
  const isValid = validator(data);
108
119
  return {
@@ -110,3 +121,5 @@ function validateAndClean(data, jsonSchema, { coerceTypes = false, useDefaults =
110
121
  errors: validator.errors,
111
122
  };
112
123
  }
124
+ var removeEmptyAndNullProperties_2 = require("./removeEmptyAndNullProperties");
125
+ Object.defineProperty(exports, "removeEmptyAndNullProperties", { enumerable: true, get: function () { return removeEmptyAndNullProperties_2.removeEmptyAndNullProperties; } });
@@ -0,0 +1,7 @@
1
+ import type Ajv from "ajv";
2
+ /**
3
+ * Schemas include json-schema-to-typescript hints (`tsType`, `tsEnumNames`, …).
4
+ * Ajv strict mode rejects unknown keywords; register them as no-ops so the same schemas work for
5
+ * runtime validation.
6
+ */
7
+ export default function addJsonSchemaToTypescriptKeywords(ajv: Ajv): void;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = addJsonSchemaToTypescriptKeywords;
4
+ /**
5
+ * Schemas include json-schema-to-typescript hints (`tsType`, `tsEnumNames`, …).
6
+ * Ajv strict mode rejects unknown keywords; register them as no-ops so the same schemas work for
7
+ * runtime validation.
8
+ */
9
+ function addJsonSchemaToTypescriptKeywords(ajv) {
10
+ const validateNoop = () => true;
11
+ ajv.addKeyword({
12
+ keyword: "tsType",
13
+ validate: validateNoop,
14
+ errors: false,
15
+ });
16
+ ajv.addKeyword({
17
+ keyword: "tsEnumNames",
18
+ validate: validateNoop,
19
+ errors: false,
20
+ });
21
+ }
@@ -0,0 +1,9 @@
1
+ export type AnyObject = Record<string, any>;
2
+ /**
3
+ * Recursively removes null properties from an object.
4
+ * Empty strings are preserved (entity schemas use "" as intentional placeholders, e.g. flowchart links).
5
+ * Nested objects are cleaned in place; array elements are walked but not removed.
6
+ * @param obj The object to clean
7
+ * @returns The cleaned object (mutates the original)
8
+ */
9
+ export declare function removeEmptyAndNullProperties(obj: AnyObject): AnyObject;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeEmptyAndNullProperties = removeEmptyAndNullProperties;
4
+ /**
5
+ * Recursively removes null properties from an object.
6
+ * Empty strings are preserved (entity schemas use "" as intentional placeholders, e.g. flowchart links).
7
+ * Nested objects are cleaned in place; array elements are walked but not removed.
8
+ * @param obj The object to clean
9
+ * @returns The cleaned object (mutates the original)
10
+ */
11
+ function removeEmptyAndNullProperties(obj) {
12
+ if (typeof obj !== "object" || obj === null) {
13
+ return obj;
14
+ }
15
+ if (Array.isArray(obj)) {
16
+ obj.forEach((item) => removeEmptyAndNullProperties(item));
17
+ return obj;
18
+ }
19
+ Object.keys(obj).forEach((key) => {
20
+ const value = obj[key];
21
+ if (value === null) {
22
+ delete obj[key];
23
+ }
24
+ else if (typeof value === "object") {
25
+ removeEmptyAndNullProperties(value);
26
+ }
27
+ });
28
+ return obj;
29
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "defect_formation_energy",
3
+ "units": "eV",
4
+ "value": 3.5
5
+ }
@@ -59,6 +59,12 @@ formation_energy:
59
59
  schemaId: properties-directory/scalar/formation-energy
60
60
  isResult: true
61
61
 
62
+ defect_formation_energy:
63
+ defaults:
64
+ units: eV
65
+ schemaId: properties-directory/scalar/defect-formation-energy
66
+ isResult: true
67
+
62
68
  total_force:
63
69
  defaults:
64
70
  units: eV/angstrom
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mat3ra/esse",
3
- "version": "2026.7.14-0",
3
+ "version": "2026.8.13-0",
4
4
  "description": "Mat3ra's Excellent Source of Schemas and Examples (ESSE) for Digital Materials R&D",
5
5
  "scripts": {
6
6
  "transpile": "tsc -p tsconfig-transpile.json",
@@ -39,10 +39,6 @@
39
39
  "description": "File information if material was exported from POSCAR, XYZ or UPF file.",
40
40
  "$ref": "../system/file_source.json"
41
41
  },
42
- "scaledHash": {
43
- "description": "Hash string for a scaled structure with lattice vector a set to 1 (eg. for materials under pressure).",
44
- "type": "string"
45
- },
46
42
  "icsdId": {
47
43
  "description": "Corresponding ICSD id of the material",
48
44
  "type": "integer"
@@ -0,0 +1,18 @@
1
+ {
2
+ "$id": "material-enhanced",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "material enhanced schema",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "material.json"
9
+ },
10
+ {
11
+ "properties": {
12
+ "basis": {
13
+ "$ref": "properties_directory/structural/basis_constrained.json"
14
+ }
15
+ }
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$id": "material-enhanced-hashed",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "material enhanced hashed schema",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "material_enhanced.json"
9
+ },
10
+ {
11
+ "$ref": "material_hashed.json"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$id": "material-hashed",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "material hashed schema",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "material.json"
9
+ },
10
+ {
11
+ "$ref": "system/hashed.json"
12
+ },
13
+ {
14
+ "properties": {
15
+ "scaledHash": {
16
+ "description": "Hash string for a scaled structure with lattice vector a set to 1 (eg. for materials under pressure).",
17
+ "type": "string"
18
+ }
19
+ }
20
+ }
21
+ ]
22
+ }
@@ -22,6 +22,7 @@
22
22
  "ScalarPropertyEnum": {
23
23
  "type": "string",
24
24
  "enum": [
25
+ "defect_formation_energy",
25
26
  "fermi_energy",
26
27
  "formation_energy",
27
28
  "homo_energy",
@@ -0,0 +1,21 @@
1
+ {
2
+ "$id": "properties-directory/scalar/defect-formation-energy",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "Defect formation energy property schema",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "../../core/reusable/energy.json"
9
+ }
10
+ ],
11
+ "properties": {
12
+ "name": {
13
+ "enum": [
14
+ "defect_formation_energy"
15
+ ]
16
+ }
17
+ },
18
+ "required": [
19
+ "name"
20
+ ]
21
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "$id": "properties-directory/structural/basis-constrained",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "basis constrained schema",
5
+ "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "basis.json"
9
+ },
10
+ {
11
+ "properties": {
12
+ "constraints": {
13
+ "$ref": "basis/atomic_constraints.json"
14
+ }
15
+ },
16
+ "required": ["constraints"]
17
+ }
18
+ ]
19
+ }
@@ -36,6 +36,9 @@
36
36
  {
37
37
  "$ref": "../properties_directory/scalar/interfacial_energy.json"
38
38
  },
39
+ {
40
+ "$ref": "../properties_directory/scalar/defect_formation_energy.json"
41
+ },
39
42
  {
40
43
  "$ref": "../properties_directory/scalar/thermal_correction_to_energy.json"
41
44
  },
@@ -7,14 +7,9 @@
7
7
  "exabyteId": {
8
8
  "description": "Identity of the corresponding bank entity",
9
9
  "type": "string"
10
- },
11
- "hash": {
12
- "description": "Hash string which is calculated based on the meaningful fields of the entity. Used to identify equal entities.",
13
- "type": "string"
14
10
  }
15
11
  },
16
12
  "required": [
17
- "exabyteId",
18
- "hash"
13
+ "exabyteId"
19
14
  ]
20
15
  }
@@ -0,0 +1,15 @@
1
+ {
2
+ "$id": "system/hashed",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "hashed schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "hash": {
8
+ "description": "Hash string which is calculated based on the meaningful fields of the entity. Used to identify equal entities.",
9
+ "type": "string"
10
+ }
11
+ },
12
+ "required": [
13
+ "hash"
14
+ ]
15
+ }
@@ -3,30 +3,14 @@
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "status schema",
5
5
  "type": "object",
6
+ "allOf": [
7
+ {
8
+ "$ref": "status_track.json"
9
+ }
10
+ ],
6
11
  "properties": {
7
12
  "status": {
8
13
  "type": "string"
9
- },
10
- "statusTrack": {
11
- "type": "array",
12
- "items": {
13
- "type": "object",
14
- "properties": {
15
- "trackedAt": {
16
- "type": "number"
17
- },
18
- "status": {
19
- "type": "string"
20
- },
21
- "repetition": {
22
- "type": "number"
23
- }
24
- },
25
- "required": [
26
- "trackedAt",
27
- "status"
28
- ]
29
- }
30
14
  }
31
15
  }
32
16
  }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$id": "system/status-track",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "title": "status track schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "statusTrack": {
8
+ "type": "array",
9
+ "items": {
10
+ "type": "object",
11
+ "properties": {
12
+ "trackedAt": {
13
+ "type": "number"
14
+ },
15
+ "status": {
16
+ "type": "string"
17
+ },
18
+ "repetition": {
19
+ "type": "number"
20
+ }
21
+ },
22
+ "required": [
23
+ "trackedAt",
24
+ "status"
25
+ ]
26
+ }
27
+ }
28
+ }
29
+ }
@@ -14,7 +14,7 @@
14
14
  "$ref": "../../system/tags.json"
15
15
  },
16
16
  {
17
- "$ref": "../../system/status.json"
17
+ "$ref": "../../system/status_track.json"
18
18
  },
19
19
  {
20
20
  "$ref": "./mixins/base.json"
@@ -7,25 +7,6 @@
7
7
  "isDraft": {
8
8
  "type": "boolean"
9
9
  },
10
- "type": {
11
- "description": "type of the unit",
12
- "type": "string"
13
- },
14
- "name": {
15
- "description": "name of the unit. e.g. pw_scf",
16
- "type": "string"
17
- },
18
- "status": {
19
- "description": "Status of the unit.",
20
- "type": "string",
21
- "enum": [
22
- "idle",
23
- "active",
24
- "warning",
25
- "error",
26
- "finished"
27
- ]
28
- },
29
10
  "head": {
30
11
  "description": "Whether this unit is the first one to be executed.",
31
12
  "type": "boolean"
@@ -41,10 +22,20 @@
41
22
  "enableRender": {
42
23
  "description": "Whether Rupy should attempt to use Jinja templating to add context variables into the unit",
43
24
  "type": "boolean"
25
+ },
26
+ "status": {
27
+ "description": "Status of the unit.",
28
+ "type": "string",
29
+ "enum": [
30
+ "idle",
31
+ "active",
32
+ "warning",
33
+ "error",
34
+ "finished"
35
+ ]
44
36
  }
45
37
  },
46
38
  "required": [
47
- "type",
48
39
  "flowchartId"
49
40
  ]
50
41
  }
@@ -19,6 +19,17 @@ export default class JSONSchemasInterface {
19
19
  return this.schemasCache.get(schemaId);
20
20
  }
21
21
 
22
+ /**
23
+ * Like {@link getSchemaById}, but throws if the schema is not registered.
24
+ */
25
+ static getRequiredSchemaById(schemaId: string): JSONSchema {
26
+ const schema = this.getSchemaById(schemaId);
27
+ if (!schema) {
28
+ throw new Error(`ESSE schema not found: ${schemaId}`);
29
+ }
30
+ return schema;
31
+ }
32
+
22
33
  /**
23
34
  * @example <caption>Search by $id regex</caption>
24
35
  * JSONSchemasInterface.matchSchema({
@@ -5,6 +5,8 @@ import addFormats from "ajv-formats";
5
5
  import { mapObjectDeep } from "../esse/schemaUtils";
6
6
  import { AnyObject } from "../esse/types";
7
7
  import type { JSONSchema } from "../esse/utils";
8
+ import addJsonSchemaToTypescriptKeywords from "./ajvKeywords/jsonSchemaToTypescriptKeywords";
9
+ import { removeEmptyAndNullProperties } from "./removeEmptyAndNullProperties";
8
10
 
9
11
  function addAdditionalPropertiesToSchema(schema: JSONSchema, additionalProperties = false) {
10
12
  return mapObjectDeep(schema, (object) => {
@@ -54,11 +56,18 @@ const ajvValidatorAndCleanerWithCoercingTypesNoDefaults = new Ajv({
54
56
  useDefaults: false,
55
57
  });
56
58
 
57
- addFormats(ajvValidator);
58
- addFormats(ajvValidatorAndCleaner);
59
- addFormats(ajvValidatorAndCleanerNoDefaults);
60
- addFormats(ajvValidatorAndCleanerWithCoercingTypes);
61
- addFormats(ajvValidatorAndCleanerWithCoercingTypesNoDefaults);
59
+ const ajvInstances = [
60
+ ajvValidator,
61
+ ajvValidatorAndCleaner,
62
+ ajvValidatorAndCleanerNoDefaults,
63
+ ajvValidatorAndCleanerWithCoercingTypes,
64
+ ajvValidatorAndCleanerWithCoercingTypesNoDefaults,
65
+ ];
66
+
67
+ ajvInstances.forEach((instance) => {
68
+ addFormats(instance);
69
+ addJsonSchemaToTypescriptKeywords(instance);
70
+ });
62
71
 
63
72
  interface AjvInstanceOptions {
64
73
  clean: boolean;
@@ -123,16 +132,18 @@ export function validate(data: AnyObject, jsonSchema: SchemaObject) {
123
132
  }
124
133
 
125
134
  /**
126
- * Validates and clean a given example against the schema
127
- * @param example example to validate.
128
- * @param schema schema to validate the example with.
129
- * @returns whether example is valid.
135
+ * Validates and cleans data against the schema.
136
+ * Drops null properties first (empty strings kept for entity placeholders), then AJV removeAdditional.
137
+ * @param data data to validate (mutated in place).
138
+ * @param jsonSchema schema to validate the data with.
139
+ * @returns whether data is valid.
130
140
  */
131
141
  export function validateAndClean(
132
142
  data: AnyObject,
133
143
  jsonSchema: SchemaObject,
134
144
  { coerceTypes = false, useDefaults = true } = {},
135
145
  ) {
146
+ removeEmptyAndNullProperties(data);
136
147
  const validator = getValidator(jsonSchema, { clean: true, coerceTypes, useDefaults });
137
148
  const isValid = validator(data);
138
149
 
@@ -141,3 +152,5 @@ export function validateAndClean(
141
152
  errors: validator.errors,
142
153
  };
143
154
  }
155
+
156
+ export { removeEmptyAndNullProperties } from "./removeEmptyAndNullProperties";
@@ -0,0 +1,22 @@
1
+ import type Ajv from "ajv";
2
+
3
+ /**
4
+ * Schemas include json-schema-to-typescript hints (`tsType`, `tsEnumNames`, …).
5
+ * Ajv strict mode rejects unknown keywords; register them as no-ops so the same schemas work for
6
+ * runtime validation.
7
+ */
8
+ export default function addJsonSchemaToTypescriptKeywords(ajv: Ajv): void {
9
+ const validateNoop = (): boolean => true;
10
+
11
+ ajv.addKeyword({
12
+ keyword: "tsType",
13
+ validate: validateNoop,
14
+ errors: false,
15
+ });
16
+
17
+ ajv.addKeyword({
18
+ keyword: "tsEnumNames",
19
+ validate: validateNoop,
20
+ errors: false,
21
+ });
22
+ }
@@ -0,0 +1,32 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
+ export type AnyObject = Record<string, any>;
3
+
4
+ /**
5
+ * Recursively removes null properties from an object.
6
+ * Empty strings are preserved (entity schemas use "" as intentional placeholders, e.g. flowchart links).
7
+ * Nested objects are cleaned in place; array elements are walked but not removed.
8
+ * @param obj The object to clean
9
+ * @returns The cleaned object (mutates the original)
10
+ */
11
+ export function removeEmptyAndNullProperties(obj: AnyObject): AnyObject {
12
+ if (typeof obj !== "object" || obj === null) {
13
+ return obj;
14
+ }
15
+
16
+ if (Array.isArray(obj)) {
17
+ obj.forEach((item) => removeEmptyAndNullProperties(item));
18
+ return obj;
19
+ }
20
+
21
+ Object.keys(obj).forEach((key) => {
22
+ const value = obj[key];
23
+
24
+ if (value === null) {
25
+ delete obj[key];
26
+ } else if (typeof value === "object") {
27
+ removeEmptyAndNullProperties(value);
28
+ }
29
+ });
30
+
31
+ return obj;
32
+ }