Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle nulls/undefined in template literal #1370

Merged
merged 3 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"node": ">=18.0.0"
},
"dependencies": {
"@salesforce/core": "^8.1.2",
"@salesforce/core": "^8.2.1",
"@salesforce/kit": "^3.1.6",
"@salesforce/ts-types": "^2.0.10",
"fast-levenshtein": "^3.0.0",
Expand All @@ -39,7 +39,7 @@
"proxy-agent": "^6.4.0"
},
"devDependencies": {
"@jsforce/jsforce-node": "^3.2.2",
"@jsforce/jsforce-node": "^3.2.4",
"@salesforce/cli-plugins-testkit": "^5.3.18",
"@salesforce/dev-scripts": "^10.2.2",
"@types/deep-equal-in-any-order": "^1.0.1",
Expand Down
8 changes: 6 additions & 2 deletions src/client/metadataApiDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,9 @@ export class MetadataApiDeploy extends MetadataTransfer<
} catch (err) {
const error = err as Error;
this.logger.debug(
`Error trying to compile/send deploy telemetry data for deploy ID: ${this.id}\nError: ${error.message}`
`Error trying to compile/send deploy telemetry data for deploy ID: ${this.id ?? '<not provided>'}\nError: ${
error.message
}`
);
}
const deployResult = new DeployResult(
Expand Down Expand Up @@ -394,7 +396,9 @@ const warnIfUnmatchedServerResult =

// warn that this component is found in server response, but not in component set
void Lifecycle.getInstance().emitWarning(
`${deployMessage.componentType}, ${deployMessage.fullName}, returned from org, but not found in the local project`
`${deployMessage.componentType ?? '<no component type in deploy message>'}, ${
deployMessage.fullName
}, returned from org, but not found in the local project`
);
}
});
Expand Down
4 changes: 2 additions & 2 deletions src/client/metadataTransfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export abstract class MetadataTransfer<
this.canceled = false;
const asyncResult = await this.pre();
this.transferId = asyncResult.id;
this.logger.debug(`Started metadata transfer. ID = ${this.id}`);
this.logger.debug(`Started metadata transfer. ID = ${this.id ?? '<no id>'}`);
return asyncResult;
}

Expand Down Expand Up @@ -105,7 +105,7 @@ export abstract class MetadataTransfer<
});

try {
this.logger.debug(`Polling for metadata transfer status. ID = ${this.id}`);
this.logger.debug(`Polling for metadata transfer status. ID = ${this.id ?? '<no id>'}`);
this.logger.debug(`Polling frequency (ms): ${normalizedOptions.frequency.milliseconds}`);
this.logger.debug(`Polling timeout (min): ${normalizedOptions.timeout.minutes}`);
const completedMdapiStatus = (await pollingClient.subscribe()) as unknown as Status;
Expand Down
4 changes: 2 additions & 2 deletions src/collections/componentSetBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ const logComponents = (logger: Logger, componentSet: ComponentSet): void => {
.map((m) => logger.debug(m));
if (components.length > 20) logger.debug(`(showing 20 of ${componentSet.size} matches)`);

logger.debug(`ComponentSet apiVersion = ${componentSet.apiVersion}`);
logger.debug(`ComponentSet sourceApiVersion = ${componentSet.sourceApiVersion}`);
logger.debug(`ComponentSet apiVersion = ${componentSet.apiVersion ?? '<not set>'}`);
logger.debug(`ComponentSet sourceApiVersion = ${componentSet.sourceApiVersion ?? '<not set>'}`);
};

const getOrgComponentFilter = (
Expand Down
2 changes: 1 addition & 1 deletion src/convert/convertContext/nonDecompositionFinalizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ const recompose = (children: Map<string, JsonMap>, parentSourceComponent: Source
const getDefaultOutput = (component: SourceComponent): string => {
const { fullName } = component;
const [baseName] = fullName.split('.');
const output = `${baseName}.${component.type.suffix}${META_XML_SUFFIX}`;
const output = `${baseName}.${component.type.suffix ?? ''}${META_XML_SUFFIX}`;

return join(component.getPackageRelativePath('', 'source'), output);
};
15 changes: 10 additions & 5 deletions src/convert/convertContext/recompositionFinalizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const stateValueToWriterFormat =
source: new JsToXml(await recompose(cache)(stateValue)),
output: join(
stateValue.component.type.directoryName,
`${stateValue.component.fullName}.${stateValue.component.type.suffix}`
`${stateValue.component.fullName}.${stateValue.component.type.suffix ?? ''}`
),
},
],
Expand Down Expand Up @@ -139,10 +139,15 @@ const ensureStateValueWithParent = (
return true;
}
throw new Error(
`The parent component is missing from the recomposition state entry. The children are ${stateValue.children
?.toArray()
.map((c) => c.fullName)
.join(', ')}`
`The parent component is missing from the recomposition state entry. ${
stateValue.children
? `The children are ${stateValue.children
?.toArray()
.map((c) => c.fullName)
.join(', ')}
`
: 'There are no children.'
}`
);
};

