Skip to content

Commit

Permalink
module: expose getPackageScopeConfig & findNearestPackageJSON utils
Browse files Browse the repository at this point in the history
  • Loading branch information
JakobJingleheimer committed Sep 29, 2024
1 parent 4062b3f commit 3fdbcd2
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 35 deletions.
40 changes: 30 additions & 10 deletions lib/internal/modules/package_json_reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@ const modulesBinding = internalBinding('modules');
const { resolve, sep } = require('path');
const { kEmptyObject } = require('internal/util');

/**
* @typedef {import('typings/internalBinding/modules').FullPackageConfig} FullPackageConfig
* @typedef {import('typings/internalBinding/modules').PackageConfig} PackageConfig
* @typedef {import('typings/internalBinding/modules').SerializedPackageConfig} SerializedPackageConfig
*/

/**
* @param {string} path
* @param {import('typings/internalBinding/modules').SerializedPackageConfig} contents
* @returns {import('typings/internalBinding/modules').PackageConfig}
* @param {SerializedPackageConfig} contents
* @param {boolean} everything
* @returns {everything extends true ? FullPackageConfig : PackageConfig}
*/
function deserializePackageJSON(path, contents) {
function deserializePackageJSON(path, contents, everything = false) {
if (contents === undefined) {
return {
__proto__: null,
Expand Down Expand Up @@ -64,6 +71,7 @@ function deserializePackageJSON(path, contents) {
ObjectDefineProperty(this, 'exports', { __proto__: null, value });
return this.exports;
},
...(everything && contents[6]),
};
}

Expand All @@ -75,7 +83,7 @@ function deserializePackageJSON(path, contents) {
* specifier?: URL | string,
* isESM?: boolean,
* }} options
* @returns {import('typings/internalBinding/modules').PackageConfig}
* @returns {PackageConfig}
*/
function read(jsonPath, { base, specifier, isESM } = kEmptyObject) {
// This function will be called by both CJS and ESM, so we need to make sure
Expand Down Expand Up @@ -105,16 +113,17 @@ function readPackage(requestPath) {
* Get the nearest parent package.json file from a given path.
* Return the package.json data and the path to the package.json file, or undefined.
* @param {string} checkPath The path to start searching from.
* @returns {undefined | {data: import('typings/internalBinding/modules').PackageConfig, path: string}}
* @param {boolean} everything Whether to include unrecognised fields.
* @returns {undefined | {data: PackageConfig, path: string}}
*/
function getNearestParentPackageJSON(checkPath) {
function getNearestParentPackageJSON(checkPath, everything = false) {
const result = modulesBinding.getNearestParentPackageJSON(checkPath);

if (result === undefined) {
return undefined;
}

const data = deserializePackageJSON(checkPath, result);
const data = deserializePackageJSON(checkPath, result, everything);

// Path should be the root folder of the matched package.json
// For example for ~/path/package.json, it should be ~/path
Expand All @@ -123,16 +132,26 @@ function getNearestParentPackageJSON(checkPath) {
return { data, path };
}

/**
* Find the nearest package.json
* @param {URL['pathname']} origin Where to start searching.
* @returns {URL['pathname']} The fully resolved location of the package.json file.
*/
function findNearestPackageJSON(origin) {
return modulesBinding.findNearestPackageJSON(origin);
}

/**
* Returns the package configuration for the given resolved URL.
* @param {URL | string} resolved - The resolved URL.
* @returns {import('typings/internalBinding/modules').PackageConfig} - The package configuration.
* @param {boolean} everything - Whether to include unrecognised fields.
* @returns {PackageConfig} - The package configuration.
*/
function getPackageScopeConfig(resolved) {
function getPackageScopeConfig(resolved, everything = false) {
const result = modulesBinding.getPackageScopeConfig(`${resolved}`);

if (ArrayIsArray(result)) {
return deserializePackageJSON(`${resolved}`, result);
return deserializePackageJSON(`${resolved}`, result, everything);
}

// This means that the response is a string
Expand Down Expand Up @@ -160,4 +179,5 @@ module.exports = {
getNearestParentPackageJSON,
getPackageScopeConfig,
getPackageType,
findNearestPackageJSON,
};
6 changes: 6 additions & 0 deletions lib/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const {
flushCompileCache,
getCompileCacheDir,
} = require('internal/modules/helpers');
const {
getPackageScopeConfig,
findNearestPackageJSON,
} = require('internal/modules/package_json_reader');

Module.findSourceMap = findSourceMap;
Module.register = register;
Expand All @@ -19,4 +23,6 @@ Module.enableCompileCache = enableCompileCache;
Module.flushCompileCache = flushCompileCache;

Module.getCompileCacheDir = getCompileCacheDir;
Module.getPackageScopeConfig = getPackageScopeConfig;
Module.findNearestPackageJSON = findNearestPackageJSON;
module.exports = Module;
43 changes: 18 additions & 25 deletions src/node_modules.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,9 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
return nullptr;
}

void BindingData::GetNearestParentPackageJSON(
const v8::FunctionCallbackInfo<v8::Value>& args) {
void BindingData::FindNearestParentPackageJSON(
const v8::FunctionCallbackInfo<v8::Value>& args
) {
CHECK_GE(args.Length(), 1);
CHECK(args[0]->IsString());

Expand All @@ -331,41 +332,32 @@ void BindingData::GetNearestParentPackageJSON(
path_value_str.push_back(kPathSeparator);
}

auto package_json =
TraverseParent(realm, std::filesystem::path(path_value_str));
args.GetReturnValue().Set(path_value_str);
}

void BindingData::GetNearestParentPackageJSON(
const v8::FunctionCallbackInfo<v8::Value>& args
) {
auto path = FindNearestParentPackageJSON(args);

auto package_json = TraverseParent(realm, std::filesystem::path(path_value_str));

if (package_json != nullptr) {
args.GetReturnValue().Set(package_json->Serialize(realm));
}
}

void BindingData::GetNearestParentPackageJSONType(
const FunctionCallbackInfo<Value>& args) {
CHECK_GE(args.Length(), 1);
CHECK(args[0]->IsString());

Realm* realm = Realm::GetCurrent(args);
BufferValue path_value(realm->isolate(), args[0]);
// Check if the path has a trailing slash. If so, add it after
// ToNamespacedPath() as it will be deleted by ToNamespacedPath()
bool slashCheck = path_value.ToStringView().ends_with(kPathSeparator);

ToNamespacedPath(realm->env(), &path_value);

std::string path_value_str = path_value.ToString();
if (slashCheck) {
path_value_str.push_back(kPathSeparator);
}

auto package_json =
TraverseParent(realm, std::filesystem::path(path_value_str));
const FunctionCallbackInfo<Value>& args
) {
auto package_json = GetNearestParentPackageJSON(args);

if (package_json == nullptr) {
return;
}

Local<Value> value =
ToV8Value(realm->context(), package_json->type).ToLocalChecked();
Local<Value> value = ToV8Value(realm->context(), package_json->type).ToLocalChecked();

args.GetReturnValue().Set(value);
}

Expand Down Expand Up @@ -497,6 +489,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
SetMethod(isolate, target, "getPackageScopeConfig", GetPackageScopeConfig);
SetMethod(isolate, target, "enableCompileCache", EnableCompileCache);
SetMethod(isolate, target, "getCompileCacheDir", GetCompileCacheDir);
SetMethod(isolate, target, "findNearestPackageJSON", FindNearestParentPackageJSON);
SetMethod(isolate, target, "flushCompileCache", FlushCompileCache);
}

Expand Down
4 changes: 4 additions & 0 deletions typings/internalBinding/modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export type PackageConfig = {
exports?: string | string[] | Record<string, unknown>
imports?: string | string[] | Record<string, unknown>
}
export type FullPackageConfig = PackageConfig & {
[key: string]: unknown,
}
export type SerializedPackageConfig = [
PackageConfig['name'],
PackageConfig['main'],
Expand All @@ -23,4 +26,5 @@ export interface ModulesBinding {
getNearestParentPackageJSONType(path: string): PackageConfig['type']
getPackageScopeConfig(path: string): SerializedPackageConfig | undefined
getPackageJSONScripts(): string | undefined
findNearestPackageJSON(origin: URL['pathname']): URL['pathname'] | undefined
}

0 comments on commit 3fdbcd2

Please sign in to comment.