From aba9a7b00ebec28e59ca248ab2e3484acda0024d Mon Sep 17 00:00:00 2001 From: Vjacheslav Trushkin Date: Sun, 28 Jul 2024 22:57:37 +0300 Subject: [PATCH] chore(utils): treat each cwd differently in loader --- packages/utils/src/loader/fs.ts | 38 ++++++++++++++++++----- packages/utils/tests/external-pkg-test.ts | 1 + packages/utils/tests/iconify-icon-test.ts | 14 +++++++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/packages/utils/src/loader/fs.ts b/packages/utils/src/loader/fs.ts index 0c85a9c..a8867d0 100644 --- a/packages/utils/src/loader/fs.ts +++ b/packages/utils/src/loader/fs.ts @@ -1,12 +1,17 @@ import { promises as fs, Stats } from 'fs'; -import { isPackageExists, importModule } from 'local-pkg'; +import { importModule } from 'local-pkg'; import type { IconifyJSON } from '@iconify/types'; import { tryInstallPkg } from './install-pkg'; import type { AutoInstall } from './types'; import { resolvePath } from 'mlly'; -const _collections: Record> = {}; -const isLegacyExists = isPackageExists('@iconify/json'); +// Cache: [cwd][name] => icon set promise +type CachedItem = Promise; +type CachedItems = Record; +const _collections = Object.create(null) as Record; + +// Check if full package exists, per cwd value +const isLegacyExists = Object.create(null) as Record; /** * Asynchronously loads a collection from the file system. @@ -22,10 +27,14 @@ export async function loadCollectionFromFS( scope = '@iconify-json', cwd = process.cwd() ): Promise { - if (!(await _collections[name])) { - _collections[name] = task(); + const cache = + _collections[cwd] || + (_collections[cwd] = Object.create(null) as CachedItems); + + if (!(await cache[name])) { + cache[name] = task(); } - return _collections[name]; + return cache[name]; async function task() { const packageName = scope.length === 0 ? name : `${scope}/${name}`; @@ -35,7 +44,20 @@ export async function loadCollectionFromFS( // Legacy support for @iconify/json if (scope === '@iconify-json') { - if (!jsonPath && isLegacyExists) { + // Check legacy package exists + if (isLegacyExists[cwd] === undefined) { + const testResult = await resolvePath( + `@iconify/json/collections.json`, + { + url: cwd, + } + ).catch(() => undefined); + isLegacyExists[cwd] = !!testResult; + } + const checkLegacy = isLegacyExists[cwd]; + + // Check legacy package + if (!jsonPath && checkLegacy) { jsonPath = await resolvePath( `@iconify/json/json/${name}.json`, { @@ -45,7 +67,7 @@ export async function loadCollectionFromFS( } // Try to install the package if it doesn't exist - if (!jsonPath && !isLegacyExists && autoInstall) { + if (!jsonPath && !checkLegacy && autoInstall) { await tryInstallPkg(packageName, autoInstall); jsonPath = await resolvePath(`${packageName}/icons.json`, { url: cwd, diff --git a/packages/utils/tests/external-pkg-test.ts b/packages/utils/tests/external-pkg-test.ts index 3c044f0..5de7bea 100644 --- a/packages/utils/tests/external-pkg-test.ts +++ b/packages/utils/tests/external-pkg-test.ts @@ -10,6 +10,7 @@ describe('external-pkg', () => { }); expect(result).toBeTruthy(); }); + test('loadNodeIcon works with importModule and scoped package name', async () => { const result = await loadNodeIcon('test-color-icons', 'about', { customCollections: createExternalPackageIconLoader( diff --git a/packages/utils/tests/iconify-icon-test.ts b/packages/utils/tests/iconify-icon-test.ts index 80d131f..ac0eb2c 100644 --- a/packages/utils/tests/iconify-icon-test.ts +++ b/packages/utils/tests/iconify-icon-test.ts @@ -122,4 +122,18 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => { expect(result && result.includes('width="')).toBeFalsy(); expect(result && result.includes('height="1em"')).toBeTruthy(); }); + + test('loadIcon with bad cwd', async () => { + const result = await loadNodeIcon('flat-color-icons', 'up-left', { + cwd: './tests', + }); + expect(result).toBeUndefined(); + }); + + test('loadIcon with multiple cwd', async () => { + const result = await loadNodeIcon('flat-color-icons', 'up-left', { + cwd: ['./tests', process.cwd()], + }); + expect(result).toBeTruthy(); + }); });