Expand Down
9 changes: 6 additions & 3 deletions src/convert/transformers/decomposedMetadataTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ const getChildWriteInfos =
return [
{
source,
output: join(dirname(mergeWith.xml), `${entryName}.${childComponent.type.suffix}${META_XML_SUFFIX}`),
output: join(
dirname(mergeWith.xml),
`${entryName}.${ensureString(childComponent.type.suffix)}${META_XML_SUFFIX}`
),
},
];
}
Expand Down Expand Up @@ -259,7 +262,7 @@ const getDefaultOutput = (component: MetadataComponent): SourcePath => {
const childName = tail.length ? tail.join('.') : undefined;
const output = join(
parent?.type.strategies?.decomposition === DecompositionStrategy.FolderPerType ? type.directoryName : '',
`${childName ?? baseName}.${component.type.suffix}${META_XML_SUFFIX}`
`${childName ?? baseName}.${ensureString(component.type.suffix)}${META_XML_SUFFIX}`
);
return join(calculateRelativePath('source')({ self: parent?.type ?? type })(fullName)(baseName), output);
};
Expand Down Expand Up @@ -289,7 +292,7 @@ type ComposedMetadata = { tagKey: string; tagValue: AnyJson; parentType: Metadat
type ComposedMetadataWithChildType = ComposedMetadata & { childType: MetadataType };

type InfoContainer = {
entryName?: string;
entryName: string;
childComponent: MetadataComponent;
/** the parsed xml */
value: JsonMap;
Expand Down
4 changes: 2 additions & 2 deletions src/convert/transformers/defaultMetadataTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const getXmlDestination = (
if (!component.content && !['digitalexperiencebundle'].includes(component.type.id)) {
if (targetFormat === 'metadata') {
if (folderContentType) {
xmlDestination = xmlDestination.replace(`.${suffix}`, '');
xmlDestination = xmlDestination.replace(`.${suffix ?? ''}`, '');
} else if (xmlDestination.includes(META_XML_SUFFIX)) {
xmlDestination = xmlDestination.slice(0, xmlDestination.lastIndexOf(META_XML_SUFFIX));
} else {
Expand All @@ -111,7 +111,7 @@ const getXmlDestination = (
}
} else {
xmlDestination = folderContentType
? xmlDestination.replace(META_XML_SUFFIX, `.${suffix}${META_XML_SUFFIX}`)
? xmlDestination.replace(META_XML_SUFFIX, `.${suffix ?? ''}${META_XML_SUFFIX}`)
: `${xmlDestination}${META_XML_SUFFIX}`;
}
} else if (suffix) {
Expand Down
20 changes: 12 additions & 8 deletions src/convert/transformers/staticResourceMetadataTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class StaticResourceMetadataTransformer extends BaseMetadataTransformer {

// Zip the static resource from disk to a stream, compressing at level 9.
const zipIt = (): Readable => {
getLogger().debug(`zipping static resource: ${component.content}`);
getLogger().debug(`zipping static resource: ${content}`);
const zip = JSZip();

// JSZip does not have an API for adding a directory of files recursively so we always
Expand All @@ -78,7 +78,7 @@ export class StaticResourceMetadataTransformer extends BaseMetadataTransformer {
streamFiles: true,
})
.on('end', () => {
getLogger().debug(`zip complete for: ${component.content}`);
getLogger().debug(`zip complete for: ${content}`);
})
);
};
Expand All @@ -88,7 +88,7 @@ export class StaticResourceMetadataTransformer extends BaseMetadataTransformer {
source: (await componentIsExpandedArchive(component))
? zipIt()
: getReplacementStreamForReadable(component, content),
output: join(type.directoryName, `${baseName(content)}.${type.suffix}`),
output: join(type.directoryName, `${baseName(content)}.${type.suffix ?? ''}`),
},
{
source: getReplacementStreamForReadable(component, xml),
Expand Down Expand Up @@ -197,7 +197,9 @@ const getContentType = async (component: SourceComponent): Promise<string> => {

if (typeof output !== 'string') {
throw new SfError(
`Expected a string for contentType in ${component.name} (${component.xml}) but got ${JSON.stringify(output)}`
`Expected a string for contentType in ${component.name} (${component.xml ?? '<no xml>'}) but got ${JSON.stringify(
output
)}`
);
}
return output;
Expand All @@ -211,7 +213,7 @@ const getBaseContentPath = (component: SourceComponent, mergeWith?: SourceCompon
const baseContentPath = component.getPackageRelativePath(component.content, 'source');
return join(dirname(baseContentPath), baseName(baseContentPath));
}
throw new SfError(`Expected a content path for ${component.name} (${component.xml})`);
throw new SfError(`Expected a content path for ${component.name} (${component.xml ?? '<no xml>'})`);
};

const getExtensionFromType = (contentType: string): string =>
Expand All @@ -238,8 +240,10 @@ async function getStaticResourceZip(component: SourceComponent, content: string)
const staticResourceZip = await component.tree.readFile(content);
return await JSZip.loadAsync(staticResourceZip, { createFolders: true });
} catch (e) {
throw new SfError(`Unable to open zip file ${content} for ${component.name} (${component.xml})`, 'BadZipFile', [
'Check that your file really is a valid zip archive',
]);
throw new SfError(
`Unable to open zip file ${content} for ${component.name} (${component.xml ?? '<no xml>'})`,
'BadZipFile',
['Check that your file really is a valid zip archive']
);
}
}
5 changes: 4 additions & 1 deletion src/resolve/adapters/digitalExperienceSourceAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
import { dirname, join, sep } from 'node:path';
import { Messages } from '@salesforce/core';
import { ensureString } from '@salesforce/ts-types';
import { META_XML_SUFFIX } from '../../common/constants';
import { SourcePath } from '../../common/types';
import { SourceComponent } from '../sourceComponent';
Expand Down Expand Up @@ -147,7 +148,9 @@ export class DigitalExperienceSourceAdapter extends BundleSourceAdapter {
// 3 because we want 'digitalExperiences' directory, 'baseType' directory and 'bundleName' directory
const basePath = pathParts.slice(0, typeFolderIndex + 3).join(sep);
const bundleFileName = pathParts[typeFolderIndex + 2];
const suffix = this.isBundleType() ? this.type.suffix : this.registry.getParentType(this.type.id)?.suffix;
const suffix = ensureString(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will throw, so ex: if the metadataRegistry ever loses a suffix for DEB stuff, it'll fail tests

this.isBundleType() ? this.type.suffix : this.registry.getParentType(this.type.id)?.suffix
);
return `${basePath}${sep}${bundleFileName}.${suffix}${META_XML_SUFFIX}`;
}

Expand Down
16 changes: 12 additions & 4 deletions src/resolve/connectionResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,17 @@ export class ConnectionResolver {

return {
components: Aggregator.filter(componentFilter).map((component) => ({
fullName: ensureString(component.fullName, `Component fullName was not set for ${component.fileName}`),
fullName: ensureString(
component.fullName,
`Component fullName was not set for ${component.fileName ?? '<missing filename>'}`
),
type: this.registry.getTypeByName(
ensureString(component.type, `Component type was not set for ${component.fullName} (${component.fileName})`)
ensureString(
component.type,
`Component type was not set for ${component.fullName ?? '<missing fullname>'} (${
component.fileName ?? '<missing filename>'
})`
)
),
})),
apiVersion: this.connection.getApiVersion(),
Expand Down Expand Up @@ -142,7 +150,7 @@ const listMembers =
return (
standardValueSetRecord.Metadata.standardValue.length && {
fullName: standardValueSetRecord.MasterLabel,
fileName: `${mdType.directoryName}/${standardValueSetRecord.MasterLabel}.${mdType.suffix}`,
fileName: `${mdType.directoryName}/${standardValueSetRecord.MasterLabel}.${mdType.suffix ?? ''}`,
type: mdType.name,
}
);
Expand Down Expand Up @@ -172,7 +180,7 @@ const listMembers =
const inferFilenamesFromType =
(metadataType: MetadataType) =>
(member: RelevantFileProperties): RelevantFileProperties =>
typeof member.fileName === 'object'
typeof member.fileName === 'object' && metadataType.suffix
? { ...member, fileName: `${metadataType.directoryName}/${member.fullName}.${metadataType.suffix}` }
: member;

Expand Down
10 changes: 5 additions & 5 deletions src/resolve/sourceComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class SourceComponent implements MetadataComponent {
}
if (this.parent && this.type.ignoreParentName) {
if (!this.name) {
throw new SfError(`Component was initialized without a name: ${this.xml} (${this.type.name})`);
throw new SfError(`Component was initialized without a name: ${this.xml ?? '<no xml>'} (${this.type.name})`);
}
return this.name;
} else {
Expand Down Expand Up @@ -350,17 +350,17 @@ export class SourceComponent implements MetadataComponent {
}

return Object.values(this.type.children.types).flatMap((childType) => {
const uniqueIdElement = childType.uniqueIdElement;
const { uniqueIdElement, xmlElementName } = childType;

if (!uniqueIdElement) {
if (!uniqueIdElement || !xmlElementName) {
return [];
}
const xmlPathToChildren = `${this.type.name}.${childType.xmlElementName}`;
const xmlPathToChildren = `${this.type.name}.${xmlElementName}`;
const elements = ensureArray(get(parsed, xmlPathToChildren, []));
return elements.map((element) => {
const name = getString(element, uniqueIdElement);
if (!name) {
throw new SfError(`Missing ${uniqueIdElement} on ${childType.name} in ${this.xml}`);
throw new SfError(`Missing ${uniqueIdElement} on ${childType.name} in ${this.xml ?? '<no xml>'}`);
}
return new SourceComponent(
{
Expand Down
24 changes: 13 additions & 11 deletions src/utils/filePathGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const filePathsFromMetadataComponent = (

if (type.strategies?.adapter === 'digitalExperience') {
// child MD Type, the metafile is a JSON, not an XML
if (type.id === 'digitalexperience') {
if (type.id === 'digitalexperience' && type.metaFileSuffix) {
// metafile name = metaFileSuffix for DigitalExperience.
return [
join(
Expand All @@ -55,12 +55,12 @@ export const filePathsFromMetadataComponent = (
}

// parent MD Type
if (type.id === 'digitalexperiencebundle') {
if (type.id === 'digitalexperiencebundle' && type.suffix) {
return [join(packageDirWithTypeDir, `${fullName}${sep}${basename(fullName)}.${type.suffix}${META_XML_SUFFIX}`)];
}
}

if (type.strategies?.adapter === 'decomposed') {
if (type.strategies?.adapter === 'decomposed' && type.suffix) {
return [join(packageDirWithTypeDir, `${fullName}${sep}${fullName}.${type.suffix}${META_XML_SUFFIX}`)];
}

Expand All @@ -70,19 +70,19 @@ export const filePathsFromMetadataComponent = (
}

// Non-decomposed parents (i.e., any type that defines children and not a decomposed transformer)
if (type.children) {
if (type.children && type.suffix) {
return [join(packageDirWithTypeDir, `${fullName}.${type.suffix}${META_XML_SUFFIX}`)];
}

// basic metadata (with or without folders)
if (!type.children && !type.strategies) {
if (!type.children && !type.strategies && type.suffix) {
return (type.inFolder ?? type.folderType ? generateFolders({ fullName, type }, packageDirWithTypeDir) : []).concat([
join(packageDirWithTypeDir, `${fullName}.${type.suffix}${META_XML_SUFFIX}`),
]);
}

// matching content (with or without folders)
if (type.strategies?.adapter === 'matchingContentFile') {
if (type.strategies?.adapter === 'matchingContentFile' && type.suffix) {
return (type.inFolder ? generateFolders({ fullName, type }, packageDirWithTypeDir) : []).concat([
join(packageDirWithTypeDir, `${fullName}.${type.suffix}${META_XML_SUFFIX}`),
join(packageDirWithTypeDir, `${fullName}.${type.suffix}`),
Expand All @@ -102,8 +102,10 @@ export const filePathsFromMetadataComponent = (
return [
join(
packageDirWithTypeDir,
// registry doesn't have a suffix for EB (it comes down inside the mdapi response)
`${fullName}.${type.strategies?.transformer === 'staticResource' ? type.suffix : 'site'}${META_XML_SUFFIX}`
// registry doesn't have a suffix for EB (it comes down inside the mdapi response). // staticResource has a suffix
`${fullName}.${
type.strategies?.transformer === 'staticResource' ? (type.suffix as string) : 'site'
}${META_XML_SUFFIX}`
),
join(packageDirWithTypeDir, `${fullName}`),
];
Expand Down Expand Up @@ -140,7 +142,7 @@ const generateFolders = ({ fullName, type }: MetadataComponent, packageDirWithTy
join(
packageDirWithTypeDir,
`${originalArray.slice(0, index + 1).join(sep)}.${
registryAccess.getTypeByName(folderType).suffix
registryAccess.getTypeByName(folderType).suffix ?? ''
}${META_XML_SUFFIX}`
)
);
Expand All @@ -159,14 +161,14 @@ const getDecomposedChildType = ({ fullName, type }: MetadataComponent, packageDi
// parent
join(
topLevelTypeDir,
`${fullName.split('.')[0]}${sep}${fullName.split('.')[0]}.${topLevelType.suffix}${META_XML_SUFFIX}`
`${fullName.split('.')[0]}${sep}${fullName.split('.')[0]}.${topLevelType.suffix ?? ''}${META_XML_SUFFIX}`
),
// child
join(
topLevelTypeDir,
fullName.split('.')[0],
type.directoryName,
`${fullName.split('.')[1]}.${type.suffix}${META_XML_SUFFIX}`
`${fullName.split('.')[1]}.${type.suffix ?? ''}${META_XML_SUFFIX}`
),
];
};
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('Multiple large custom labels files', () => {
genUniqueDir: false,
});
// Longer than 10 seconds could indicate a regression
expect(Date.now() - convertStartTime, 'conversion should take less than 10 seconds').to.be.lessThan(10000);
expect(Date.now() - convertStartTime, 'conversion should take less than 10 seconds').to.be.lessThan(10_000);

const convertedFiles = await getConvertedFilePaths(testOutput);
for (const file of convertedFiles) {
Expand Down
Loading
Loading