@hestia-earth/data-validation 0.41.11 → 0.41.12

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.
@@ -57,7 +57,7 @@ declare const urlConfig: (baseUrl?: string) => IUrlConfig;
57
57
  * primary entry point). They are kept structurally compatible on purpose.
58
58
  */
59
59
  type validationErrorLevel = 'error' | 'warning';
60
- type validationErrorParam = 'missingProperty' | 'type' | 'term' | 'termType' | 'termIds' | 'model' | 'product' | 'range' | 'node' | 'allowedValues' | 'allowedValue' | 'additionalProperty' | 'expected' | 'default' | 'current' | 'percentage' | 'keys' | 'threshold' | 'outliers' | 'country' | 'min' | 'max' | 'mu' | 'sd' | 'defaultSource' | 'source' | 'group' | 'message' | 'distance' | 'siteType' | 'products' | 'units' | 'duplicatedIndexes' | 'invalidCoordinates' | 'ids' | 'limit' | 'delta';
60
+ type validationErrorParam = 'missingProperty' | 'type' | 'term' | 'termType' | 'termIds' | 'model' | 'product' | 'range' | 'node' | 'allowedValues' | 'allowedValue' | 'additionalProperty' | 'expected' | 'default' | 'current' | 'percentage' | 'keys' | 'threshold' | 'outliers' | 'country' | 'min' | 'max' | 'mu' | 'sd' | 'defaultSource' | 'source' | 'group' | 'message' | 'distance' | 'siteType' | 'products' | 'units' | 'duplicatedIndexes' | 'invalidCoordinates' | 'ids' | 'limit' | 'delta' | 'newlyCovered' | 'recommended' | 'missing';
61
61
  type validationErrorKeyword = 'required' | 'type' | 'if' | 'then' | 'not';
62
62
  interface ICustomValidationRules {
63
63
  const?: any;
@@ -57,7 +57,7 @@ declare const urlConfig: (baseUrl?: string) => IUrlConfig;
57
57
  * primary entry point). They are kept structurally compatible on purpose.
58
58
  */
59
59
  type validationErrorLevel = 'error' | 'warning';
60
- type validationErrorParam = 'missingProperty' | 'type' | 'term' | 'termType' | 'termIds' | 'model' | 'product' | 'range' | 'node' | 'allowedValues' | 'allowedValue' | 'additionalProperty' | 'expected' | 'default' | 'current' | 'percentage' | 'keys' | 'threshold' | 'outliers' | 'country' | 'min' | 'max' | 'mu' | 'sd' | 'defaultSource' | 'source' | 'group' | 'message' | 'distance' | 'siteType' | 'products' | 'units' | 'duplicatedIndexes' | 'invalidCoordinates' | 'ids' | 'limit' | 'delta';
60
+ type validationErrorParam = 'missingProperty' | 'type' | 'term' | 'termType' | 'termIds' | 'model' | 'product' | 'range' | 'node' | 'allowedValues' | 'allowedValue' | 'additionalProperty' | 'expected' | 'default' | 'current' | 'percentage' | 'keys' | 'threshold' | 'outliers' | 'country' | 'min' | 'max' | 'mu' | 'sd' | 'defaultSource' | 'source' | 'group' | 'message' | 'distance' | 'siteType' | 'products' | 'units' | 'duplicatedIndexes' | 'invalidCoordinates' | 'ids' | 'limit' | 'delta' | 'newlyCovered' | 'recommended' | 'missing';
61
61
  type validationErrorKeyword = 'required' | 'type' | 'if' | 'then' | 'not';
