Skip to content

Commit

Permalink
refactor: modernized Atlas
Browse files Browse the repository at this point in the history
  • Loading branch information
catalandres committed Dec 24, 2023
1 parent 0b47a9c commit e3f5ce4
Show file tree
Hide file tree
Showing 25 changed files with 223 additions and 292 deletions.
28 changes: 21 additions & 7 deletions src/commands/doc/generate/atlas.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { dirname } from 'node:path';
import { readdir } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
import { SfProject, Messages } from '@salesforce/core';
import { SfProject, Messages, NamedPackageDir } from '@salesforce/core';
import { ExcelWriter } from '../../../shared/xlsx/ExcelWriter.js';

import { Atlas } from '../../../shared/Atlas.js';
import { Atlas } from '../../../shared/metadata/Atlas.js';

Messages.importMessagesDirectory(dirname(fileURLToPath(import.meta.url)));
const messages = Messages.loadMessages('plugin-documentation-atlas', 'doc.generate.atlas');
Expand All @@ -26,16 +28,28 @@ export default class DocGenerateAtlas extends SfCommand<DocGenerateAtlasResult>
}),
};

// TODO - add flags and remove this exception
// eslint-disable-next-line class-methods-use-this
public async run(): Promise<DocGenerateAtlasResult> {
// const { flags } = await this.parse(DocGenerateAtlas);
this.spinner.start('Generating documentation atlas');
const atlas = new Atlas(SfProject.getInstance().getPath());
await atlas.initialize(this.spinner);
const xlsxFilename = await atlas.writeXlsx();
this.spinner.stop('Written atlas file: ' + xlsxFilename);
const projectPath = SfProject.getInstance().getPath();
const allProjectFiles = await getAllProjectFiles(projectPath);
const atlas = new Atlas(allProjectFiles);
const xlWriter = new ExcelWriter(atlas.album, projectPath);
const xlsxFilename = await xlWriter.writeXlsx();

return {
path: xlsxFilename,
};
}
}

async function getAllProjectFiles(projectPath: string): Promise<string[]> {
const metadata: string[] = [];
const packageDirectories: NamedPackageDir[] = SfProject.getInstance(projectPath).getUniquePackageDirectories();
for await (const thisPackageDirectory of packageDirectories) {
const items = await readdir(thisPackageDirectory.fullPath, { recursive: true });
metadata.push(...items.map((item) => thisPackageDirectory.fullPath + item));
}
return metadata;
}
44 changes: 0 additions & 44 deletions src/shared/ExcelWriter.ts

This file was deleted.

76 changes: 0 additions & 76 deletions src/shared/XmlParser.ts

This file was deleted.

96 changes: 96 additions & 0 deletions src/shared/metadata/Atlas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as fs from 'node:fs';
import * as xml2js from 'xml2js';
import { array } from '../array.js';
import { Extended, ExtendedMetadata, Album, Definition, ALL_DEFINITIONS, getExtension } from './file/index.js';

export class Atlas {
public album: Album = {};
private projectFilenames: string[];
private metadataFilenames: string[];
private fileDefinitionsByExtension: Map<string, Definition>;
private metadataExtensions: Set<string>;

public constructor(projectFilenames: string[]) {
this.projectFilenames = projectFilenames;
this.fileDefinitionsByExtension = new Map();

for (const thisFileDefinition of ALL_DEFINITIONS) {
if (thisFileDefinition.extension) {
this.fileDefinitionsByExtension.set(thisFileDefinition.extension, thisFileDefinition);
}
}
this.metadataExtensions = new Set(this.fileDefinitionsByExtension.keys());

this.metadataFilenames = this.projectFilenames.filter((theFile) => this.isMetadataFile(theFile));

for (const thisFile of this.metadataFilenames) {
const thisDefinition: Definition = this.fileDefinitionsByExtension.get(getExtension(thisFile))!;
const xml = fs.readFileSync(thisFile, 'utf-8');
this.absorb(getMetadata<Extended<typeof thisDefinition.metadataType>>(xml, thisFile, thisDefinition));
}
}

private absorb(album: Album): void {
for (const thisList of Object.keys(album)) {
if (!this.album[thisList]) {
this.album[thisList] = [];
}
this.album[thisList].push(...album[thisList]);
}
}

private isMetadataFile(thisFile: string): boolean {
return this.metadataExtensions.has(getExtension(thisFile));
}
}

