-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support decomposed components across multiple directories (#224)
- Loading branch information
Showing
26 changed files
with
762 additions
and
603 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* Copyright (c) 2020, salesforce.com, inc. | ||
* All rights reserved. | ||
* Licensed under the BSD 3-Clause license. | ||
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
import { WriteInfo, WriterFormat } from './types'; | ||
import { SourceComponent } from '../metadata-registry'; | ||
import { join } from 'path'; | ||
import { JsToXml } from './streams'; | ||
import { MetadataComponent } from '../common'; | ||
import { JsonArray, JsonMap } from '@salesforce/ts-types'; | ||
import { ComponentSet } from '../collections'; | ||
|
||
abstract class ConvertTransactionFinalizer<T> { | ||
protected abstract _state: T; | ||
|
||
public setState(props: (state: T) => void): void { | ||
props(this._state); | ||
} | ||
|
||
get state(): T { | ||
return this._state; | ||
} | ||
|
||
public abstract finalize(): Promise<WriterFormat[]>; | ||
} | ||
|
||
export interface RecompositionState { | ||
[componentKey: string]: { | ||
/** | ||
* Parent component that children are rolled up into | ||
*/ | ||
component?: SourceComponent; | ||
/** | ||
* Children to be rolled up into the parent file | ||
*/ | ||
children?: ComponentSet; | ||
}; | ||
} | ||
|
||
/** | ||
* Merges child components that share the same parent in the conversion pipeline | ||
* into a single file. | ||
*/ | ||
class RecompositionFinalizer extends ConvertTransactionFinalizer<RecompositionState> { | ||
protected _state: RecompositionState = {}; | ||
|
||
public async finalize(): Promise<WriterFormat[]> { | ||
const writerData: WriterFormat[] = []; | ||
|
||
for (const { component: parent, children } of Object.values(this.state)) { | ||
const baseObject: JsonMap = await parent.parseXml(); | ||
const recomposedXmlObj = await this.recompose(children, baseObject); | ||
writerData.push({ | ||
component: parent, | ||
writeInfos: [ | ||
{ | ||
source: new JsToXml(recomposedXmlObj), | ||
output: join(parent.type.directoryName, `${parent.fullName}.${parent.type.suffix}`), | ||
}, | ||
], | ||
}); | ||
} | ||
|
||
return writerData; | ||
} | ||
|
||
private async recompose(children: ComponentSet, baseXmlObj: any): Promise<JsonMap> { | ||
for (const child of children) { | ||
const { directoryName: groupNode } = child.type; | ||
const { name: parentName } = child.parent.type; | ||
const xmlObj = await (child as SourceComponent).parseXml(); | ||
const childContents = xmlObj[child.type.name]; | ||
|
||
if (!baseXmlObj[parentName][groupNode]) { | ||
baseXmlObj[parentName][groupNode] = []; | ||
} | ||
(baseXmlObj[parentName][groupNode] as JsonArray).push(childContents); | ||
} | ||
return baseXmlObj; | ||
} | ||
} | ||
|
||
export interface DecompositionState { | ||
[componentKey: string]: { | ||
foundMerge?: boolean; | ||
writeInfo?: WriteInfo; | ||
origin?: MetadataComponent; | ||
}; | ||
} | ||
|
||
/** | ||
* Creates write infos for any children that haven't been written yet. Children may | ||
* delay being written in order to find potential existing children to merge | ||
* with in the conversion pipeline. | ||
*/ | ||
class DecompositionFinalizer extends ConvertTransactionFinalizer<DecompositionState> { | ||
protected _state: DecompositionState = {}; | ||
|
||
public async finalize(): Promise<WriterFormat[]> { | ||
const writerData: WriterFormat[] = []; | ||
|
||
for (const toDecompose of Object.values(this._state)) { | ||
if (!toDecompose.foundMerge) { | ||
writerData.push({ | ||
component: toDecompose.origin.parent ?? toDecompose.origin, | ||
writeInfos: [toDecompose.writeInfo], | ||
}); | ||
} | ||
} | ||
|
||
return writerData; | ||
} | ||
} | ||
|
||
/** | ||
* A state manager over the course of a single metadata conversion call. | ||
*/ | ||
export class ConvertContext { | ||
public readonly decomposition = new DecompositionFinalizer(); | ||
public readonly recomposition = new RecompositionFinalizer(); | ||
|
||
public async *executeFinalizers(): AsyncIterable<WriterFormat[]> { | ||
for (const member of Object.values(this)) { | ||
if (member instanceof ConvertTransactionFinalizer) { | ||
yield member.finalize(); | ||
} | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.