11import _ from 'lodash' ;
22import axios from "axios" ;
3+ import axiosRetry from 'axios-retry' ;
34import * as traverse from "traverse" ;
45import * as FileSaver from "file-saver" ;
56import moment from "moment" ;
@@ -9,7 +10,10 @@ import * as actionTypes from "../actions/actionTypes";
910import * as settingsAction from "../actions/settingsAction" ;
1011import * as configuration from "./configuration" ;
1112
13+ axiosRetry ( axios , { retries : 10 } ) ;
14+
1215const timeout = ms => new Promise ( res => setTimeout ( res , ms ) ) ;
16+ const mergeCustomizer = ( obj , src ) => _ . isArray ( obj ) ? obj . concat ( src ) : src ;
1317
1418export let Extractor = ( function ( ) {
1519 let instance ;
@@ -50,29 +54,32 @@ ExtractorClass.prototype.initialFetchAndRetrieve = async function (elements) {
5054} ;
5155
5256ExtractorClass . prototype . fetchAndRetrieve = async function ( json ) {
53- for ( const type in json ) {
54- if ( Array . isArray ( json [ type ] ) ) {
55- let elements = json [ type ] . filter ( e => e . id !== undefined && e . code !== 'default' ) ;
56- for ( const element of elements ) {
57- // Insert on the metadata map
58- this . metadataMap . set ( element . id , { ...element , type} ) ;
59-
60- if ( this . debug ) console . log ( 'fetchAndRetrieve: Parsing ' + element . id ) ;
61-
62- // Traverse references and call recursion
63- let references = await this . recursiveParse ( element , this . d2 . models [ type ] . name ) ;
64- let newJson = await this . parseElements ( references ) ;
65- await this . fetchAndRetrieve ( newJson ) ;
66- }
57+ const metadataTypes = _ . keys ( json ) . filter ( type => _ . isArray ( json [ type ] ) ) ;
58+ for ( const metadataType of metadataTypes ) {
59+ let references = [ ] ;
60+ let elements = json [ metadataType ] . filter ( e => e . id !== undefined ) ;
61+ if ( this . debug ) console . log ( 'fetchAndRetrieve: Parsing ' + elements . map ( e => e . id ) ) ;
62+
63+ for ( const element of elements ) {
64+ // Insert on the metadata map
65+ this . metadataMap . set ( element . id , { metadataType, ...element } ) ;
66+
67+ // Traverse and store references
68+ const innerReferences = await this . recursiveParse ( element , this . d2 . models [ metadataType ] . name ) ;
69+ references . push ( ...innerReferences ) ;
6770 }
71+
72+ // Call recursion
73+ const newJson = await this . parseElements ( references ) ;
74+ await this . fetchAndRetrieve ( newJson ) ;
6875 }
6976} ;
7077
7178ExtractorClass . prototype . recursiveParse = async function ( element , type ) {
7279 let context = this ;
7380 let references = [ ] ;
7481 traverse ( element ) . forEach ( function ( item ) {
75- if ( this . isLeaf && this . key === 'id' && item !== '' ) {
82+ if ( this . isLeaf && this . key === 'id' && isValidUid ( item ) ) {
7683 let parent = this . parent ;
7784 while ( parent . level > 1 && context . d2 . models [ parent . key ] === undefined ) parent = parent . parent ;
7885 if ( parent . key !== undefined ) {
@@ -92,12 +99,13 @@ ExtractorClass.prototype.parseElements = async function (elementsArray) {
9299 let promises = [ ] ;
93100 for ( let i = 0 ; i < elements . length ; i += 100 ) {
94101 let requestUrl = this . d2 . Api . getApi ( ) . baseUrl +
95- '/metadata.json?fields=:all&filter=id:in:[' + elements . slice ( i , i + 100 ) . toString ( ) + ']' ;
102+ '/metadata.json?fields=:all&defaults=EXCLUDE& filter=id:in:[' + elements . slice ( i , i + 100 ) . toString ( ) + ']' ;
96103 if ( this . debug ) console . log ( 'parseElements: ' + requestUrl ) ;
97104 promises . push ( axios . get ( requestUrl ) ) ;
98105 }
99106 let result = await Promise . all ( promises ) ;
100- return _ . merge ( { } , ...result . map ( result => result . data ) ) ;
107+ const data = result . map ( result => result . data ) ;
108+ return _ . mergeWith ( { } , ...data , mergeCustomizer ) ;
101109} ;
102110
103111ExtractorClass . prototype . handleCreatePackage = async function ( elements , dependencies ) {
@@ -121,7 +129,7 @@ ExtractorClass.prototype.createPackage = async function (elements, dependencies)
121129 for ( const id of elementSet ) {
122130 if ( this . metadataMap . has ( id ) ) {
123131 let element = this . metadataMap . get ( id ) ;
124- let elementType = this . d2 . models [ element . type ] . plural ;
132+ let elementType = this . d2 . models [ element . metadataType ] . plural ;
125133 if ( resultObject [ elementType ] === undefined ) resultObject [ elementType ] = [ ] ;
126134 resultObject [ elementType ] . push ( cleanJson ( element ) ) ;
127135 } else if ( this . debug ) {
@@ -168,6 +176,7 @@ function cleanJson(json) {
168176 if ( store . getState ( ) . settings [ actionTypes . SETTINGS_USER_CLEAN_UP ] === settingsAction . USER_CLEAN_UP_REMOVE_OPTION ) {
169177 traverse ( result ) . forEach ( function ( item ) {
170178 if ( this . key === 'user' ) this . update ( { } ) ;
179+ if ( this . key === 'users' ) this . update ( [ ] ) ;
171180 if ( this . key === 'userGroupAccesses' ) this . update ( [ ] ) ;
172181 if ( this . key === 'userAccesses' ) this . update ( [ ] ) ;
173182 if ( this . key === 'lastUpdatedBy' ) this . update ( { } ) ;
@@ -179,4 +188,9 @@ function cleanJson(json) {
179188 } ) ;
180189 }
181190 return result ;
191+ }
192+
193+ function isValidUid ( code ) {
194+ const CODE_PATTERN = / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 ] { 10 } $ / ;
195+ return code !== null && CODE_PATTERN . test ( code ) ;
182196}
0 commit comments