const parserOptions: xml2js.ParserOptions = {
explicitArray: false,
mergeAttrs: true,
valueProcessors: [
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
xml2js.processors.parseNumbers,
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
xml2js.processors.parseBooleans,
],
};

function getMetadata<T extends ExtendedMetadata>(xml: string, fileName: string, definition: Definition): Album {
const album: Album = {};
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
xml2js.parseString(xml, parserOptions, (err, result: Record<string, T>) => {
const theRecord = result[definition.name];
if (!definition.container) {
treatRecord(theRecord, definition, fileName);
album[definition.list] = [theRecord];
}
if (definition.children) {
for (const listName of Object.keys(definition.children)) {
const thisDefinition = definition.children[listName];
album[thisDefinition.list] = [];
const records = array(theRecord[listName]) as Array<Extended<typeof thisDefinition.metadataType>>;
for (const thisRecord of records) {
treatRecord(thisRecord, thisDefinition, fileName);
album[thisDefinition.list].push(thisRecord as T);
}
}
}
});
return album;
}

function treatRecord<T extends ExtendedMetadata>(record: Extended<T>, metadata: Definition, fileName: string): void {
record.fileName = fileName;
if (metadata.setName) {
record.name = metadata.setName(record);
}
if (metadata.setObjectname) {
record.objectName = metadata.setObjectname(record);
}
if (metadata.setFullName) {
record.fullName = metadata.setFullName(record);
}
if (metadata.transform) {
metadata.transform(record);
}
}
8 changes: 4 additions & 4 deletions src/shared/metadata/file/classes/Definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export interface Definition {
readonly extension?: string;
readonly metadataType: Metadata;
readonly container?: boolean;
readonly setName?: (parameter: string) => string;
readonly setObjectname?: (parameter: string) => string;
readonly setFullName?: (parameter: string) => string;
readonly setName?: (record: Extended<Metadata>) => string;
readonly setObjectname?: (record: Extended<Metadata>) => string;
readonly setFullName?: (record: Extended<Metadata>) => string;
readonly transform?: (record: Extended<Metadata>) => void;
readonly process?: Array<(record: Extended<Metadata>) => Array<Extended<Metadata>>>;
readonly children?: Map<string, Definition>;
readonly children?: Record<string, Definition>;
}
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/CompactLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const COMPACT_LAYOUT: Definition = {
Expand All @@ -13,5 +13,5 @@ export const COMPACT_LAYOUT: Definition = {
metadataType: {} as CompactLayout,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/CustomField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const CUSTOM_FIELD: Definition = {
Expand All @@ -13,5 +13,5 @@ export const CUSTOM_FIELD: Definition = {
metadataType: {} as CustomField,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/FieldSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const FIELD_SET: Definition = {
Expand All @@ -13,5 +13,5 @@ export const FIELD_SET: Definition = {
metadataType: {} as FieldSet,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/ListView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const LIST_VIEW: Definition = {
Expand All @@ -13,5 +13,5 @@ export const LIST_VIEW: Definition = {
metadataType: {} as ListView,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/RecordType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const RECORD_TYPE: Definition = {
Expand All @@ -13,5 +13,5 @@ export const RECORD_TYPE: Definition = {
metadataType: {} as RecordType,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/ValidationRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const VALIDATION_RULE: Definition = {
Expand All @@ -13,5 +13,5 @@ export const VALIDATION_RULE: Definition = {
metadataType: {} as ValidationRule,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
4 changes: 2 additions & 2 deletions src/shared/metadata/file/definitions/WebLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
Definition,
getBasenameWithoutExtension,
getNameOfSecondToLastFolderLevel,
getFullNameForObjectComponent,
concatenateObjectNameAndName,
} from '../index.js';

export const WEBLINK: Definition = {
Expand All @@ -13,5 +13,5 @@ export const WEBLINK: Definition = {
metadataType: {} as WebLink,
setName: getBasenameWithoutExtension,
setObjectname: getNameOfSecondToLastFolderLevel,
setFullName: getFullNameForObjectComponent,
setFullName: concatenateObjectNameAndName,
};
Loading

0 comments on commit e3f5ce4

Please sign in to comment.