UNPKG

@vis.gl/dev-tools

Version:

Dev tools for vis.gl frameworks

100 lines (90 loc) 3.05 kB
/** * Support module alias in ESM mode by implementing Node.js custom module resolver * tsconfig-paths does not work in ESM, see https://github.com/dividab/tsconfig-paths/issues/122 * Adapted from https://github.com/TypeStrong/ts-node/discussions/1450 */ import path from 'path'; import fs from 'fs'; import {pathToFileURL} from 'url'; import {getValidPath, ocularRoot} from '../utils/utils.js'; /** Node.js resolve hook, * https://nodejs.org/api/module.html#resolvespecifier-context-nextresolve */ type ResolveHook = ( specifier: string, context: { conditions?: unknown; importAssertions?: unknown; parentURL: string; }, nextResolve: ResolveHook ) => Promise<{ url: string; format?: 'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'; shortCircuit?: boolean; }>; // Load alias from file const pathJSON = fs.readFileSync(path.resolve(ocularRoot, '.alias.json'), 'utf-8'); const paths: Record<string, string> = JSON.parse(pathJSON); const matchPath = createMatchPath(paths); export const resolve: ResolveHook = (specifier, context, nextResolver) => { const mappedSpecifier = matchPath(specifier); if (mappedSpecifier) { const fileUrl = pathToFileURL(mappedSpecifier); if (mappedSpecifier.match(/(\/\*|\.jsx?|\.tsx?|\.cjs|\.json)$/)) { specifier = fileUrl.pathname; } else if (mappedSpecifier.includes('/dist/')) { specifier = getValidPath(`${fileUrl}.js`, `${fileUrl}/index.js`) || fileUrl.toString(); } else { specifier = fileUrl.toString(); } } // @ts-expect-error omitted arguments are populated by Node.js return nextResolver(specifier); }; /** Checks if a path matches aliased pattern. * If so, returns mapped path, otherwise returns null */ type AliasTest = (specifier: string) => string | null; /** Get alias mapping function from ocular config */ function createMatchPath(aliases: Record<string, string>): AliasTest { const tests: AliasTest[] = []; for (const key in aliases) { const alias = aliases[key]; let testFunc: AliasTest; if (key.includes('*')) { const regex = new RegExp(`^${key.replace('*', '(.+)')}`); testFunc = (specifier: string) => { const match = specifier.match(regex); if (match) { return specifier.replace(match[0], alias.replace('*', match[1])); } return null; }; } else { let defaultEntry = alias; if (!alias.match(/(\/\*|\.jsx?|\.tsx?|\.cjs)$/)) { defaultEntry = getValidPath(`${alias}/index.ts`, `${alias}/index.js`) || defaultEntry; } testFunc = (specifier: string) => { if (key === specifier) { return defaultEntry; } if (specifier.startsWith(`${key}/`)) { return `${alias}${specifier.slice(key.length)}`; } return null; }; } tests.push(testFunc); } return (specifier: string) => { for (const test of tests) { const result = test(specifier); if (result) { return result; } } return null; }; }