62
62
  interface ICustomValidationRules {
63
63
  const?: any;
@@ -712,6 +712,11 @@ var validations = [
712
712
  level: "error",
713
713
  message: "must have a value or a distance if complete"
714
714
  },
715
+ {
716
+ function: "validate_coverage",
717
+ level: "warning",
718
+ message: "can not calculate all emissions"
719
+ },
715
720
  {
716
721
  function: "validate_has_termType",
717
722
  level: "warning",
@@ -1204,6 +1209,30 @@ var createErrorFormatter = ({ renderer: r, urls }) => {
1204
1209
  const listAsCode = (values) => (values != null ? values : []).map((value) => r.code(value)).join(", ");
1205
1210
  const joinWithAnd = (values) => values.length > 1 ? `${values.slice(0, -1).join(", ")} and ${values[values.length - 1]}` : values.join("");
1206
1211
  const listAsCodeWithAnd = (values) => joinWithAnd((values != null ? values : []).map((value) => r.code(value)));
1212
+ const joinWithOr = (values) => values.length > 1 ? `${values.slice(0, -1).join(", ")} or ${values[values.length - 1]}` : values.join("");
1213
+ const pluralizeCount = (count, word) => `${count} ${pluralize(word, count)}`;
1214
+ const termNames = (terms = [], max = 3) => [
1215
+ ...terms.slice(0, max).map(({ "@id": id, name }) => termLink({ id, name })),
1216
+ ...terms.length > max ? [`${terms.length - max} more`] : []
1217
+ ].reduce((text, name, index, names) => index === 0 ? name : `${text}; ${index === names.length - 1 ? "and " : ""}${name}`, "");
1218
+ const coverageItems = {
1219
+ properties: ({ expected, term, blankNodeType }) => `add ${listAsCodeWithAnd(expected)} to the ${code(term == null ? void 0 : term["@id"])} ${blankNodeType}`,
1220
+ cropResidue: () => `add the fate of the crop residue: a ${code(schema.TermTermType.cropResidueManagement)} Practice, or the crop residue Products`,
1221
+ completeness: ({ paths }) => `set ${listAsCodeWithAnd(paths)} to ${code(true)}, if all the ${joinWithAnd(
1222
+ paths.map((path) => path.split(".")[1])
1223
+ )} data is recorded`,
1224
+ pastureGrass: () => `add a ${code("pastureGrass")} Practice, with the type of grass as its key`,
1225
+ system: ({ expected }) => `add an animal production system Practice${(expected == null ? void 0 : expected.length) ? `: ${joinWithOr(expected.map(code))}` : ""}`,
1226
+ milkYield: ({ expected }) => `add a milk yield Practice to the Animals: ${joinWithOr(expected.map(code))}`,
1227
+ animals: () => "add the herd composition, as Animals",
1228
+ data: ({ path, expected }) => path === "or" ? `add one of ${joinWithOr(expected.map((fields) => listAsCodeWithAnd(fields)))}` : (expected == null ? void 0 : expected.length) && expected.join() !== path.split(".").pop() ? `add ${joinWithOr(expected.map(code))} to ${code(path)}` : `add ${code(path)}`
1229
+ };
1230
+ const coverageItem = (item) => {
1231
+ var _a, _b;
1232
+ return `\u2022 ${(_b = (_a = coverageItems[item.type]) == null ? void 0 : _a.call(coverageItems, item)) != null ? _b : code(item.path)}${item.nodeType && item.nodeType !== schema.SchemaType.Cycle ? ` (on the ${item.nodeType})` : ""}`;
1233
+ };
1234
+ const coverageRequirement = ({ path, expected, current, nodeType: nodeType2 }) => `${code(path)} is ${joinWithOr(expected.map(code))}${current ? ` (this ${nodeType2} has ${code(current)})` : ""}`;
1235
+ const coverageMissing = ({ requirements, terms }) => `\u2022 HESTIA only calculates them when ${joinWithAnd(requirements.map(coverageRequirement))}: ${termNames(terms)}.`;
1207
1236
  const listAsTermLinksWithAnd = (termIds) => joinWithAnd((termIds != null ? termIds : []).map((id) => termLink({ id })));
1208
1237
  const glossaryQueryLink = (query, type) => r.link(`${urls.glossaryBaseUrl()}?query=${encodeURIComponent(query)}&termType=${type}`, query);
1209
1238
  const joinValues = (values) => (values || []).filter(Boolean).map((value) => r.code(value)).join(r.inlineSeparator);
@@ -1813,7 +1842,7 @@ var createErrorFormatter = ({ renderer: r, urls }) => {
1813
1842
  schema.CycleFunctionalUnit.relative
1814
1843
  )} or change the ${schemaLink("Site#siteType", "siteType")}.`,
1815
1844
  "should specify a value when HESTIA has a default one": ({ params }) => `As you have not specified a ${code("value")}, we will assume the value is ${code(params == null ? void 0 : params.expected)}.
1816
- If this is incorrect, pelase add a value.`,
1845
+ If this is incorrect, please add a value.`,
1817
1846
  "should contain at least one management node": ({ params }) => `${(params == null ? void 0 : params.termType) ? `Does not contain information about ${code(params.termType)}.
1818
1847
  Please consider adding a history of ${code(
1819
1848
  params.termType
@@ -2038,12 +2067,36 @@ var createErrorFormatter = ({ renderer: r, urls }) => {
2038
2067
  but the calculated duration from the end date and start date provided is ${params.current}.`,
2039
2068
  "should add the term pastureGrass": () => `For Cycles with ${code("siteType=permanent pasture")} we recommend specifying the type(s) of ${code("Pasture grass")} grown.
2040
2069
  This is particularly important for ruminants and will allow for a more accurate estimate of the amount of grass grazed.`,
2041
- "should add the fields for a relative cycle": ({ params }) => {
2042
- var _a;
2043
- return `We strongly recommend setting ${(_a = params == null ? void 0 : params.expected) == null ? void 0 : _a.map((param) => code(param)).join("and")} on all other sites for any uploads with a ${code(
2044
- "relative"
2045
- )} functional unit. This will allow calculation of land occupation and land transformation.`;
2070
+ "can not calculate all emissions": ({ params }) => {
2071
+ var _a, _b, _c;
2072
+ const indicators = "GWP100, acidification and other similar indicators";
2073
+ const recommended = (_a = params == null ? void 0 : params.recommended) != null ? _a : [];
2074
+ const missing = (_b = params == null ? void 0 : params.missing) != null ? _b : [];
2075
+ const missingCount = missing.reduce(
2076
+ (count, { terms }) => count + terms.length,
2077
+ 0
2078
+ );
2079
+ const unlocked = (_c = params == null ? void 0 : params.newlyCovered) != null ? _c : [];
2080
+ const these = recommended.length === 1 ? "this" : "all of this";
2081
+ return (recommended.length ? [
2082
+ r.bold(`HESTIA cannot yet calculate all the emissions used by ${indicators} for this Cycle.`),
2083
+ "To calculate more of them:",
2084
+ ...recommended.map(coverageItem),
2085
+ unlocked.length ? `With ${these}, HESTIA could calculate ${unlocked.length} more ${pluralize("emission", unlocked.length)}, such as: ${termNames(unlocked)}.` : `With ${these}, HESTIA could calculate more of these emissions.`,
2086
+ ...missing.length ? [
2087
+ `Even then, ${pluralizeCount(missingCount, "emission")} will be missing, so the indicators using ${missingCount === 1 ? "it" : "them"} will be incomplete:`,
2088
+ ...missing.map(coverageMissing)
2089
+ ] : []
2090
+ ] : [
2091
+ r.bold(
2092
+ `With the data provided, ${pluralizeCount(missingCount, "emission")} used by ${indicators} cannot be calculated, so those indicators will be incomplete:`
2093
+ ),
2094
+ ...missing.map(coverageMissing)
2095
+ ]).join(r.lineBreak);
2046
2096
  },
2097
+ "should add the fields for a relative cycle": ({ params }) => `We strongly recommend setting ${listAsCodeWithAnd(params == null ? void 0 : params.expected)} on all other sites for any uploads with a ${code(
2098
+ "relative"
2099
+ )} functional unit. This will allow calculation of land occupation and land transformation.`,
2047
2100
  "must not be blank if complete": ({ params }) => `If completeness is set to true for ${schemaLink(
2048
2101
  `Completeness#${params.expected}`,
2049
2102
  params.expected
@@ -710,6 +710,11 @@ var validations = [
710
710
  level: "error",
711
711
  message: "must have a value or a distance if complete"
712
712
  },
713
+ {
714
+ function: "validate_coverage",
715
+ level: "warning",
716
+ message: "can not calculate all emissions"
717
+ },
713
718
  {
714
719
  function: "validate_has_termType",
715
720
  level: "warning",
@@ -1202,6 +1207,30 @@ var createErrorFormatter = ({ renderer: r, urls }) => {
1202
1207
  const listAsCode = (values) => (values != null ? values : []).map((value) => r.code(value)).join(", ");
1203
1208
  const joinWithAnd = (values) => values.length > 1 ? `${values.slice(0, -1).join(", ")} and ${values[values.length - 1]}` : values.join("");
1204
1209
  const listAsCodeWithAnd = (values) => joinWithAnd((values != null ? values : []).map((value) => r.code(value)));
1210
+ const joinWithOr = (values) => values.length > 1 ? `${values.slice(0, -1).join(", ")} or ${values[values.length - 1]}` : values.join("");
1211
+ const pluralizeCount = (count, word) => `${count} ${pluralize(word, count)}`;
1212
+ const termNames = (terms = [], max = 3) => [
1213
+ ...terms.slice(0, max).map(({ "@id": id, name }) => termLink({ id, name })),
1214
+ ...terms.length > max ? [`${terms.length - max} more`] : []
1215
+ ].reduce((text, name, index, names) => index === 0 ? name : `${text}; ${index === names.length - 1 ? "and " : ""}${name}`, "");
1216
+ const coverageItems = {
1217
+ properties: ({ expected, term, blankNodeType }) => `add ${listAsCodeWithAnd(expected)} to the ${code(term == null ? void 0 : term["@id"])} ${blankNodeType}`,
1218
+ cropResidue: () => `add the fate of the crop residue: a ${code(TermTermType.cropResidueManagement)} Practice, or the crop residue Products`,
1219
+ completeness: ({ paths }) => `set ${listAsCodeWithAnd(paths)} to ${code(true)}, if all the ${joinWithAnd(
1220
+ paths.map((path) => path.split(".")[1])
1221
+ )} data is recorded`,
1222
+ pastureGrass: () => `add a ${code("pastureGrass")} Practice, with the type of grass as its key`,
1223
+ system: ({ expected }) => `add an animal production system Practice${(expected == null ? void 0 : expected.length) ? `: ${joinWithOr(expected.map(code))}` : ""}`,
1224
+ milkYield: ({ expected }) => `add a milk yield Practice to the Animals: ${joinWithOr(expected.map(code))}`,
1225
+ animals: () => "add the herd composition, as Animals",
1226
+ data: ({ path, expected }) => path === "or" ? `add one of ${joinWithOr(expected.map((fields) => listAsCodeWithAnd(fields)))}` : (expected == null ? void 0 : expected.length) && expected.join() !== path.split(".").pop() ? `add ${joinWithOr(expected.map(code))} to ${code(path)}` : `add ${code(path)}`
1227
+ };
1228
+ const coverageItem = (item) => {
1229
+ var _a, _b;
1230
+ return `\u2022 ${(_b = (_a = coverageItems[item.type]) == null ? void 0 : _a.call(coverageItems, item)) != null ? _b : code(item.path)}${item.nodeType && item.nodeType !== SchemaType.Cycle ? ` (on the ${item.nodeType})` : ""}`;
1231
+ };
1232
+ const coverageRequirement = ({ path, expected, current, nodeType: nodeType2 }) => `${code(path)} is ${joinWithOr(expected.map(code))}${current ? ` (this ${nodeType2} has ${code(current)})` : ""}`;
1233
+ const coverageMissing = ({ requirements, terms }) => `\u2022 HESTIA only calculates them when ${joinWithAnd(requirements.map(coverageRequirement))}: ${termNames(terms)}.`;
1205
1234
  const listAsTermLinksWithAnd = (termIds) => joinWithAnd((termIds != null ? termIds : []).map((id) => termLink({ id })));
1206
1235
  const glossaryQueryLink = (query, type) => r.link(`${urls.glossaryBaseUrl()}?query=${encodeURIComponent(query)}&termType=${type}`, query);
1207
1236
  const joinValues = (values) => (values || []).filter(Boolean).map((value) => r.code(value)).join(r.inlineSeparator);
@@ -1811,7 +1840,7 @@ var createErrorFormatter = ({ renderer: r, urls }) => {
1811
1840
  CycleFunctionalUnit.relative
1812
1841
  )} or change the ${schemaLink("Site#siteType", "siteType")}.`,
1813
1842
  "should specify a value when HESTIA has a default one": ({ params }) => `As you have not specified a ${code("value")}, we will assume the value is ${code(params == null ? void 0 : params.expected)}.
1814
- If this is incorrect, pelase add a value.`,
1843
+ If this is incorrect, please add a value.`,
1815
1844
  "should contain at least one management node": ({ params }) => `${(params == null ? void 0 : params.termType) ? `Does not contain information about ${code(params.termType)}.
1816
1845
  Please consider adding a history of ${code(
1817
1846
  params.termType
@@ -2036,12 +2065,36 @@ var createErrorFormatter = ({ renderer: r, urls }) => {
2036
2065
  but the calculated duration from the end date and start date provided is ${params.current}.`,
2037
2066
  "should add the term pastureGrass": () => `For Cycles with ${code("siteType=permanent pasture")} we recommend specifying the type(s) of ${code("Pasture grass")} grown.
2038
2067
  This is particularly important for ruminants and will allow for a more accurate estimate of the amount of grass grazed.`,
2039
- "should add the fields for a relative cycle": ({ params }) => {
2040
- var _a;
2041
- return `We strongly recommend setting ${(_a = params == null ? void 0 : params.expected) == null ? void 0 : _a.map((param) => code(param)).join("and")} on all other sites for any uploads with a ${code(
2042
- "relative"
2043
- )} functional unit. This will allow calculation of land occupation and land transformation.`;
2068
+ "can not calculate all emissions": ({ params }) => {
2069
+ var _a, _b, _c;
2070
+ const indicators = "GWP100, acidification and other similar indicators";
2071
+ const recommended = (_a = params == null ? void 0 : params.recommended) != null ? _a : [];
2072
+ const missing = (_b = params == null ? void 0 : params.missing) != null ? _b : [];
2073
+ const missingCount = missing.reduce(
2074
+ (count, { terms }) => count + terms.length,
2075
+ 0
2076
+ );
2077
+ const unlocked = (_c = params == null ? void 0 : params.newlyCovered) != null ? _c : [];
2078
+ const these = recommended.length === 1 ? "this" : "all of this";
2079
+ return (recommended.length ? [
2080
+ r.bold(`HESTIA cannot yet calculate all the emissions used by ${indicators} for this Cycle.`),
2081
+ "To calculate more of them:",
2082
+ ...recommended.map(coverageItem),
2083
+ unlocked.length ? `With ${these}, HESTIA could calculate ${unlocked.length} more ${pluralize("emission", unlocked.length)}, such as: ${termNames(unlocked)}.` : `With ${these}, HESTIA could calculate more of these emissions.`,
2084
+ ...missing.length ? [
2085
+ `Even then, ${pluralizeCount(missingCount, "emission")} will be missing, so the indicators using ${missingCount === 1 ? "it" : "them"} will be incomplete:`,
2086
+ ...missing.map(coverageMissing)
2087
+ ] : []
2088
+ ] : [
2089
+ r.bold(
2090
+ `With the data provided, ${pluralizeCount(missingCount, "emission")} used by ${indicators} cannot be calculated, so those indicators will be incomplete:`
2091
+ ),
2092
+ ...missing.map(coverageMissing)
2093
+ ]).join(r.lineBreak);
2044
2094
  },
2095
+ "should add the fields for a relative cycle": ({ params }) => `We strongly recommend setting ${listAsCodeWithAnd(params == null ? void 0 : params.expected)} on all other sites for any uploads with a ${code(
2096
+ "relative"
2097
+ )} functional unit. This will allow calculation of land occupation and land transformation.`,
2045
2098
  "must not be blank if complete": ({ params }) => `If completeness is set to true for ${schemaLink(
2046
2099
  `Completeness#${params.expected}`,
2047
2100
  params.expected
package/index.js CHANGED
@@ -718,6 +718,11 @@ var validations = [
718
718
  level: "error",
719
719
  message: "must have a value or a distance if complete"
720
720
  },
721
+ {
722
+ function: "validate_coverage",
723
+ level: "warning",
724
+ message: "can not calculate all emissions"
725
+ },
721
726
  {
722
727
  function: "validate_has_termType",
723
728
  level: "warning",
package/index.mjs CHANGED
@@ -716,6 +716,11 @@ var validations = [
716
716
  level: "error",
717
717
  message: "must have a value or a distance if complete"
718
718
  },
719
+ {
720
+ function: "validate_coverage",
721
+ level: "warning",
722
+ message: "can not calculate all emissions"
723
+ },
719
724
  {
720
725
  function: "validate_has_termType",
721
726
  level: "warning",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hestia-earth/data-validation",
3
- "version": "0.41.11",
3
+ "version": "0.41.12",
4
4
  "description": "HESTIA Data Validation library",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
package/validation.json CHANGED
@@ -705,6 +705,11 @@
705
705
  "level": "error",
706
706
  "message": "must have a value or a distance if complete"
707
707
  },
708
+ {
709
+ "function": "validate_coverage",
710
+ "level": "warning",
711
+ "message": "can not calculate all emissions"
712
+ },
708
713
  {
709
714
  "function": "validate_has_termType",
710
715
  "level": "warning",