Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
peternhale committed Jan 9, 2025
1 parent e963eb4 commit 484663a
Show file tree
Hide file tree
Showing 34 changed files with 323 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,74 @@
* 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 * as fs from 'node:fs/promises';
// import * as path from 'node:path';
// import { Readable } from 'node:stream';
// import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import { Readable } from 'node:stream';
import * as yaml from 'yaml';
import { JsonMap } from '@salesforce/ts-types';
import { XMLBuilder, XMLParser } from 'fast-xml-parser';
import { WriteInfo } from '../types';
import { SourceComponent } from '../../resolve';
import { BaseMetadataTransformer } from './baseMetadataTransformer';

export type ESR = JsonMap & {
ExternalServiceRegistration: {
schema?: {
_text: string;
};
schema?: string;
};
};

export class DecomposeExternalServiceRegistrationTransformer extends BaseMetadataTransformer {
// private xmlParser = new XMLParser({ ignoreAttributes: false });
// private xmlBuilder = new XMLBuilder({ ignoreAttributes: false });
private xmlParser = new XMLParser({ ignoreAttributes: false });
private xmlBuilder = new XMLBuilder({ ignoreAttributes: false });

// eslint-disable-next-line @typescript-eslint/require-await,class-methods-use-this,@typescript-eslint/no-unused-vars
public async toSourceFormat(input: {
component: SourceComponent;
mergeWith?: SourceComponent | undefined;
}): Promise<WriteInfo[]> {
this.context.decomposedExternalServiceRegistration.externalServiceRegistration ??=
this.registry.getTypeByName('ExternalServiceRegistration');
const writeInfos: WriteInfo[] = [];
// const { component, mergeWith } = input;
// const xmlContent = await component.parseXml<ESR>();
// const esrContent = xmlContent.ExternalServiceRegistration;
//
// // Extract schema content
// // eslint-disable-next-line no-underscore-dangle
// const schemaContent = esrContent.schema?._text ?? '';
// const schemaExtension = this.getSchemaExtension(schemaContent);
// const schemaFileName = `${component.fullName}.schema.${schemaExtension}`;
// const schemaFilePath = path.join(this.defaultDirectory ?? '', schemaFileName);
//
// // Write schema content to file
// writeInfos.push({
// source: Readable.from(schemaContent),
// output: schemaFilePath
// });
//
// // Remove schema content from ESR content
// delete esrContent.schema;
//
// // Write remaining ESR content to file
// const esrFileName = `${component.fullName}.externalServiceRegistration`;
// const esrFilePath = path.join(this.defaultDirectory ?? '', esrFileName);
// writeInfos.push({
// // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
// source: this.xmlBuilder.build({ ExternalServiceRegistration: esrContent }),
// output: esrFilePath
// });
const { component } = input;
const xmlContent = await component.parseXml<ESR>();
const esrContent = xmlContent.ExternalServiceRegistration;

// Extract schema content
// eslint-disable-next-line no-underscore-dangle
const schemaContent: string = esrContent.schema ?? '';
const schemaExtension = this.getSchemaExtension(schemaContent);
const schemaFileName = `${component.fullName}.${schemaExtension}`;
const schemaFilePath = path.join(
this.defaultDirectory ?? '',
'main',
'default',
component.type.directoryName,
schemaFileName
);

// Write schema content to file
writeInfos.push({
source: Readable.from(schemaContent),
output: schemaFilePath,
});

// Remove schema content from ESR content
delete esrContent.schema;

// Write remaining ESR content to file
const esrFileName = `${component.fullName}.externalServiceRegistration`;
const esrFilePath = path.join(
this.defaultDirectory ?? '',
'main',
'default',
component.type.directoryName,
`${esrFileName}-meta.xml`
);
writeInfos.push({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
source: this.xmlBuilder.build({ ExternalServiceRegistration: esrContent }),
output: esrFilePath,
});

return writeInfos;
}
Expand All @@ -70,40 +82,40 @@ export class DecomposeExternalServiceRegistrationTransformer extends BaseMetadat
this.context.decomposedExternalServiceRegistration.externalServiceRegistration ??=
this.registry.getTypeByName('ExternalServiceRegistration');
const writeInfos: WriteInfo[] = [];
// const esrFilePath = this.getOutputFile(component);
// const esrContent = await fs.readFile(esrFilePath, 'utf8');
// // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
// const esrXml = this.xmlParser.parse(esrContent);
//
// // Read schema content from file
// const schemaFileName = `${component.fullName}.schema.yaml`; // or .json based on your logic
// const schemaFilePath = path.join(this.defaultDirectory ?? '', schemaFileName);
// const schemaContent = await fs.readFile(schemaFilePath, 'utf8');
//
// // Add schema content back to ESR content
// // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
// esrXml.ExternalServiceRegistration.schema = { _text: schemaContent };
//
// // Write combined content back to source format
// writeInfos.push({
// // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
// source: this.xmlBuilder.build(esrXml),
// output: esrFilePath
// });
const esrFilePath = this.getOutputFile(component);
const esrContent = await fs.readFile(esrFilePath, 'utf8');
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const esrXml = this.xmlParser.parse(esrContent);

// Read schema content from file
const schemaFileName = `${component.fullName}.schema.yaml`; // or .json based on your logic
const schemaFilePath = path.join(this.defaultDirectory ?? '', schemaFileName);
const schemaContent = await fs.readFile(schemaFilePath, 'utf8');

// Add schema content back to ESR content
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
esrXml.ExternalServiceRegistration.schema = { _text: schemaContent };

// Write combined content back to source format
writeInfos.push({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
source: this.xmlBuilder.build(esrXml),
output: esrFilePath,
});

return writeInfos;
}

