From 14090267bc9ed90ac9701250e0301584bd948c48 Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Tue, 20 Feb 2024 21:33:45 +0000 Subject: [PATCH 1/7] refactor(pkg-utils.ts): improve findUp function to support searching for multiple paths and add detailed JSDoc comments for better understanding and documentation --- packages/schema/src/utils/pkg-utils.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/schema/src/utils/pkg-utils.ts b/packages/schema/src/utils/pkg-utils.ts index ce41dac34..c3890db39 100644 --- a/packages/schema/src/utils/pkg-utils.ts +++ b/packages/schema/src/utils/pkg-utils.ts @@ -5,8 +5,8 @@ import { execSync } from './exec-utils'; export type PackageManagers = 'npm' | 'yarn' | 'pnpm'; /** - * A type named FindUp that takes a type parameter e which extends boolean. - * If e extends true, it returns a union type of string[] or undefined. + * A type named FindUp that takes a type parameter e which extends boolean. + * If e extends true, it returns a union type of string[] or undefined. * If e does not extend true, it returns a union type of string or undefined. * * @export @@ -14,9 +14,9 @@ export type PackageManagers = 'npm' | 'yarn' | 'pnpm'; */ export type FindUp = e extends true ? string[] | undefined : string | undefined /** - * Find and return file paths by searching parent directories based on the given names list and current working directory (cwd) path. - * Optionally return a single path or multiple paths. - * If multiple allowed, return all paths found. + * Find and return file paths by searching parent directories based on the given names list and current working directory (cwd) path. + * Optionally return a single path or multiple paths. + * If multiple allowed, return all paths found. * If no paths are found, return undefined. * * @export @@ -106,7 +106,7 @@ export function ensurePackage( } /** - * A function that searches for the nearest package.json file starting from the provided search path or the current working directory if no search path is provided. + * A function that searches for the nearest package.json file starting from the provided search path or the current working directory if no search path is provided. * It iterates through the directory structure going one level up at a time until it finds a package.json file. If no package.json file is found, it returns undefined. * @deprecated Use findUp instead @see findUp */ From aba77842276fb08c250f4a1ac9edbc5e7751d14a Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Tue, 20 Feb 2024 22:13:40 +0000 Subject: [PATCH 2/7] feat(pkg-utils.ts): add findNodeModulesFile function to pkg-utils.ts Signed-off-by: Jonathan Stevens --- packages/schema/src/utils/pkg-utils.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/schema/src/utils/pkg-utils.ts b/packages/schema/src/utils/pkg-utils.ts index c3890db39..e01e1ab2a 100644 --- a/packages/schema/src/utils/pkg-utils.ts +++ b/packages/schema/src/utils/pkg-utils.ts @@ -37,6 +37,32 @@ export function findUp(names: string[], cwd: string = return findUp(names, up, multiple, result); } +/** + * A function that finds a file within the node_modules directory by the provided name. + * It first searches for the node_modules directory using the findUp function, and if not found, returns undefined. + * It then splits the provided name into folder and file parts. + * It finds the location of the folder in the node_modules directory by checking for its existence. + * If the folder is not found, it returns undefined. + * It then constructs the file location by joining the folder location and the file name with a '.zmodel' extension if the file does not already have an extension. + * Returns the file location if it exists, otherwise returns undefined. + * @author Jonathan Stevens (TGTGamer) + * + * @export + * @param name A string representing the name of the file to find in the node_modules folder + * @returns Path to a specific file within the node_modules directory + */ +export function findNodeModulesFile(name: string, cwd: string = process.cwd()) { + if (!name) return undefined; + const nodeModules = findUp(['node_modules'], cwd, true); + if (!nodeModules) return undefined; + const split = name.split('/') + const folder = split.slice(0, -1).join('/'); + const folderLocation = nodeModules.find((dir) =>fs.existsSync(path.join(dir, folder))); + if (!folderLocation) return undefined; + const fileLocation = path.join(folderLocation, name); + return fs.existsSync(fileLocation) ? fileLocation : undefined; +} + function getPackageManager(projectPath = '.'): PackageManagers { const lockFile = findUp(['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json'], projectPath); From 3e5b0d95a1c38120176d70159e3a0d66c5f870a3 Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Tue, 20 Feb 2024 22:34:57 +0000 Subject: [PATCH 3/7] feat(ast-utils.ts): add support for resolving import URIs with various conditions to handle different scenarios and improve flexibility in importing modules --- packages/schema/src/utils/ast-utils.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/schema/src/utils/ast-utils.ts b/packages/schema/src/utils/ast-utils.ts index 661f14b26..ce8c5a0f6 100644 --- a/packages/schema/src/utils/ast-utils.ts +++ b/packages/schema/src/utils/ast-utils.ts @@ -18,6 +18,7 @@ import { import { isFromStdlib } from '@zenstackhq/sdk'; import { AstNode, getDocument, LangiumDocuments, Mutable } from 'langium'; import { URI, Utils } from 'vscode-uri'; +import { findNodeModulesFile } from './pkg-utils'; export function extractDataModelsWithAllowRules(model: Model): DataModel[] { return model.declarations.filter( @@ -94,15 +95,23 @@ export function getDataModelFieldReference(expr: Expression): DataModelField | u } export function resolveImportUri(imp: ModelImport): URI | undefined { - if (imp.path === undefined || imp.path.length === 0) { - return undefined; + if (!imp.path) return undefined; // This will return true if imp.path is undefined, null, or an empty string (""). + + if (!imp.path.endsWith('.zmodel')) { + imp.path += '.zmodel'; } + + if ( + !imp.path.startsWith('.') // Respect relative paths + && !imp.path.startsWith('/') // Respect absolute paths (Unix) + && !/^[a-zA-Z]:\\/.test(imp.path) // Respect absolute paths (Windows) + ) { + imp.path = findNodeModulesFile(imp.path) ?? ''; + if (!imp.path) return undefined; // If the path is empty, return undefined + } + const dirUri = Utils.dirname(getDocument(imp).uri); - let grammarPath = imp.path; - if (!grammarPath.endsWith('.zmodel')) { - grammarPath += '.zmodel'; - } - return Utils.resolvePath(dirUri, grammarPath); + return Utils.resolvePath(dirUri, imp.path); } export function resolveTransitiveImports(documents: LangiumDocuments, model: Model): Model[] { From 5a5dcd4841c34b8326c79de325daab4b4d5b436f Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Wed, 21 Feb 2024 00:31:15 +0000 Subject: [PATCH 4/7] fix: incorrectly exiting with undefined when dependant function expects URI Signed-off-by: Jonathan Stevens --- packages/schema/src/utils/ast-utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/schema/src/utils/ast-utils.ts b/packages/schema/src/utils/ast-utils.ts index ce8c5a0f6..2d09fd0bb 100644 --- a/packages/schema/src/utils/ast-utils.ts +++ b/packages/schema/src/utils/ast-utils.ts @@ -106,8 +106,7 @@ export function resolveImportUri(imp: ModelImport): URI | undefined { && !imp.path.startsWith('/') // Respect absolute paths (Unix) && !/^[a-zA-Z]:\\/.test(imp.path) // Respect absolute paths (Windows) ) { - imp.path = findNodeModulesFile(imp.path) ?? ''; - if (!imp.path) return undefined; // If the path is empty, return undefined + imp.path = findNodeModulesFile(imp.path) ?? imp.path; } const dirUri = Utils.dirname(getDocument(imp).uri); From 3162606877f387a9797aa3377d220dba180c3d62 Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Fri, 15 Mar 2024 13:29:39 +0000 Subject: [PATCH 5/7] Refactor findNodeModulesFile function to use require.resolve Signed-off-by: Jonathan Stevens --- packages/schema/src/utils/pkg-utils.ts | 29 +++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/schema/src/utils/pkg-utils.ts b/packages/schema/src/utils/pkg-utils.ts index e01e1ab2a..3184807aa 100644 --- a/packages/schema/src/utils/pkg-utils.ts +++ b/packages/schema/src/utils/pkg-utils.ts @@ -38,14 +38,13 @@ export function findUp(names: string[], cwd: string = } /** - * A function that finds a file within the node_modules directory by the provided name. - * It first searches for the node_modules directory using the findUp function, and if not found, returns undefined. - * It then splits the provided name into folder and file parts. - * It finds the location of the folder in the node_modules directory by checking for its existence. - * If the folder is not found, it returns undefined. - * It then constructs the file location by joining the folder location and the file name with a '.zmodel' extension if the file does not already have an extension. + * A function that finds a file within the node_modules directory by the provided name. + * It first searches for the node_modules directory using the findUp function, and if not found, returns undefined. + * It then splits the provided name into folder and file parts. + * It finds the location of the folder in the node_modules directory by checking for its existence. + * If the folder is not found, it returns undefined. + * It then constructs the file location by joining the folder location and the file name with a '.zmodel' extension if the file does not already have an extension. * Returns the file location if it exists, otherwise returns undefined. - * @author Jonathan Stevens (TGTGamer) * * @export * @param name A string representing the name of the file to find in the node_modules folder @@ -53,14 +52,14 @@ export function findUp(names: string[], cwd: string = */ export function findNodeModulesFile(name: string, cwd: string = process.cwd()) { if (!name) return undefined; - const nodeModules = findUp(['node_modules'], cwd, true); - if (!nodeModules) return undefined; - const split = name.split('/') - const folder = split.slice(0, -1).join('/'); - const folderLocation = nodeModules.find((dir) =>fs.existsSync(path.join(dir, folder))); - if (!folderLocation) return undefined; - const fileLocation = path.join(folderLocation, name); - return fs.existsSync(fileLocation) ? fileLocation : undefined; + try { + // Use require.resolve to find the module/file. The paths option allows specifying the directory to start from. + const resolvedPath = require.resolve(name, { paths: [cwd] }) + return resolvedPath + } catch (error) { + // If require.resolve fails to find the module/file, it will throw an error. + return undefined + } } function getPackageManager(projectPath = '.'): PackageManagers { From c8c01683d8c4595af6c70264278a6d4eaac54258 Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Fri, 15 Mar 2024 13:29:54 +0000 Subject: [PATCH 6/7] Fix import resolution in ast-utils Signed-off-by: Jonathan Stevens --- packages/schema/src/utils/ast-utils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/schema/src/utils/ast-utils.ts b/packages/schema/src/utils/ast-utils.ts index 170a127ab..c752c837d 100644 --- a/packages/schema/src/utils/ast-utils.ts +++ b/packages/schema/src/utils/ast-utils.ts @@ -19,6 +19,7 @@ import { isFromStdlib } from '@zenstackhq/sdk'; import { AstNode, getDocument, LangiumDocuments, Mutable } from 'langium'; import { URI, Utils } from 'vscode-uri'; import { findNodeModulesFile } from './pkg-utils'; +import {isAbsolute} from 'node:path' export function extractDataModelsWithAllowRules(model: Model): DataModel[] { return model.declarations.filter( @@ -96,18 +97,17 @@ export function getDataModelFieldReference(expr: Expression): DataModelField | u export function resolveImportUri(imp: ModelImport): URI | undefined { if (!imp.path) return undefined; // This will return true if imp.path is undefined, null, or an empty string (""). - + if (!imp.path.endsWith('.zmodel')) { imp.path += '.zmodel'; } if ( !imp.path.startsWith('.') // Respect relative paths - && !imp.path.startsWith('/') // Respect absolute paths (Unix) - && !/^[a-zA-Z]:\\/.test(imp.path) // Respect absolute paths (Windows) + && !isAbsolute(imp.path) // Respect Absolute paths ) { imp.path = findNodeModulesFile(imp.path) ?? imp.path; - } + } const dirUri = Utils.dirname(getDocument(imp).uri); return Utils.resolvePath(dirUri, imp.path); From 817e3e800b7509666996dd88cd77b1738ac79a1e Mon Sep 17 00:00:00 2001 From: Jonathan Stevens Date: Sat, 16 Mar 2024 02:38:46 +0000 Subject: [PATCH 7/7] Docs: Refactor findNodeModulesFile function to use require.resolve Signed-off-by: Jonathan Stevens --- packages/schema/src/utils/pkg-utils.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/schema/src/utils/pkg-utils.ts b/packages/schema/src/utils/pkg-utils.ts index 3184807aa..99593dcd3 100644 --- a/packages/schema/src/utils/pkg-utils.ts +++ b/packages/schema/src/utils/pkg-utils.ts @@ -37,18 +37,17 @@ export function findUp(names: string[], cwd: string = return findUp(names, up, multiple, result); } + /** - * A function that finds a file within the node_modules directory by the provided name. - * It first searches for the node_modules directory using the findUp function, and if not found, returns undefined. - * It then splits the provided name into folder and file parts. - * It finds the location of the folder in the node_modules directory by checking for its existence. - * If the folder is not found, it returns undefined. - * It then constructs the file location by joining the folder location and the file name with a '.zmodel' extension if the file does not already have an extension. - * Returns the file location if it exists, otherwise returns undefined. + * Find a Node module/file given its name in a specific directory, with a fallback to the current working directory. + * If the name is empty, return undefined. + * Try to resolve the module/file using require.resolve with the specified directory as the starting point. + * Return the resolved path if successful, otherwise return undefined. * * @export - * @param name A string representing the name of the file to find in the node_modules folder - * @returns Path to a specific file within the node_modules directory + * @param {string} name The name of the module/file to find + * @param {string} [cwd=process.cwd()] + * @returns {*} Finds a specified module or file using require.resolve starting from a specified directory path, or the current working directory if not provided. */ export function findNodeModulesFile(name: string, cwd: string = process.cwd()) { if (!name) return undefined;