Skip to content

Commit

Permalink
fix: more robust calculation of default location for code generation (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ymc9 authored Mar 7, 2024
1 parent d3629be commit d11d4ba
Show file tree
Hide file tree
Showing 18 changed files with 72 additions and 50 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zenstack-monorepo",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "",
"scripts": {
"build": "pnpm -r build",
Expand Down
2 changes: 1 addition & 1 deletion packages/ide/jetbrains/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
}

group = "dev.zenstack"
version = "2.0.0-alpha.4"
version = "2.0.0-alpha.5"

repositories {
mavenCentral()
Expand Down
2 changes: 1 addition & 1 deletion packages/ide/jetbrains/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jetbrains",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"displayName": "ZenStack JetBrains IDE Plugin",
"description": "ZenStack JetBrains IDE plugin",
"homepage": "https://zenstack.dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/language/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/language",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"displayName": "ZenStack modeling language compiler",
"description": "ZenStack modeling language compiler",
"homepage": "https://zenstack.dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/misc/redwood/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/redwood",
"displayName": "ZenStack RedwoodJS Integration",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/openapi/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/openapi",
"displayName": "ZenStack Plugin and Runtime for OpenAPI",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "ZenStack plugin and runtime supporting OpenAPI",
"main": "index.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/swr/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/swr",
"displayName": "ZenStack plugin for generating SWR hooks",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "ZenStack plugin for generating SWR hooks",
"main": "index.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/tanstack-query/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/tanstack-query",
"displayName": "ZenStack plugin for generating tanstack-query hooks",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "ZenStack plugin for generating tanstack-query hooks",
"main": "index.js",
"exports": {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/trpc/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/trpc",
"displayName": "ZenStack plugin for tRPC",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "ZenStack plugin for tRPC",
"main": "index.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/runtime",
"displayName": "ZenStack Runtime Library",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "Runtime of ZenStack for both client-side and server-side environments.",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"publisher": "zenstack",
"displayName": "ZenStack Language Tools",
"description": "Build scalable web apps with minimum code by defining authorization and validation rules inside the data schema that closer to the database",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"author": {
"name": "ZenStack Team"
},
Expand Down
32 changes: 21 additions & 11 deletions packages/schema/src/plugins/plugin-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PluginGlobalOptions } from '@zenstackhq/sdk';
import fs from 'fs';
import path from 'path';
import { PluginRunnerOptions } from '../cli/plugin-runner';
import { getPackageManager } from '../utils/pkg-utils';

export const ALL_OPERATION_KINDS: PolicyOperationKind[] = ['create', 'update', 'postUpdate', 'read', 'delete'];

Expand Down Expand Up @@ -76,23 +77,32 @@ export function getDefaultOutputFolder(globalOptions?: PluginGlobalOptions) {
return path.resolve(globalOptions.output);
}

// Find the real runtime module path, it might be a symlink in pnpm
let runtimeModulePath = require.resolve('@zenstackhq/runtime');

// for testing, use the local node_modules
if (process.env.ZENSTACK_TEST === '1') {
// handle the case when running as tests, resolve relative to CWD
runtimeModulePath = path.resolve(path.join(process.cwd(), 'node_modules', '@zenstackhq', 'runtime'));
return path.join(process.cwd(), 'node_modules', DEFAULT_RUNTIME_LOAD_PATH);
}

if (runtimeModulePath) {
// start with the parent folder of @zenstackhq, supposed to be a node_modules folder
while (!runtimeModulePath.endsWith('@zenstackhq') && runtimeModulePath !== '/') {
const { projectRoot } = getPackageManager(__dirname);
if (fs.existsSync(path.join(projectRoot, 'node_modules'))) {
// use the located node_modules folder
return path.join(projectRoot, 'node_modules', DEFAULT_RUNTIME_LOAD_PATH);
} else {
// unable to locate a node_modules folder, fallback to where the runtime
// package resides

// find the real runtime module path, it might be a symlink in pnpm
let runtimeModulePath = require.resolve('@zenstackhq/runtime');

if (runtimeModulePath) {
// start with the parent folder of @zenstackhq, supposed to be a node_modules folder
while (!runtimeModulePath.endsWith('@zenstackhq') && runtimeModulePath !== '/') {
runtimeModulePath = path.join(runtimeModulePath, '..');
}
runtimeModulePath = path.join(runtimeModulePath, '..');
}
runtimeModulePath = path.join(runtimeModulePath, '..');
const modulesFolder = getNodeModulesFolder(runtimeModulePath);
return modulesFolder ? path.join(modulesFolder, DEFAULT_RUNTIME_LOAD_PATH) : undefined;
}
const modulesFolder = getNodeModulesFolder(runtimeModulePath);
return modulesFolder ? path.join(modulesFolder, DEFAULT_RUNTIME_LOAD_PATH) : undefined;
}

/**
Expand Down
43 changes: 24 additions & 19 deletions packages/schema/src/utils/pkg-utils.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import fs from 'node:fs';
import path from 'node:path';
import { execSync } from './exec-utils';
import { match } from 'ts-pattern';

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
* @template e A type parameter that extends boolean
*/
export type FindUp<e extends boolean> = e extends true ? string[] | undefined : string | undefined
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.
* 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
Expand All @@ -27,7 +28,12 @@ export type FindUp<e extends boolean> = e extends true ? string[] | undefined :
* @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> {
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>;
Expand All @@ -37,23 +43,22 @@ export function findUp<e extends boolean = false>(names: string[], cwd: string =
return findUp(names, up, multiple, result);
}

function getPackageManager(projectPath = '.'): PackageManagers {
const lockFile = findUp(['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json'], projectPath);
export function getPackageManager(searchStartPath = '.') {
const lockFile = findUp(['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json'], searchStartPath);

if (!lockFile) {
// default use npm
return 'npm';
return { packageManager: 'npm', lockFile: undefined, projectRoot: searchStartPath };
}

switch (path.basename(lockFile)) {
case 'yarn.lock':
return 'yarn';
case 'pnpm-lock.yaml':
return 'pnpm';
default:
return 'npm';
}
const packageManager = match(path.basename(lockFile))
.with('yarn.lock', () => 'yarn')
.with('pnpm-lock.yaml', () => 'pnpm')
.otherwise(() => 'npm');

return { packageManager, lockFile, projectRoot: path.dirname(lockFile) };
}

export function installPackage(
pkg: string,
dev: boolean,
Expand Down Expand Up @@ -106,7 +111,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
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/sdk",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "ZenStack plugin development SDK",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/server",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"displayName": "ZenStack Server-side Adapters",
"description": "ZenStack server-side adapters",
"homepage": "https://zenstack.dev",
Expand Down
9 changes: 5 additions & 4 deletions packages/server/src/shared.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import type { ModelMeta, PolicyDef, ZodSchemas } from '@zenstackhq/runtime';
import { DEFAULT_RUNTIME_LOAD_PATH, type ModelMeta, type PolicyDef, type ZodSchemas } from '@zenstackhq/runtime';
import path from 'path';
import { AdapterBaseOptions } from './types';

Expand Down Expand Up @@ -39,7 +39,8 @@ export function getDefaultModelMeta(loadPath: string | undefined): ModelMeta {
if (process.env.ZENSTACK_TEST === '1' && !loadPath) {
try {
// special handling for running as tests, try resolving relative to CWD
return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'model-meta')).default;
return require(path.join(process.cwd(), 'node_modules', DEFAULT_RUNTIME_LOAD_PATH, 'model-meta'))
.default;
} catch {
throw new Error('Model meta cannot be loaded. Please make sure "zenstack generate" has been run.');
}
Expand All @@ -66,7 +67,7 @@ export function getDefaultPolicy(loadPath: string | undefined): PolicyDef {
if (process.env.ZENSTACK_TEST === '1' && !loadPath) {
try {
// special handling for running as tests, try resolving relative to CWD
return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'policy')).default;
return require(path.join(process.cwd(), 'node_modules', DEFAULT_RUNTIME_LOAD_PATH, 'policy')).default;
} catch {
throw new Error(
'Policy definition cannot be loaded from default location. Please make sure "zenstack generate" has been run.'
Expand Down Expand Up @@ -97,7 +98,7 @@ export function getDefaultZodSchemas(loadPath: string | undefined): ZodSchemas |
if (process.env.ZENSTACK_TEST === '1' && !loadPath) {
try {
// special handling for running as tests, try resolving relative to CWD
return require(path.join(process.cwd(), 'node_modules', '.zenstack', 'zod'));
return require(path.join(process.cwd(), 'node_modules', DEFAULT_RUNTIME_LOAD_PATH, 'zod'));
} catch {
return undefined;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/testtools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/testtools",
"version": "2.0.0-alpha.4",
"version": "2.0.0-alpha.5",
"description": "ZenStack Test Tools",
"main": "index.js",
"private": true,
Expand Down
10 changes: 8 additions & 2 deletions packages/testtools/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { DMMF } from '@prisma/generator-helper';
import type { Model } from '@zenstackhq/language/ast';
import type { AuthUser, CrudContract, EnhancementKind, EnhancementOptions } from '@zenstackhq/runtime';
import {
DEFAULT_RUNTIME_LOAD_PATH,
type AuthUser,
type CrudContract,
type EnhancementKind,
type EnhancementOptions,
} from '@zenstackhq/runtime';
import { getDMMF } from '@zenstackhq/sdk';
import { execSync } from 'child_process';
import * as fs from 'fs';
Expand Down Expand Up @@ -284,7 +290,7 @@ export async function loadSchema(schema: string, options?: SchemaLoadOptions) {
? path.isAbsolute(opt.output)
? opt.output
: path.join(projectRoot, opt.output)
: path.join(projectRoot, 'node_modules', '.zenstack');
: path.join(projectRoot, 'node_modules', DEFAULT_RUNTIME_LOAD_PATH);

const policy = require(path.join(outputPath, 'policy')).default;
const modelMeta = require(path.join(outputPath, 'model-meta')).default;
Expand Down

0 comments on commit d11d4ba

Please sign in to comment.