Skip to content

Commit

Permalink
Refactor: find up (#1019)
Browse files Browse the repository at this point in the history
  • Loading branch information
TGTGamer authored Feb 22, 2024
1 parent 65473bb commit 4bf812e
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 18 deletions.
4 changes: 2 additions & 2 deletions packages/schema/src/cli/cli-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { PLUGIN_MODULE_NAME, STD_LIB_MODULE_NAME } from '../language-server/cons
import { ZModelFormatter } from '../language-server/zmodel-formatter';
import { createZModelServices, ZModelServices } from '../language-server/zmodel-module';
import { mergeBaseModel, resolveImport, resolveTransitiveImports } from '../utils/ast-utils';
import { findPackageJson } from '../utils/pkg-utils';
import { findUp } from '../utils/pkg-utils';
import { getVersion } from '../utils/version-utils';
import { CliError } from './cli-error';

Expand Down Expand Up @@ -280,7 +280,7 @@ export async function formatDocument(fileName: string) {

export function getDefaultSchemaLocation() {
// handle override from package.json
const pkgJsonPath = findPackageJson();
const pkgJsonPath = findUp(['package.json']);
if (pkgJsonPath) {
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
if (typeof pkgJson?.zenstack?.schema === 'string') {
Expand Down
4 changes: 2 additions & 2 deletions packages/schema/src/plugins/prisma/schema-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import { name } from '.';
import { getStringLiteral } from '../../language-server/validator/utils';
import telemetry from '../../telemetry';
import { execPackage } from '../../utils/exec-utils';
import { findPackageJson } from '../../utils/pkg-utils';
import { findUp } from '../../utils/pkg-utils';
import {
ModelFieldType,
AttributeArg as PrismaAttributeArg,
Expand Down Expand Up @@ -450,7 +450,7 @@ export default class PrismaSchemaGenerator {

export function getDefaultPrismaOutputFile(schemaPath: string) {
// handle override from package.json
const pkgJsonPath = findPackageJson(path.dirname(schemaPath));
const pkgJsonPath = findUp(['package.json'], path.dirname(schemaPath));
if (pkgJsonPath) {
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
if (typeof pkgJson?.zenstack?.prisma === 'string') {
Expand Down
53 changes: 39 additions & 14 deletions packages/schema/src/utils/pkg-utils.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
import fs from 'fs';
import path from 'path';
import fs from 'node:fs';
import path from 'node:path';
import { execSync } from './exec-utils';

export type PackageManagers = 'npm' | 'yarn' | 'pnpm';

function findUp(names: string[], cwd: string): string | undefined {
let dir = cwd;
// eslint-disable-next-line no-constant-condition
while (true) {
const target = names.find((name) => fs.existsSync(path.join(dir, name)));
if (target) return target;

const up = path.resolve(dir, '..');
if (up === dir) return undefined; // it'll fail anyway
dir = up;
}
/**
* 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
* @template e A type parameter that extends boolean
*/
export type FindUp<e extends boolean> = 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.
* If no paths are found, return undefined.
*
* @export
* @template [e=false]
* @param names An array of strings representing names to search for within the directory
* @param cwd A string representing the current working directory
* @param [multiple=false as e] A boolean flag indicating whether to search for multiple levels. Useful for finding node_modules directories...
* @param [result=[]] An array of strings representing the accumulated results used in multiple results
* @returns Path(s) to a specific file or folder within the directory or parent directories
*/
export function findUp<e extends boolean = false>(names: string[], cwd: string = process.cwd(), multiple: e = false as e, result: string[] = []): FindUp<e> {
if (!names.some((name) => !!name)) return undefined;
const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
if (multiple == false && target) return path.join(cwd, target) as FindUp<e>;
if (target) result.push(path.join(cwd, target));
const up = path.resolve(cwd, '..');
if (up === cwd) return (multiple && result.length > 0 ? result : undefined) as FindUp<e>; // it'll fail anyway
return findUp(names, up, multiple, result);
}

function getPackageManager(projectPath = '.'): PackageManagers {
Expand Down Expand Up @@ -85,6 +105,11 @@ 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.
* 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
*/
export function findPackageJson(searchPath?: string) {
let currDir = searchPath ?? process.cwd();
while (currDir) {
Expand All @@ -102,7 +127,7 @@ export function findPackageJson(searchPath?: string) {
}

export function getPackageJson(searchPath?: string) {
const pkgJsonPath = findPackageJson(searchPath);
const pkgJsonPath = findUp(['package.json'], searchPath ?? process.cwd());
if (pkgJsonPath) {
return JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
} else {
Expand Down

0 comments on commit 4bf812e

Please sign in to comment.