Skip to content
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.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"description": "",
"scripts": {
"build": "pnpm -r build",
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.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"displayName": "ZenStack modeling language compiler",
"description": "ZenStack modeling language compiler",
"homepage": "https://zenstack.dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/next",
"version": "1.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"displayName": "ZenStack Next.js integration",
"description": "ZenStack Next.js integration",
"homepage": "https://zenstack.dev",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/react/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/react",
"displayName": "ZenStack plugin and runtime for ReactJS",
"version": "1.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"description": "ZenStack plugin and runtime for ReactJS",
"main": "index.js",
"repository": {
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.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"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.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"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": "A toolkit for building secure CRUD apps with Next.js + Typescript",
"version": "1.0.0-alpha.58",
"version": "1.0.0-alpha.60",
"author": {
"name": "ZenStack Team"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { IssueCodes, SCALAR_TYPES } from '../constants';
import { AstValidator } from '../types';
import { getIdFields, getUniqueFields } from '../utils';
import { validateAttributeApplication, validateDuplicatedDeclarations } from './utils';
import { getLiteral } from '@zenstackhq/sdk';

/**
* Validates data model declarations.
Expand Down Expand Up @@ -174,13 +175,15 @@ export default class DataModelValidator implements AstValidator<DataModel> {
const oppositeModelFields = field.type.reference?.ref?.fields as DataModelField[];
if (oppositeModelFields) {
for (const oppositeField of oppositeModelFields) {
const { name: oppositeRelationName } = this.parseRelation(oppositeField);
if (
oppositeRelationName === relationName &&
oppositeField.type.reference?.ref === field.$container
) {
// found an opposite relation field that points back to this field's type
return true;
// find the opposite relation with the matching name
const relAttr = oppositeField.attributes.find((a) => a.decl.ref?.name === '@relation');
if (relAttr) {
const relNameExpr = relAttr.args.find((a) => !a.name || a.name === 'name');
const relName = getLiteral<string>(relNameExpr?.value);
if (relName === relationName && oppositeField.type.reference?.ref === field.$container) {
// found an opposite relation field that points back to this field's type
return true;
}
}
}
}
Expand Down Expand Up @@ -253,13 +256,15 @@ export default class DataModelValidator implements AstValidator<DataModel> {
relationOwner = field;
}
} else {
[field, oppositeField].forEach((f) =>
accept(
'error',
'Field for one side of relation must carry @relation attribute with both "fields" and "references" fields',
{ node: f }
)
);
[field, oppositeField].forEach((f) => {
if (!this.isSelfRelation(f, thisRelation.name)) {
accept(
'error',
'Field for one side of relation must carry @relation attribute with both "fields" and "references" fields',
{ node: f }
);
}
});
return;
}

Expand Down
70 changes: 50 additions & 20 deletions packages/schema/src/plugins/prisma/prisma-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class Generator {
}

export class DeclarationBase {
public documentations: string[] = [];
constructor(public documentations: string[] = []) {}

addComment(name: string): string {
this.documentations.push(name);
Expand All @@ -91,26 +91,38 @@ export class DeclarationBase {
return this.documentations.map((x) => `${x}\n`).join('');
}
}
export class Model extends DeclarationBase {

export class ContainerDeclaration extends DeclarationBase {
constructor(documentations: string[] = [], public attributes: (ContainerAttribute | PassThroughAttribute)[] = []) {
super(documentations);
}
}

export class FieldDeclaration extends DeclarationBase {
constructor(documentations: string[] = [], public attributes: (FieldAttribute | PassThroughAttribute)[] = []) {
super(documentations);
}
}

export class Model extends ContainerDeclaration {
public fields: ModelField[] = [];
public attributes: ModelAttribute[] = [];
constructor(public name: string, public documentations: string[] = []) {
super();
constructor(public name: string, documentations: string[] = []) {
super(documentations);
}

addField(
name: string,
type: ModelFieldType | string,
attributes: FieldAttribute[] = [],
attributes: (FieldAttribute | PassThroughAttribute)[] = [],
documentations: string[] = []
): ModelField {
const field = new ModelField(name, type, attributes, documentations);
this.fields.push(field);
return field;
}

addAttribute(name: string, args: AttributeArg[] = []): ModelAttribute {
const attr = new ModelAttribute(name, args);
addAttribute(name: string, args: AttributeArg[] = []) {
const attr = new ContainerAttribute(name, args);
this.attributes.push(attr);
return attr;
}
Expand Down Expand Up @@ -145,14 +157,14 @@ export class ModelFieldType {
}
}

export class ModelField extends DeclarationBase {
export class ModelField extends FieldDeclaration {
constructor(
public name: string,
public type: ModelFieldType | string,
public attributes: FieldAttribute[] = [],
public documentations: string[] = []
attributes: (FieldAttribute | PassThroughAttribute)[] = [],
documentations: string[] = []
) {
super();
super(documentations, attributes);
}

addAttribute(name: string, args: AttributeArg[] = []): FieldAttribute {
Expand All @@ -178,14 +190,25 @@ export class FieldAttribute {
}
}

export class ModelAttribute {
export class ContainerAttribute {
constructor(public name: string, public args: AttributeArg[] = []) {}

toString(): string {
return `${this.name}(` + this.args.map((a) => a.toString()).join(', ') + `)`;
}
}

/**
* Represents @@prisma.passthrough and @prisma.passthrough
*/
export class PassThroughAttribute {
constructor(public text: string) {}

toString(): string {
return this.text;
}
}

export class AttributeArg {
constructor(public name: string | undefined, public value: AttributeArgValue) {}

Expand Down Expand Up @@ -287,22 +310,25 @@ export class FunctionCallArg {
}
}

export class Enum extends DeclarationBase {
export class Enum extends ContainerDeclaration {
public fields: EnumField[] = [];
public attributes: ModelAttribute[] = [];

constructor(public name: string, public documentations: string[] = []) {
super();
super(documentations);
}

addField(name: string, attributes: FieldAttribute[] = [], documentations: string[] = []): EnumField {
addField(
name: string,
attributes: (FieldAttribute | PassThroughAttribute)[] = [],
documentations: string[] = []
): EnumField {
const field = new EnumField(name, attributes, documentations);
this.fields.push(field);
return field;
}

addAttribute(name: string, args: AttributeArg[] = []): ModelAttribute {
const attr = new ModelAttribute(name, args);
addAttribute(name: string, args: AttributeArg[] = []) {
const attr = new ContainerAttribute(name, args);
this.attributes.push(attr);
return attr;
}
Expand All @@ -323,7 +349,11 @@ export class Enum extends DeclarationBase {
}

export class EnumField extends DeclarationBase {
constructor(public name: string, public attributes: FieldAttribute[] = [], public documentations: string[] = []) {
constructor(
public name: string,
public attributes: (FieldAttribute | PassThroughAttribute)[] = [],
public documentations: string[] = []
) {
super();
}

Expand Down
Loading