Skip to content

Commit a05d320

Browse files
authored
feat: add support for type modifier attributes (#240)
1 parent 88828e3 commit a05d320

File tree

16 files changed

+259
-25
lines changed

16 files changed

+259
-25
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zenstack-monorepo",
3-
"version": "1.0.0-alpha.55",
3+
"version": "1.0.0-alpha.56",
44
"description": "",
55
"scripts": {
66
"build": "pnpm -r build",

packages/language/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/language",
3-
"version": "1.0.0-alpha.55",
3+
"version": "1.0.0-alpha.56",
44
"displayName": "ZenStack modeling language compiler",
55
"description": "ZenStack modeling language compiler",
66
"homepage": "https://zenstack.dev",

packages/language/src/generated/grammar.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,11 +2035,23 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
20352035
"value": "."
20362036
},
20372037
{
2038-
"$type": "RuleCall",
2039-
"rule": {
2040-
"$ref": "#/rules@53"
2041-
},
2042-
"arguments": []
2038+
"$type": "Alternatives",
2039+
"elements": [
2040+
{
2041+
"$type": "RuleCall",
2042+
"rule": {
2043+
"$ref": "#/rules@53"
2044+
},
2045+
"arguments": []
2046+
},
2047+
{
2048+
"$type": "RuleCall",
2049+
"rule": {
2050+
"$ref": "#/rules@48"
2051+
},
2052+
"arguments": []
2053+
}
2054+
]
20432055
}
20442056
],
20452057
"cardinality": "*"

packages/language/src/zmodel.langium

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ FunctionParamType:
171171
(type=ExpressionType | reference=[TypeDeclaration]) (array?='[' ']')?;
172172

173173
QualifiedName returns string:
174-
ID ('.' ID)*;
174+
// TODO: is this the right way to deal with token precedence?
175+
ID ('.' (ID|BuiltinType))*;
175176

176177
// attribute-level attribute
177178
AttributeAttributeName returns string:
@@ -221,7 +222,7 @@ ExpressionType returns string:
221222
'String' | 'Int' | 'Float' | 'Boolean' | 'DateTime' | 'Null' | 'Any';
222223

223224
BuiltinType returns string:
224-
'String'|'Boolean'|'Int'|'BigInt'|'Float'|'Decimal'|'DateTime'|'Json'|'Bytes';
225+
'String' | 'Boolean' | 'Int' | 'BigInt' | 'Float' | 'Decimal' | 'DateTime' | 'Json' | 'Bytes';
225226

226227
hidden terminal WS: /\s+/;
227228
terminal BOOLEAN returns boolean: /true|false/;

packages/next/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zenstackhq/next",
3-
"version": "1.0.0-alpha.55",
3+
"version": "1.0.0-alpha.56",
44
"displayName": "ZenStack Next.js integration",
55
"description": "ZenStack Next.js integration",
66
"homepage": "https://zenstack.dev",

