Skip to content

Commit 07f0933

Browse files
authored
Merge pull request #482 from devforth/feature/AdminForth/1188/currently-when-you-set-incorre
feat: add checkIconNames method to validate icon collections and names
2 parents b15317a + 72460be commit 07f0933

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

adminforth/modules/codeInjector.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ function hashify(obj) {
6464
return md5hash(JSON.stringify(obj));
6565
}
6666

67+
function isFulfilled<T>(result: PromiseSettledResult<T>): result is PromiseFulfilledResult<T> {
68+
return result.status === 'fulfilled';
69+
}
70+
6771
function notifyWatcherIssue(limit) {
6872
afLogger.info('Ran out of file handles after watching %s files.', limit);
6973
afLogger.info('Falling back to polling which uses more CPU.');
@@ -86,6 +90,36 @@ class CodeInjector implements ICodeInjector {
8690
return path.join(TMP_DIR, 'adminforth', brandSlug, 'spa_tmp');
8791
}
8892

93+
async checkIconNames(icons: string[]) {
94+
const uniqueIcons = Array.from(new Set(icons));
95+
const collections = new Set(icons.map((icon) => icon.split(':')[0]));
96+
const iconPackageNames = Array.from(collections).map((collection) => `@iconify-prerendered/vue-${collection}`);
97+
98+
const iconPackages = (
99+
await Promise.allSettled(iconPackageNames.map(async (pkg) => ({ pkg: await import(this.spaTmpPath() +'/node_modules/' + pkg), name: pkg})))
100+
);
101+
102+
const loadedIconPackages = iconPackages.filter(isFulfilled).map((res) => res.value).reduce((acc, { pkg, name }) => {
103+
acc[name.slice(`@iconify-prerendered/vue-`.length)] = pkg;
104+
return acc;
105+
}, {});
106+
107+
uniqueIcons.forEach((icon) => {
108+
const [ collection, iconName ] = icon.split(':');
109+
const PascalIconName = 'Icon' + iconName.split('-').map((part, index) => {
110+
return part[0].toUpperCase() + part.slice(1);
111+
}).join('');
112+
113+
if (!loadedIconPackages[collection]) {
114+
throw new Error(`Collection ${collection} not found`);
115+
}
116+
if (!loadedIconPackages[collection][PascalIconName]) {
117+
throw new Error(`Icon ${iconName} not found in collection ${collection}`);
118+
}
119+
});
120+
}
121+
122+
89123
registerCustomComponent(filePath: string): void {
90124
const componentName = getComponentNameFromPath(filePath);
91125
this.allComponentNames[filePath] = componentName;
@@ -497,7 +531,6 @@ class CodeInjector implements ICodeInjector {
497531
}
498532
}
499533

500-
501534
customResourceComponents.forEach((filePath) => {
502535
const componentName = getComponentNameFromPath(filePath);
503536
this.allComponentNames[filePath] = componentName;
@@ -528,7 +561,6 @@ class CodeInjector implements ICodeInjector {
528561
let imports = iconImports + '\n';
529562
imports += customComponentsImports + '\n';
530563

531-
532564
if (this.adminforth.config.customization?.vueUsesFile) {
533565
imports += `import addCustomUses from '${this.adminforth.config.customization.vueUsesFile}';\n`;
534566
}
@@ -654,6 +686,7 @@ class CodeInjector implements ICodeInjector {
654686

655687
try {
656688
const existingHash = await fs.promises.readFile(hashPath, 'utf-8');
689+
await this.checkIconNames(icons);
657690
if (existingHash === fullHash) {
658691
afLogger.trace(`🪲Hashes match, skipping npm ci/install, from file: ${existingHash}, actual: ${fullHash}`);
659692
return;
@@ -693,7 +726,7 @@ class CodeInjector implements ICodeInjector {
693726
}
694727
});
695728
}
696-
729+
await this.checkIconNames(icons);
697730
await fs.promises.writeFile(hashPath, fullHash);
698731
}
699732

0 commit comments

Comments
 (0)