// eslint-disable-next-line class-methods-use-this
protected getOutputFile(component: SourceComponent, mergeWith?: SourceComponent): string {
private getOutputFile(component: SourceComponent, mergeWith?: SourceComponent): string {
if (mergeWith?.xml) {
return mergeWith.xml;
}
return component.xml ?? '';
}

// eslint-disable-next-line class-methods-use-this
protected getSchemaExtension(content: string): string {
private getSchemaExtension(content: string): string {
try {
yaml.parse(content);
return 'yaml';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
"externalserviceregistration": {
"children": {
"types": {
"schema": {
"directoryName": " ",
"id": "schema",
"yaml": {
"directoryName": "",
"id": "yaml",
"isAddressable": false,
"name": "Schema",
"suffix": "schema",
"name": "OAS Yaml Schema",
"suffix": "yaml",
"xmlElementName": "schema"
}
},
"suffixes": {
"schema": "schema"
"yaml": "yaml"
}
},
"directoryName": "externalServiceRegistrations",
Expand All @@ -31,13 +31,13 @@
}
},
"suffixes": {
"schema": "schema",
"yaml": "yaml",
"externalServiceRegistration": "externalserviceregistration"
},
"strictDirectoryNames": {
"externalServiceRegistrations": "externalserviceregistration"
},
"childTypes": {
"schema": "externalserviceregistration"
"yaml": "externalserviceregistration"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,22 @@ describe('DecomposeExternalServiceRegistrationTransformer', () => {
const component = MD_FORMAT_ESR;
const xf = new DecomposeExternalServiceRegistrationTransformer(regAcc);
const result = await xf.toSourceFormat({ component });
expect(result).to.have.length(1);
expect(result).to.have.length(2);
result.map((l) => {
expect(l.output).to.include(join('main', 'default', 'externalServiceRegistrations'));
});
expect(result[0].output).to.match(/myESR.externalServiceRegistrations-meta.xml$/);
expect(result[1].output).to.match(/myESR.schema.yaml$/);
expect(result[0].output).to.match(/myESR\.yaml$/);
expect(result[1].output).to.match(/myESR.externalServiceRegistration-meta\.xml$/);
});

it('merge component in defaultDir', async () => {
const component = MD_FORMAT_ESR;
const xf = new DecomposeExternalServiceRegistrationTransformer(regAcc);
const result = await xf.toSourceFormat({
component,
mergeWith: SOURCE_FORMAT_ESR,
});
expect(result).to.have.length(5);
expect(result[4].output).to.equal(SOURCE_FORMAT_ESR.xml);
expect(result).to.have.length(2);
expect(result[1].output).to.equal(SOURCE_FORMAT_ESR.xml);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ export const SOURCE_FORMAT_ESR = new SourceComponent(
{
name: 'myESR',
type: externalServiceRegistration,
content: join('main', 'default', 'externalServiceRegistrations', 'myESR', SOURCE_XML_NAME),
xml: join('main', 'default', 'externalServiceRegistrations', SOURCE_XML_NAME),
},
new VirtualTreeContainer([
{
dirPath: join('main', 'default', 'externalServiceRegistrations', 'myESR'),
dirPath: join('main', 'default', 'externalServiceRegistrations'),
children: [
{
name: 'myESR.externalServiceRegistrations-meta.xml',
Expand All @@ -127,7 +127,7 @@ export const SOURCE_FORMAT_ESR = new SourceComponent(
`),
},
{
name: 'myESR.schema.yaml',
name: 'myESR.yaml',
data: Buffer.from(`openapi: 3.0.0
info:
title: OpenAPIChallenge
Expand Down
4 changes: 2 additions & 2 deletions test/registry/registryValidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { metadataTypes as UnsupportedTypes } from '../../src/registry/nonSupport
import { presets } from './presetTesting';

describe('will run preset tests', () => {
for (const preset of presets) {
for (const preset of presets.filter((preset) => preset.name.includes('decomposeExternalServiceRegistrationBeta'))) {
describe(`Registry Validation ${preset.name}`, () => {
const registry = preset.registry;
const typesWithChildren = Object.values(registry.types).filter((type) => type.children);
Expand Down Expand Up @@ -113,7 +113,7 @@ describe('will run preset tests', () => {
if (registry.childTypes[typeId]) {
expect(registry.types[registry.childTypes[typeId]].children?.types[typeId].suffix).to.equal(suffix);
} else if (registry.types[typeId].legacySuffix) {
// if there are legacy suffixes, this could be either that or the regular suffix
// if there are legacy suffixes, this could be either that or the regular suffix
expect([registry.types[typeId].legacySuffix, registry.types[typeId].suffix]).to.include(suffix);
} else {
expect(registry.types[typeId].suffix).to.equal(suffix);
Expand Down
2 changes: 1 addition & 1 deletion test/snapshot/helper/conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const dirsAreIdentical = async (dir1: string, dir2: string): Promise<Chai

const [files1, files2] = (await Promise.all(dirs.map(getAllDirents))).map(dirEntsToPaths).map(resolveRelative(dirs));

return expect(files1).to.deep.equal(files2);
return expect(files1).to.deep.equalInAnyOrder(files2);
};

const exists = (dir: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('appTemplates', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
2 changes: 1 addition & 1 deletion test/snapshot/sampleProjects/bots/snapshots.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Labels', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('Multiple large custom labels files', () => {
for (const file of convertedFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(path.join(snapshotsDir, 'testOutput'), testOutput);
await dirsAreIdentical(path.join(snapshotsDir, 'testOutput'), testOutput);
});

after(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Labels', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('Custom objects and children', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('digitalExperienceBundle', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
2 changes: 1 addition & 1 deletion test/snapshot/sampleProjects/forceignore/snapshots.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('will respect forceignore when resolving from metadata ', () => {
for (const file of convertedFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(path.join(snapshotsDir, 'testOutput', 'source-format'), sourceOutput);
await dirsAreIdentical(path.join(snapshotsDir, 'testOutput', 'source-format'), sourceOutput);
});

after(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Nested Folders', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('fully decomposed permission set via preset', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, 'force-app'),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', 'force-app')
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('decomposed custom labels', () => {
for (const file of sourceFiles) {
await fileSnap(file, testDir);
}
dirsAreIdentical(
await dirsAreIdentical(
path.join(testDir, FORCE_APP),
path.join(testDir, '__snapshots__', 'verify-source-files.expected', FORCE_APP)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ExternalServiceRegistration xmlns="http://soap.sforce.com/2006/04/metadata"><label>BankService</label><namedCredential>ntest</namedCredential><registrationProviderType>Custom</registrationProviderType><schemaType>OpenApi3</schemaType><schemaUrl>/accounts/schema</schemaUrl><serviceBinding>{&quot;host&quot;:&quot;&quot;,&quot;basePath&quot;:&quot;/&quot;,&quot;allowedSchemes&quot;:[],&quot;requestMediaTypes&quot;:[],&quot;responseMediaTypes&quot;:[],&quot;compatibleMediaTypes&quot;:{}}</serviceBinding><status>Complete</status><systemVersion>3</systemVersion></ExternalServiceRegistration>
Loading

0 comments on commit 484663a

Please sign in to comment.