packages/plugins/react/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/react",
33
"displayName": "ZenStack plugin and runtime for ReactJS",
4-
"version": "1.0.0-alpha.55",
4+
"version": "1.0.0-alpha.56",
55
"description": "ZenStack plugin and runtime for ReactJS",
66
"main": "index.js",
77
"repository": {

packages/plugins/trpc/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/trpc",
33
"displayName": "ZenStack plugin for tRPC",
4-
"version": "1.0.0-alpha.55",
4+
"version": "1.0.0-alpha.56",
55
"description": "ZenStack plugin for tRPC",
66
"main": "index.js",
77
"repository": {

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zenstackhq/runtime",
33
"displayName": "ZenStack Runtime Library",
4-
"version": "1.0.0-alpha.55",
4+
"version": "1.0.0-alpha.56",
55
"description": "Runtime of ZenStack for both client-side and server-side environments.",
66
"repository": {
77
"type": "git",

packages/schema/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"publisher": "zenstack",
44
"displayName": "ZenStack Language Tools",
55
"description": "A toolkit for building secure CRUD apps with Next.js + Typescript",
6-
"version": "1.0.0-alpha.55",
6+
"version": "1.0.0-alpha.56",
77
"author": {
88
"name": "ZenStack Team"
99
},

packages/schema/src/language-server/validator/datamodel-validator.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export default class DataModelValidator implements AstValidator<DataModel> {
2323
}
2424

2525
private validateFields(dm: DataModel, accept: ValidationAcceptor) {
26+
// TODO: check conflict of @id and @@id
27+
2628
const idFields = dm.fields.filter((f) => f.attributes.find((attr) => attr.decl.ref?.name === '@id'));
2729
if (idFields.length === 0) {
2830
const { allows, denies, hasFieldValidation } = analyzePolicies(dm);

packages/schema/src/language-server/validator/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ function isValidAttributeTarget(attrDecl: Attribute, targetDecl: DataModelField)
267267
case 'IntField':
268268
allowed = allowed || targetDecl.type.type === 'Int';
269269
break;
270+
case 'BigIntField':
271+
allowed = allowed || targetDecl.type.type === 'BigInt';
272+
break;
270273
case 'FloatField':
271274
allowed = allowed || targetDecl.type.type === 'Float';
272275
break;

packages/schema/src/res/stdlib.zmodel

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum ReferentialAction {
3939
enum AttributeTargetField {
4040
StringField
4141
IntField
42+
BigIntField
4243
FloatField
4344
DecimalField
4445
BooleanField
@@ -51,43 +52,51 @@ enum AttributeTargetField {
5152
/*
5253
* Reads value from an environment variable.
5354
*/
54-
function env(name: String): String {}
55+
function env(name: String): String {
56+
}
5557

5658
/*
5759
* Gets the current login user.
5860
*/
59-
function auth(): Any {}
61+
function auth(): Any {
62+
}
6063

6164
/*
6265
* Gets current date-time (as DateTime type).
6366
*/
64-
function now(): DateTime {}
67+
function now(): DateTime {
68+
}
6569

6670
/*
6771
* Generates a globally unique identifier based on the UUID specs.
6872
*/
69-
function uuid(): String {}
73+
function uuid(): String {
74+
}
7075

7176
/*
7277
* Generates a globally unique identifier based on the CUID spec.
7378
*/
74-
function cuid(): String {}
79+
function cuid(): String {
80+
}
7581

7682
/*
7783
* Creates a sequence of integers in the underlying database and assign the incremented
7884
* values to the ID values of the created records based on the sequence.
7985
*/
80-
function autoincrement(): Int {}
86+
function autoincrement(): Int {
87+
}
8188

8289
/*
8390
* Represents default values that cannot be expressed in the Prisma schema (such as random()).
8491
*/
85-
function dbgenerated(expr: String): Any {}
92+
function dbgenerated(expr: String): Any {
93+
}
8694

8795
/**
8896
* Gets entities value before an update. Only valid when used in a "update" policy rule.
8997
*/
90-
function future(): Any {}
98+
function future(): Any {
99+
}
91100

92101
/**
93102
* Marks an attribute to be only applicable to certain field types.
@@ -114,6 +123,11 @@ attribute @default(_ value: ContextType) @@@prisma
114123
*/
115124
attribute @unique(map: String?) @@@prisma
116125

126+
/*
127+
* Defines a multi-field ID (composite ID) on the model.
128+
*/
129+
attribute @@id(_ fields: FieldReference[], name: String?, map: String?) @@@prisma
130+
117131
/*
118132
* Defines a compound unique constraint for the specified fields.
119133
*/
@@ -144,6 +158,94 @@ attribute @@map(_ name: String) @@@prisma
144158
*/
145159
attribute @updatedAt() @@@targetField([DateTimeField]) @@@prisma
146160

161+
// String type modifiers
162+
163+
attribute @db.String(_ x: Int?) @@@targetField([StringField]) @@@prisma
164+
attribute @db.Text() @@@targetField([StringField]) @@@prisma
165+
attribute @db.NText() @@@targetField([StringField]) @@@prisma
166+
attribute @db.Char(_ x: Int) @@@targetField([StringField]) @@@prisma
167+
attribute @db.NChar(_ x: Int) @@@targetField([StringField]) @@@prisma
168+
attribute @db.VarChar(_ x: Int) @@@targetField([StringField]) @@@prisma
169+
attribute @db.NVarChar(_ x: Int) @@@targetField([StringField]) @@@prisma
170+
attribute @db.CatalogSingleChar() @@@targetField([StringField]) @@@prisma
171+
attribute @db.TinyText() @@@targetField([StringField]) @@@prisma
172+
attribute @db.MediumText() @@@targetField([StringField]) @@@prisma
173+
attribute @db.LongText() @@@targetField([StringField]) @@@prisma
174+
attribute @db.Bit(_ x: Int?) @@@targetField([StringField, BooleanField, BytesField]) @@@prisma
175+
attribute @db.VarBit(_ x: Int?) @@@targetField([StringField]) @@@prisma
176+
attribute @db.Uuid() @@@targetField([StringField]) @@@prisma
177+
attribute @db.UniqueIdentifier() @@@targetField([StringField]) @@@prisma
178+
attribute @db.Xml() @@@targetField([StringField]) @@@prisma
179+
attribute @db.Inet() @@@targetField([StringField]) @@@prisma
180+
attribute @db.Citext() @@@targetField([StringField]) @@@prisma
181+
182+
// Boolean type modifiers
183+
184+
attribute @db.Boolean() @@@targetField([BooleanField]) @@@prisma
185+
attribute @db.TinyInt(_ x: Int?) @@@targetField([BooleanField]) @@@prisma
186+
attribute @db.Bool() @@@targetField([BooleanField]) @@@prisma
187+
188+
// Int type modifiers
189+
190+
attribute @db.Int() @@@targetField([IntField]) @@@prisma
191+
attribute @db.Integer() @@@targetField([IntField]) @@@prisma
192+
attribute @db.SmallInt() @@@targetField([IntField]) @@@prisma
193+
attribute @db.Oid() @@@targetField([IntField]) @@@prisma
194+
attribute @db.UnsignedInt() @@@targetField([IntField]) @@@prisma
195+
attribute @db.UnsignedSmallInt() @@@targetField([IntField]) @@@prisma
196+
attribute @db.MediumInt() @@@targetField([IntField]) @@@prisma
197+
attribute @db.UnsignedMediumInt() @@@targetField([IntField]) @@@prisma
198+
attribute @db.UnsignedTinyInt() @@@targetField([IntField]) @@@prisma
199+
attribute @db.Year() @@@targetField([IntField]) @@@prisma
200+
attribute @db.Int4() @@@targetField([IntField]) @@@prisma
201+
attribute @db.Int2() @@@targetField([IntField]) @@@prisma
202+
203+
// BigInt type modifiers
204+
205+
attribute @db.BigInt() @@@targetField([BigIntField]) @@@prisma
206+
attribute @db.UnsignedBigInt() @@@targetField([BigIntField]) @@@prisma
207+
attribute @db.Int8() @@@targetField([BigIntField]) @@@prisma
208+
209+
// Float/Decimal type modifiers
210+
attribute @db.DoublePrecision() @@@targetField([FloatField, DecimalField]) @@@prisma
211+
attribute @db.Real() @@@targetField([FloatField, DecimalField]) @@@prisma
212+
attribute @db.Float() @@@targetField([FloatField, DecimalField]) @@@prisma
213+
attribute @db.Decimal() @@@targetField([FloatField, DecimalField]) @@@prisma
214+
attribute @db.Double() @@@targetField([FloatField, DecimalField]) @@@prisma
215+
attribute @db.Money() @@@targetField([FloatField, DecimalField]) @@@prisma
216+
attribute @db.SmallMoney() @@@targetField([FloatField, DecimalField]) @@@prisma
217+
attribute @db.Float8() @@@targetField([FloatField, DecimalField]) @@@prisma
218+
attribute @db.Float4() @@@targetField([FloatField, DecimalField]) @@@prisma
219+
220+
// DateTime type modifiers
221+
222+
attribute @db.DateTime(x: Int?) @@@targetField([DateTimeField]) @@@prisma
223+
attribute @db.DateTime2() @@@targetField([DateTimeField]) @@@prisma
224+
attribute @db.SmallDateTime() @@@targetField([DateTimeField]) @@@prisma
225+
attribute @db.DateTimeOffset() @@@targetField([DateTimeField]) @@@prisma
226+
attribute @db.Timestamp(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
227+
attribute @db.Timestamptz(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
228+
attribute @db.Date() @@@targetField([DateTimeField]) @@@prisma
229+
attribute @db.Time(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
230+
attribute @db.Timetz(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
231+
232+
// Json type modifiers
233+
234+
attribute @db.Json() @@@targetField([JsonField]) @@@prisma
235+
attribute @db.JsonB() @@@targetField([JsonField]) @@@prisma
236+
237+
// Bytes type modifiers
238+
239+
attribute @db.Bytes() @@@targetField([BytesField]) @@@prisma
240+
attribute @db.ByteA() @@@targetField([BytesField]) @@@prisma
241+
attribute @db.LongBlob() @@@targetField([BytesField]) @@@prisma
242+
attribute @db.Binary() @@@targetField([BytesField]) @@@prisma
243+
attribute @db.VarBinary() @@@targetField([BytesField]) @@@prisma
244+
attribute @db.TinyBlob() @@@targetField([BytesField]) @@@prisma
245+
attribute @db.Blob() @@@targetField([BytesField]) @@@prisma
246+
attribute @db.MediumBlob() @@@targetField([BytesField]) @@@prisma
247+
attribute @db.Image() @@@targetField([BytesField]) @@@prisma
248+
147249
/*
148250
* Defines an access policy that allows a set of operations when the given condition is true.
149251
*/

0 commit comments

Comments
 (0)