Skip to content

Instantly share code, notes, and snippets.

@brainkim
Created March 17, 2023 02:10
Show Gist options
  • Save brainkim/285d0c2ed69a4a158f5f576e16fdff41 to your computer and use it in GitHub Desktop.
Save brainkim/285d0c2ed69a4a158f5f576e16fdff41 to your computer and use it in GitHub Desktop.
ChatGPT implementation of resolve using node.js pseudocode
// This code was generated with the help of OpenAI's ChatGPT-4.
import * as FS from 'fs/promises';
import * as Path from 'path';
import {fileURLToPath, pathToFileURL} from 'url';
async function resolvePackageImports(basePath, specifier, conditions) {
const pkgJson = JSON.parse(await FS.readFile(fileURLToPath(basePath) + '/package.json'));
const imports = pkgJson.imports;
if (typeof imports === 'object' && !Array.isArray(imports)) {
for (const key of Object.keys(imports)) {
if (key === specifier) {
const target = imports[key];
if (typeof target === 'string') {
return new URL(target, basePath);
} else if (typeof target === 'object' && !Array.isArray(target)) {
for (const condition of conditions) {
if (target.hasOwnProperty(condition)) {
return new URL(target[condition], basePath);
}
}
}
}
}
}
throw new Error(`Import not found: ${specifier}`);
}
async function resolvePackageExports(basePath, subpath, exports, conditions) {
if (typeof exports === 'object' && !Array.isArray(exports)) {
for (const key of Object.keys(exports)) {
if (key === '.' || (key.startsWith('./') && subpath.startsWith(key))) {
const target = exports[key];
if (typeof target === 'string') {
const resolved = new URL(target, basePath);
if (fileURLToPath(resolved).endsWith(subpath)) {
return resolved;
}
} else if (typeof target === 'object' && !Array.isArray(target)) {
for (const condition of conditions) {
if (target.hasOwnProperty(condition)) {
const resolved = new URL(target[condition], basePath);
if (fileURLToPath(resolved).endsWith(subpath)) {
return resolved;
}
}
}
}
}
}
}
throw new Error(`Export not found: ${subpath}`);
}
function isCoreModule(moduleName) {
// Replace this list with the actual list of core modules for your Node.js version.
const coreModules = [
'assert',
'buffer',
'child_process',
'cluster',
'console',
'constants',
'crypto',
'dgram',
'dns',
'domain',
'events',
'fs',
'http',
'https',
'module',
'net',
'os',
'path',
'punycode',
'querystring',
'readline',
'repl',
'stream',
'string_decoder',
'timers',
'tls',
'tty',
'url',
'util',
'v8',
'vm',
'zlib',
];
return coreModules.includes(moduleName);
}
async function resolveEsmMatch(match) {
const resolvedPath = fileURLToPath(match);
try {
await FS.access(resolvedPath);
return resolvedPath;
} catch {
throw new Error(`Module not found: ${resolvedPath}`);
}
}
async function loadPackageImports(x, dir) {
const scope = await findClosestPackageScope(dir);
if (!scope) return null;
const pkgJson = JSON.parse(await FS.readFile(Path.join(scope, 'package.json')));
if (!pkgJson.imports) return null;
const basePath = pathToFileURL(scope);
const match = await resolvePackageImports(basePath, x, ['node', 'require']);
return await resolveEsmMatch(match);
}
async function loadPackageExports(name, subpath, dir) {
try {
const pkgJsonFile = Path.join(dir, name, 'package.json');
await FS.access(pkgJsonFile);
const pkgJson = JSON.parse(await FS.readFile(pkgJsonFile));
if (!pkgJson.exports) return null;
const basePath = pathToFileURL(Path.join(dir, name));
const match = await resolvePackageExports(basePath, '.' + subpath, pkgJson.exports, ['node', 'require']);
return await resolveEsmMatch(match);
} catch {
// Do nothing, continue to next step
}
return null;
}
async function loadAsFile(x) {
const extensions = ['', '.js', '.json', '.node'];
for (const ext of extensions) {
const file = x + ext;
try {
await FS.access(file);
return file;
} catch {
// Do nothing, continue to next extension
}
}
return null;
}
async function loadIndex(x) {
const extensions = ['/index.js', '/index.json', '/index.node'];
for (const ext of extensions) {
const file = x + ext;
try {
await FS.access(file);
return file;
} catch {
// Do nothing, continue to next extension
}
}
return null;
}
async function loadAsDirectory(x) {
const pkgJsonFile = Path.join(x, 'package.json');
try {
await FS.access(pkgJsonFile);
const pkgJson = JSON.parse(await FS.readFile(pkgJsonFile));
if (pkgJson.main) {
const mainFile = Path.join(x, pkgJson.main);
return (await loadAsFile(mainFile)) || (await loadIndex(mainFile));
}
} catch {
// Do nothing, continue to next step
}
return await loadIndex(x);
}
async function nodeModulesPaths(start) {
const parts = start.split(Path.sep);
const dirs = [];
for (let i = parts.length - 1; i >= 0; i--) {
if (parts[i] === 'node_modules') continue;
const dir = Path.join(...parts.slice(0, i + 1), 'node_modules');
dirs.unshift(dir);
}
// You should add global folders if needed
return dirs;
}
async function loadNodeModules(x, start) {
const dirs = await nodeModulesPaths(start);
for (const dir of dirs) {
const exportsResult = await loadPackageExports(x, dir);
if (exportsResult) return exportsResult;
const fileResult = await loadAsFile(Path.join(dir, x));
if (fileResult) return fileResult;
const dirResult = await loadAsDirectory(Path.join(dir, x));
if (dirResult) return dirResult;
}
return null;
}
async function loadPackageSelf(x, dir) {
const scope = await findClosestPackageScope(dir);
if (!scope) return null;
const pkgJson = JSON.parse(await FS.readFile(Path.join(scope, 'package.json')));
if (!pkgJson.exports || pkgJson.name !== x.split('/')[0]) return null;
const basePath = pathToFileURL(scope);
const match = await resolvePackageExports(basePath, '.' + x.slice(pkgJson.name.length), pkgJson.exports, ['node', 'require']);
return await resolveEsmMatch(match);
}
async function findClosestPackageScope(dir) {
if (dir === Path.sep) return null;
try {
await FS.access(Path.join(dir, 'package.json'));
return dir;
} catch {
// Continue to parent directory
}
return await findClosestPackageScope(Path.dirname(dir));
}
export async function resolve(x, y) {
if (isCoreModule(x)) {
return x;
}
if (x.startsWith('/')) {
y = Path.sep;
}
if (x.startsWith('./') || x.startsWith('/') || x.startsWith('../')) {
const fullPath = Path.resolve(y, x);
const result =
(await loadAsFile(fullPath)) ||
(await loadAsDirectory(fullPath)) ||
(await loadIndex(fullPath));
if (result) return result;
throw new Error(`Module not found: ${x}`);
}
if (x.startsWith('#')) {
const result = await loadPackageImports(x, Path.dirname(y));
if (result) return result;
throw new Error(`Module not found: ${x}`);
}
const result =
(await loadPackageSelf(x, Path.dirname(y))) ||
(await loadNodeModules(x, Path.dirname(y)));
if (result) return result;
throw new Error(`Module not found: ${x}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment