Skip to content

Commit

Permalink
Merge pull request #5 from hildjj/cache
Browse files Browse the repository at this point in the history
Add caching
  • Loading branch information
hildjj authored Feb 24, 2024
2 parents 105a6d4 + 9b25eb0 commit 1130296
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 61 deletions.
36 changes: 30 additions & 6 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
declare function _exports(code: string, options: FromMemOptions): Promise<unknown>;
export = _exports;
export = fromMem;
/**
* Import or require the given code from memory. Knows about the different
* Peggy output formats. Returns the exports of the module.
*
* @param {string} code Code to import
* @param {FromMemOptions} options Options. Most important is filename.
* @returns {Promise<unknown>} The evaluated code.
*/
declare function fromMem(code: string, options: FromMemOptions): Promise<unknown>;
declare namespace fromMem {
export { guessModuleType, FromMemOptions, ModuleType };
}
/**
* Options for how to process code.
*/
export type FromMemOptions = {
type FromMemOptions = {
/**
* What format does the code have? Throws an error if the format is not
* "commonjs", "es", "umd", or "bare".
* What format does the code have? "guess" means to read the closest
* package.json file looking for the "type" key.
*/
format?: "amd" | "bare" | "commonjs" | "es" | "globals" | "umd" | undefined;
format?: "amd" | "bare" | "commonjs" | "es" | "globals" | "guess" | "umd" | undefined;
/**
* What is the fully-qualified synthetic
* filename for the code? Most important is the directory, which is used to
Expand All @@ -31,3 +42,16 @@ export type FromMemOptions = {
*/
globalExport?: string | undefined;
};
/**
* Figure out the module type for the given file. If no package.json is
* found, default to "commonjs".
*
* @param {string} filename Fully-qualified filename to start from.
* @returns {Promise<ModuleType>}
* @throws On invalid package.json
*/
declare function guessModuleType(filename: string): Promise<ModuleType>;
declare namespace guessModuleType {
function clearCache(): void;
}
type ModuleType = "commonjs" | "es";
40 changes: 35 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,21 @@ async function importString(code, dirname, options) {
return mod.namespace;
}

/**
* @typedef {"commonjs"|"es"} ModuleType
*/

/**
* @type Record<string, ModuleType>
*/
let cache = {};

/**
* Figure out the module type for the given file. If no package.json is
* found, default to "commonjs".
*
* @param {string} filename Fully-qualified filename to start from.
* @returns {Promise<"commonjs"|"es">}
* @returns {Promise<ModuleType>}
* @throws On invalid package.json
*/
async function guessModuleType(filename) {
Expand All @@ -167,13 +176,23 @@ async function guessModuleType(filename) {
default:
// Fall-through
}

/** @type {ModuleType} */
let res = "commonjs";
let dir = fp.dir;
let prev = undefined;
const pending = [];
while (dir !== prev) {
const cached = cache[dir];
if (cached) {
return cached;
}
pending.push(dir);
try {
const pkg = await fs.readFile(path.join(dir, "package.json"), "utf8");
const pkgj = JSON.parse(pkg);
return (pkgj.type === "module") ? "es" : "commonjs";
res = (pkgj.type === "module") ? "es" : "commonjs";
break;
} catch (err) {
// If the file just didn't exist, keep going.
if (/** @type {NodeJS.ErrnoException} */ (err).code !== "ENOENT") {
Expand All @@ -183,9 +202,16 @@ async function guessModuleType(filename) {
prev = dir;
dir = path.dirname(dir);
}
return "commonjs";
for (const p of pending) {
cache[p] = res;
}
return res;
}

guessModuleType.clearCache = function clearCache() {
cache = {};
};

/**
* Import or require the given code from memory. Knows about the different
* Peggy output formats. Returns the exports of the module.
Expand All @@ -194,7 +220,7 @@ async function guessModuleType(filename) {
* @param {FromMemOptions} options Options. Most important is filename.
* @returns {Promise<unknown>} The evaluated code.
*/
module.exports = async function fromMem(code, options) {
async function fromMem(code, options) {
options = {
format: "commonjs",
context: {},
Expand Down Expand Up @@ -239,4 +265,8 @@ module.exports = async function fromMem(code, options) {
default:
throw new Error(`Unsupported output format: "${options.format}"`);
}
};
}

fromMem.guessModuleType = guessModuleType;

module.exports = fromMem;
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
"author": "Joe Hildebrand <[email protected]>",
"license": "MIT",
"devDependencies": {
"@peggyjs/eslint-config": "3.2.2",
"@types/node": "20.11.19",
"@types/semver": "7.5.7",
"@peggyjs/eslint-config": "3.2.3",
"@types/node": "20.11.20",
"@types/semver": "7.5.8",
"c8": "9.1.0",
"eslint": "8.56.0",
"eslint": "8.57.0",
"typescript": "5.3.3"
},
"packageManager": "[email protected]",
Expand Down
92 changes: 46 additions & 46 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1130296

Please sign in to comment.