@cumulus/cmrjs 20.3.0 → 21.0.0-echo10

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.
@@ -0,0 +1,91 @@
1
+ type Echo10XmlBaseGranule = {
2
+ Granule: {
3
+ GranuleUR?: string;
4
+ DataGranule?: {
5
+ ProducerGranuleId?: string;
6
+ }
7
+ [key: string]: unknown;
8
+ };
9
+ };
10
+
11
+ function isEcho10XmlBaseGranule(obj: any): obj is Echo10XmlBaseGranule {
12
+ return typeof obj === 'object' && obj !== null
13
+ && obj.Granule?.GranuleUR !== undefined;
14
+ }
15
+
16
+ /**
17
+ * Updates an ECHO10 metadata XML object with a new GranuleUR and ProducerGranuleId.
18
+ *
19
+ * This function:
20
+ * - Validates that the input is a minimally valid ECHO10 metadata object.
21
+ * - Performs a deep clone to avoid mutating the original input.
22
+ * - Sets the new `GranuleUR` and `ProducerGranuleId` values accordingly.
23
+ *
24
+ * @param params
25
+ * @param params.xml - The parsed XML object (e.g., from xml2js) representing ECHO10 metadata.
26
+ * @param params.granuleUr - The new GranuleUR value to apply to the metadata.
27
+ * @param params.producerGranuleId - The original identifier value to be set as ProducerGranuleId.
28
+ * @returns A deep-cloned and updated copy of the original ECHO10 metadata object.
29
+ * @throws If the input object does not conform to the expected ECHO10 structure.
30
+ */
31
+ export function updateEcho10XMLGranuleUrAndGranuleIdentifier({
32
+ xml, // The parsed XML object (e.g., from xml2js)
33
+ granuleUr, // The new GranuleUR value
34
+ producerGranuleId, // The original identifier to store
35
+ }: {
36
+ xml: unknown;
37
+ granuleUr: string;
38
+ producerGranuleId: string;
39
+ }): any {
40
+ if (!isEcho10XmlBaseGranule(xml)) {
41
+ throw new Error('Invalid XML input - expected an object with GranuleUR');
42
+ }
43
+
44
+ const moddedXml = structuredClone(xml);
45
+
46
+ moddedXml.Granule ??= {};
47
+ moddedXml.Granule.GranuleUR = granuleUr;
48
+
49
+ moddedXml.Granule.DataGranule ??= {};
50
+
51
+ const dataGranule = moddedXml.Granule.DataGranule as any;
52
+ const orderedDataGranule = new Map<string, any>();
53
+
54
+ // ECHO10 DataGranule element order as defined in the XSD schema
55
+ // https://git.earthdata.nasa.gov/projects/EMFD/repos/echo-schemas/browse/schemas/10.0/Granule.xsd
56
+ const echo10DataGranuleOrder = [
57
+ 'DataGranuleSizeInBytes',
58
+ 'SizeMBDataGranule',
59
+ 'Checksum',
60
+ 'ReprocessingPlanned',
61
+ 'ReprocessingActual',
62
+ 'ProducerGranuleId',
63
+ 'DayNightFlag',
64
+ 'ProductionDateTime',
65
+ 'LocalVersionId',
66
+ 'AdditionalFile',
67
+ ];
68
+
69
+ const existingKeys = Object.keys(dataGranule);
70
+ const unexpectedKeys = existingKeys.filter((key) => !echo10DataGranuleOrder.includes(key));
71
+
72
+ if (unexpectedKeys.length > 0) {
73
+ throw new Error(
74
+ `Unexpected DataGranule key(s) found: ${unexpectedKeys.join(', ')}. `
75
+ + `Valid keys are: ${echo10DataGranuleOrder.join(', ')}. `
76
+ + `GranuleUR: ${moddedXml.Granule.GranuleUR}`
77
+ );
78
+ }
79
+
80
+ echo10DataGranuleOrder.forEach((key) => {
81
+ if (key === 'ProducerGranuleId') {
82
+ orderedDataGranule.set(key, producerGranuleId);
83
+ } else if (dataGranule[key] !== undefined) {
84
+ orderedDataGranule.set(key, dataGranule[key]);
85
+ }
86
+ });
87
+
88
+ moddedXml.Granule.DataGranule = orderedDataGranule as any;
89
+
90
+ return moddedXml;
91
+ }
@@ -0,0 +1,71 @@
1
+ // Implementation against https://git.earthdata.nasa.gov/projects/EMFD/repos/unified-metadata-model/browse/granule/v1.6.6/umm-g-json-schema.json
2
+ type UMMGGranule = {
3
+ GranuleUR: string;
4
+ DataGranule?: {
5
+ Identifiers?: {
6
+ Identifier: string;
7
+ IdentifierType: string;
8
+ IdentifierName?: string;
9
+ }[];
10
+ [key: string]: any;
11
+ };
12
+ [key: string]: unknown;
13
+ };
14
+
15
+ function isUMMGGranule(obj: any): obj is UMMGGranule {
16
+ return typeof obj === 'object' && obj !== null && typeof obj.GranuleUR === 'string';
17
+ }
18
+
19
+ /**
20
+ * Updates a UMM-G metadata object with a new GranuleUR and ProducerGranuleId.
21
+ *
22
+ * This function:
23
+ * - Validates that the input is a valid UMM-G granule metadata object.
24
+ * - Performs a deep clone to preserve the original input.
25
+ * - Sets the GranuleUR to the specified value.
26
+ * - Ensures that the DataGranule.Identifiers array exists.
27
+ * - Adds or updates an entry of type "ProducerGranuleId" with the provided identifier.
28
+ *
29
+ * @param metadataObject - The parsed UMM-G metadata object to be modified.
30
+ * @param granuleUr - The new GranuleUR value to assign.
31
+ * @param producerGranuleId - The ProducerGranuleId to store in the Identifiers list.
32
+ * @returns A deep-cloned and updated copy of the UMM-G metadata object.
33
+ * @throws If the input does not match the expected UMM-G granule structure.
34
+ */
35
+
36
+ export function updateUMMGGranuleURAndGranuleIdentifier({
37
+ metadataObject,
38
+ granuleUr,
39
+ producerGranuleId,
40
+ }: {
41
+ metadataObject: unknown;
42
+ granuleUr: string;
43
+ producerGranuleId: string;
44
+ }): UMMGGranule {
45
+ if (!isUMMGGranule(metadataObject)) {
46
+ throw new Error('Invalid UMM-G JSON metadata');
47
+ }
48
+
49
+ const moddedJson = structuredClone(metadataObject);
50
+
51
+ moddedJson.GranuleUR = granuleUr;
52
+ moddedJson.DataGranule ??= {};
53
+ moddedJson.DataGranule.Identifiers ??= [];
54
+
55
+ const producerIndex = moddedJson.DataGranule.Identifiers.findIndex(
56
+ (id) => id.IdentifierType === 'ProducerGranuleId'
57
+ );
58
+
59
+ const producerGranuleIdIdentifier = {
60
+ Identifier: producerGranuleId,
61
+ IdentifierType: 'ProducerGranuleId',
62
+ };
63
+
64
+ if (producerIndex !== -1) {
65
+ moddedJson.DataGranule.Identifiers[producerIndex] = producerGranuleIdIdentifier;
66
+ } else {
67
+ moddedJson.DataGranule.Identifiers.push(producerGranuleIdIdentifier);
68
+ }
69
+
70
+ return moddedJson;
71
+ }