Skip to content

Commit

Permalink
fix: handling folders during various operations (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryan Powell authored and lcampos committed Dec 3, 2020
1 parent 5176b98 commit 7525a73
Show file tree
Hide file tree
Showing 12 changed files with 269 additions and 135 deletions.
5 changes: 5 additions & 0 deletions scripts/update-registry/typeOverride.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
{
"emailservicesfunction": {
"suffix": null
},
"emailtemplatefolder": {
"id": "emailfolder",
"name": "EmailFolder",
"suffix": "emailFolder"
}
}
25 changes: 17 additions & 8 deletions scripts/update-registry/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,40 @@ function update(registry, describeResult) {
const typeOverrides = JSON.parse(fs.readFileSync(path.join(__dirname, 'typeOverride.json')))

for (const object of describeResult.metadataObjects) {
const typeId = object.xmlName.toLowerCase();
const { xmlName: name, suffix, directoryName, inFolder, childXmlNames } = object;
let typeId = object.xmlName.toLowerCase();
const { xmlName: name, suffix, directoryName, inFolder, childXmlNames, folderContentType } = object;

// If it's a type with folders, process the folder type later
if (inFolder === 'true') {
let folderTypeId;
if (inFolder === 'true' || inFolder === true) {
describeResult.metadataObjects.push({
xmlName: `${name}Folder`,
suffix: `${typeId}Folder`,
directoryName,
inFolder: false,
folderContentType: typeId
});
folderTypeId = `${typeId}folder`
}

let type = registry.types[typeId] || {
const generatedType = {
id: typeId,
name,
suffix,
directoryName,
inFolder: inFolder === 'true' || inFolder === true,
strictDirectoryName: !suffix
strictDirectoryName: !suffix,
folderType: folderTypeId,
folderContentType
};
let type = deepmerge(generatedType, registry.types[typeId] || {})

// apply type override if one exists
if (typeOverrides[typeId]) {
type = deepmerge(type, typeOverrides[typeId])
const typeOverride = typeOverrides[typeId]
if (typeOverride) {
type = deepmerge(type, typeOverride)
if (typeOverride.id) {
typeId = typeOverride.id
}
}

if (childXmlNames) {
Expand Down
35 changes: 31 additions & 4 deletions src/collections/workingSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class WorkingSet implements MetadataSet, Iterable<MetadataComponent> {
* with the `resolve` option to resolve source files for the components.
*
* ```
* WorkingSet.fromManifest('/path/to/package.xml', {
* WorkingSet.fromManifestFile('/path/to/package.xml', {
* resolve: '/path/to/force-app'
* });
* ```
Expand Down Expand Up @@ -128,9 +128,14 @@ export class WorkingSet implements MetadataSet, Iterable<MetadataComponent> {
for (const { name: typeName, members } of typeMembers) {
const fullNames = Array.isArray(members) ? members : [members];
for (const fullName of fullNames) {
let type = registry.getTypeByName(typeName);
// if there is no delimeter and it's a type in folders, infer folder component
if (type.folderType && !fullName.includes('/')) {
type = registry.getTypeByName(type.folderType);
}
yield {
fullName,
type: registry.getTypeByName(typeName),
type,
};
}
}
Expand Down Expand Up @@ -209,12 +214,34 @@ export class WorkingSet implements MetadataSet, Iterable<MetadataComponent> {
*/
public getObject(): PackageManifestObject {
const typeMembers: PackageTypeMembers[] = [];
const folderMembers = new Map<string, string[]>();

for (const [typeName, components] of this.components.entries()) {
const members: string[] = [];
let members: string[] = [];
const type = this.registry.getTypeByName(typeName);

// build folder related members separately to combine folder types and types in folders into one
const isFolderRelatedType = type.folderType || type.folderContentType;
if (isFolderRelatedType) {
const { name: contentTypeName } = type.folderContentType
? this.registry.getTypeByName(type.folderContentType)
: type;
if (!folderMembers.has(contentTypeName)) {
folderMembers.set(contentTypeName, []);
}
members = folderMembers.get(contentTypeName);
}

for (const { fullName } of components.values()) {
members.push(fullName);
}

if (!isFolderRelatedType) {
typeMembers.push({ members, name: typeName });
}
}

for (const [typeName, members] of folderMembers.entries()) {
typeMembers.push({ members, name: typeName });
}

Expand Down Expand Up @@ -343,6 +370,6 @@ export class WorkingSet implements MetadataSet, Iterable<MetadataComponent> {
if (!this.components.has(type.name)) {
this.components.set(type.name, new ComponentSet<MetadataComponent>());
}
this.components.get(type.name).add(Object.freeze(component));
this.components.get(type.name).add(component);
}
}
9 changes: 9 additions & 0 deletions src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type MetadataType = {
* Whether or not components are stored in folders.
*
* __Examples:__ Reports, Dashboards, Documents, EmailTemplates
* @deprecated use `folderType` to get the related folder type, if one exists
*/
inFolder?: boolean;
/**
Expand All @@ -37,6 +38,14 @@ export type MetadataType = {
* Whether or not components are required to reside in a folder named after the type's directoryName.
*/
strictDirectoryName?: boolean;
/**
* If the type is a folder type (container for components), the id of the type it is a container for.
*/
folderContentType?: string;
/**
* If the type is contained in folders, the id of the type that contains it.
*/
folderType?: string;
/**
* Type definitions for child types, if the type has any.
*
Expand Down
11 changes: 6 additions & 5 deletions src/convert/metadataConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
DirectoryConfig,
ZipConfig,
} from './types';
import { ManifestGenerator, RegistryAccess, SourceComponent } from '../metadata-registry';
import { RegistryAccess, SourceComponent } from '../metadata-registry';
import { promises } from 'fs';
import { dirname, join } from 'path';
import { ensureDirectoryExists } from '../utils/fileSystemHandler';
Expand All @@ -25,7 +25,7 @@ import {
} from './streams';
import { ConversionError, LibraryError } from '../errors';
import { SourcePath } from '../common';
import { ComponentSet } from '../collections';
import { ComponentSet, WorkingSet } from '../collections';

export class MetadataConverter {
public static readonly PACKAGE_XML_FILE = 'package.xml';
Expand All @@ -50,9 +50,10 @@ export class MetadataConverter {
output: ConvertOutputConfig
): Promise<ConvertResult> {
try {
// TODO: evaluate if a builder pattern for manifest creation is more efficient here
const manifestGenerator = new ManifestGenerator(undefined, this.registry);
const manifestContents = manifestGenerator.createManifest(components);
// it's possible the components came from a working set, so this may be redundant in some cases...
const manifestContents = WorkingSet.fromComponents(components, {
registry: this.registry,
}).getPackageXml();
const isSource = targetFormat === 'source';
const tasks = [];

Expand Down
16 changes: 11 additions & 5 deletions src/convert/transformers/defaultMetadataTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,18 @@ export class DefaultMetadataTransformer extends BaseMetadataTransformer {

let xmlDestination = component.getPackageRelativePath(component.xml, targetFormat);

// quirk: append or strip the -meta.xml suffix to the xml if there's no content
// quirks:
// - append or strip the -meta.xml suffix to the path if there's no content
// - remove file extension but preserve -meta.xml suffix if folder type
if (!component.content) {
xmlDestination =
targetFormat === 'metadata'
? xmlDestination.slice(0, xmlDestination.lastIndexOf(META_XML_SUFFIX))
: `${xmlDestination}${META_XML_SUFFIX}`;
if (targetFormat === 'metadata') {
const { folderContentType, suffix } = component.type;
xmlDestination = folderContentType
? xmlDestination.replace(`.${suffix}`, '')
: xmlDestination.slice(0, xmlDestination.lastIndexOf(META_XML_SUFFIX));
} else {
xmlDestination = `${xmlDestination}${META_XML_SUFFIX}`;
}
}

return xmlDestination;
Expand Down
Loading

0 comments on commit 7525a73

Please sign in to comment.