Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge dev to main (v1.11.0) #1146

Merged
merged 3 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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": "1.10.3",
"version": "1.11.0",
"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 = "1.10.3"
version = "1.11.0"

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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"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": "1.10.3",
"version": "1.11.0",
"author": {
"name": "ZenStack Team"
},
Expand Down
22 changes: 15 additions & 7 deletions packages/schema/src/utils/ast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
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(
Expand Down Expand Up @@ -94,15 +96,21 @@ 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';
}
const dirUri = Utils.dirname(getDocument(imp).uri);
let grammarPath = imp.path;
if (!grammarPath.endsWith('.zmodel')) {
grammarPath += '.zmodel';

if (
!imp.path.startsWith('.') // Respect relative paths
&& !isAbsolute(imp.path) // Respect Absolute paths
) {
imp.path = findNodeModulesFile(imp.path) ?? imp.path;
}
return Utils.resolvePath(dirUri, grammarPath);

const dirUri = Utils.dirname(getDocument(imp).uri);
return Utils.resolvePath(dirUri, imp.path);
ymc9 marked this conversation as resolved.
Show resolved Hide resolved
}

export function resolveTransitiveImports(documents: LangiumDocuments, model: Model): Model[] {
Expand Down
36 changes: 30 additions & 6 deletions packages/schema/src/utils/pkg-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ 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
* @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.
* 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 @@ -37,6 +37,30 @@ export function findUp<e extends boolean = false>(names: string[], cwd: string =
return findUp(names, up, multiple, result);
}


/**
* 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 {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;
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
}
}
ymc9 marked this conversation as resolved.
Show resolved Hide resolved

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

Expand Down Expand Up @@ -106,7 +130,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": "1.10.3",
"version": "1.11.0",
"description": "ZenStack plugin development SDK",
"main": "index.js",
"scripts": {
Expand Down
9 changes: 6 additions & 3 deletions packages/sdk/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,14 @@ export function isIdField(field: DataModelField) {
return true;
}

// NOTE: we have to use name to match fields because the fields
// may be inherited from an abstract base and have cloned identities

const model = field.$container as DataModel;

// model-level @@id attribute with a list of fields
const modelLevelIds = getModelIdFields(model);
if (modelLevelIds.includes(field)) {
if (modelLevelIds.map((f) => f.name).includes(field.name)) {
return true;
}

Expand All @@ -234,12 +237,12 @@ export function isIdField(field: DataModelField) {
// then, the first field with @unique can be used as id
const firstUniqueField = model.fields.find((f) => hasAttribute(f, '@unique'));
if (firstUniqueField) {
return firstUniqueField === field;
return firstUniqueField.name === field.name;
}

// last, the first model level @@unique can be used as id
const modelLevelUnique = getModelUniqueFields(model);
if (modelLevelUnique.includes(field)) {
if (modelLevelUnique.map((f) => f.name).includes(field.name)) {
return true;
}

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": "1.10.3",
"version": "1.11.0",
"displayName": "ZenStack Server-side Adapters",
"description": "ZenStack server-side adapters",
"homepage": "https://zenstack.dev",
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": "1.10.3",
"version": "1.11.0",
"description": "ZenStack Test Tools",
"main": "index.js",
"private": true,
Expand Down
87 changes: 87 additions & 0 deletions tests/integration/tests/regression/issue-1129.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { createPostgresDb, dropPostgresDb, loadSchema } from '@zenstackhq/testtools';

describe('Regression for issue 1129', () => {
it('regression', async () => {
let prisma;
const dbUrl = await createPostgresDb('regression-issue-1129');

try {
const r = await loadSchema(
`
model Relation1 {
id String @id @default(cuid())
field1 String
concrete Concrete[]
@@allow('all', true)
}

model Relation2 {
id String @id @default(cuid())
field2 String
concrete Concrete[]
@@allow('all', true)
}

abstract model WithRelation1 {
relation1Id String
relation1 Relation1 @relation(fields: [relation1Id], references: [id])
}
abstract model WithRelation2 {
relation2Id String
relation2 Relation2 @relation(fields: [relation2Id], references: [id])
}

model Concrete extends WithRelation1, WithRelation2 {
concreteField String
@@id([relation1Id, relation2Id])
@@allow('all', true)
}
`,
{ provider: 'postgresql', dbUrl }
);

prisma = r.prisma;
const db = r.enhance();

await db.$transaction(async (tx: any) => {
await tx.relation2.createMany({
data: [
{
id: 'relation2Id1',
field2: 'field2Value1',
},
{
id: 'relation2Id2',
field2: 'field2Value2',
},
],
});

await tx.relation1.create({
data: {
field1: 'field1Value',
concrete: {
createMany: {
data: [
{
concreteField: 'concreteFieldValue1',
relation2Id: 'relation2Id1',
},
{
concreteField: 'concreteFieldValue2',
relation2Id: 'relation2Id2',
},
],
},
},
},
});
});
} finally {
if (prisma) {
await prisma.$disconnect();
}
await dropPostgresDb('regression-issue-1129');
}
});
ymc9 marked this conversation as resolved.
Show resolved Hide resolved
});
Loading