@zenstackhq/language 3.0.0-alpha.9 → 3.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7,45 +7,11 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
7
7
  throw Error('Dynamic require of "' + x + '" is not supported');
8
8
  });
9
9
 
10
- // src/index.ts
11
- import { URI as URI3 } from "langium";
12
- import { NodeFileSystem } from "langium/node";
10
+ // src/document.ts
11
+ import { isAstNode, URI as URI4 } from "langium";
13
12
  import fs3 from "fs";
14
- import path3 from "path";
15
- import { fileURLToPath as fileURLToPath2 } from "url";
16
-
17
- // src/constants.ts
18
- var SUPPORTED_PROVIDERS = [
19
- "sqlite",
20
- "postgresql"
21
- ];
22
- var SCALAR_TYPES = [
23
- "String",
24
- "Int",
25
- "Float",
26
- "Decimal",
27
- "BigInt",
28
- "Boolean",
29
- "Bytes",
30
- "DateTime"
31
- ];
32
- var STD_LIB_MODULE_NAME = "stdlib.zmodel";
33
- var PLUGIN_MODULE_NAME = "plugin.zmodel";
34
- var IssueCodes = /* @__PURE__ */ function(IssueCodes2) {
35
- IssueCodes2["MissingOppositeRelation"] = "miss-opposite-relation";
36
- return IssueCodes2;
37
- }({});
38
- var ExpressionContext = /* @__PURE__ */ function(ExpressionContext2) {
39
- ExpressionContext2["DefaultValue"] = "DefaultValue";
40
- ExpressionContext2["AccessPolicy"] = "AccessPolicy";
41
- ExpressionContext2["ValidationRule"] = "ValidationRule";
42
- ExpressionContext2["Index"] = "Index";
43
- return ExpressionContext2;
44
- }({});
45
-
46
- // src/module.ts
47
- import { inject } from "langium";
48
- import { createDefaultModule, createDefaultSharedModule } from "langium/lsp";
13
+ import path4 from "path";
14
+ import { fileURLToPath as fileURLToPath4 } from "url";
49
15
 
50
16
  // src/generated/ast.ts
51
17
  import * as langium from "langium";
@@ -64,7 +30,6 @@ __name(isLiteralExpr, "isLiteralExpr");
64
30
  var MemberAccessTarget = "MemberAccessTarget";
65
31
  var ReferenceTarget = "ReferenceTarget";
66
32
  var TypeDeclaration = "TypeDeclaration";
67
- var TypeDefFieldTypes = "TypeDefFieldTypes";
68
33
  var Argument = "Argument";
69
34
  var ArrayExpr = "ArrayExpr";
70
35
  function isArrayExpr(item) {
@@ -97,6 +62,21 @@ __name(isConfigArrayExpr, "isConfigArrayExpr");
97
62
  var ConfigField = "ConfigField";
98
63
  var ConfigInvocationArg = "ConfigInvocationArg";
99
64
  var ConfigInvocationExpr = "ConfigInvocationExpr";
65
+ var DataField = "DataField";
66
+ function isDataField(item) {
67
+ return reflection.isInstance(item, DataField);
68
+ }
69
+ __name(isDataField, "isDataField");
70
+ var DataFieldAttribute = "DataFieldAttribute";
71
+ function isDataFieldAttribute(item) {
72
+ return reflection.isInstance(item, DataFieldAttribute);
73
+ }
74
+ __name(isDataFieldAttribute, "isDataFieldAttribute");
75
+ var DataFieldType = "DataFieldType";
76
+ function isDataFieldType(item) {
77
+ return reflection.isInstance(item, DataFieldType);
78
+ }
79
+ __name(isDataFieldType, "isDataFieldType");
100
80
  var DataModel = "DataModel";
101
81
  function isDataModel(item) {
102
82
  return reflection.isInstance(item, DataModel);
@@ -107,21 +87,6 @@ function isDataModelAttribute(item) {
107
87
  return reflection.isInstance(item, DataModelAttribute);
108
88
  }
109
89
  __name(isDataModelAttribute, "isDataModelAttribute");
110
- var DataModelField = "DataModelField";
111
- function isDataModelField(item) {
112
- return reflection.isInstance(item, DataModelField);
113
- }
114
- __name(isDataModelField, "isDataModelField");
115
- var DataModelFieldAttribute = "DataModelFieldAttribute";
116
- function isDataModelFieldAttribute(item) {
117
- return reflection.isInstance(item, DataModelFieldAttribute);
118
- }
119
- __name(isDataModelFieldAttribute, "isDataModelFieldAttribute");
120
- var DataModelFieldType = "DataModelFieldType";
121
- function isDataModelFieldType(item) {
122
- return reflection.isInstance(item, DataModelFieldType);
123
- }
124
- __name(isDataModelFieldType, "isDataModelFieldType");
125
90
  var DataSource = "DataSource";
126
91
  function isDataSource(item) {
127
92
  return reflection.isInstance(item, DataSource);
@@ -175,6 +140,10 @@ function isObjectExpr(item) {
175
140
  }
176
141
  __name(isObjectExpr, "isObjectExpr");
177
142
  var Plugin = "Plugin";
143
+ function isPlugin(item) {
144
+ return reflection.isInstance(item, Plugin);
145
+ }
146
+ __name(isPlugin, "isPlugin");
178
147
  var PluginField = "PluginField";
179
148
  var Procedure = "Procedure";
180
149
  var ProcedureParam = "ProcedureParam";
@@ -199,12 +168,6 @@ function isTypeDef(item) {
199
168
  return reflection.isInstance(item, TypeDef);
200
169
  }
201
170
  __name(isTypeDef, "isTypeDef");
202
- var TypeDefField = "TypeDefField";
203
- function isTypeDefField(item) {
204
- return reflection.isInstance(item, TypeDefField);
205
- }
206
- __name(isTypeDefField, "isTypeDefField");
207
- var TypeDefFieldType = "TypeDefFieldType";
208
171
  var UnaryExpr = "UnaryExpr";
209
172
  var UnsupportedFieldType = "UnsupportedFieldType";
210
173
  var ZModelAstReflection = class extends langium.AbstractAstReflection {
@@ -227,11 +190,11 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
227
190
  ConfigField,
228
191
  ConfigInvocationArg,
229
192
  ConfigInvocationExpr,
193
+ DataField,
194
+ DataFieldAttribute,
195
+ DataFieldType,
230
196
  DataModel,
231
197
  DataModelAttribute,
232
- DataModelField,
233
- DataModelFieldAttribute,
234
- DataModelFieldType,
235
198
  DataSource,
236
199
  Enum,
237
200
  EnumField,
@@ -262,9 +225,6 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
262
225
  ThisExpr,
263
226
  TypeDeclaration,
264
227
  TypeDef,
265
- TypeDefField,
266
- TypeDefFieldType,
267
- TypeDefFieldTypes,
268
228
  UnaryExpr,
269
229
  UnsupportedFieldType
270
230
  ];
@@ -297,16 +257,13 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
297
257
  case ConfigArrayExpr: {
298
258
  return this.isSubtype(ConfigExpr, supertype);
299
259
  }
300
- case DataModel: {
301
- return this.isSubtype(AbstractDeclaration, supertype) || this.isSubtype(TypeDeclaration, supertype);
302
- }
303
- case DataModelField:
304
- case TypeDefField: {
260
+ case DataField: {
305
261
  return this.isSubtype(MemberAccessTarget, supertype) || this.isSubtype(ReferenceTarget, supertype);
306
262
  }
263
+ case DataModel:
307
264
  case Enum:
308
265
  case TypeDef: {
309
- return this.isSubtype(AbstractDeclaration, supertype) || this.isSubtype(TypeDeclaration, supertype) || this.isSubtype(TypeDefFieldTypes, supertype);
266
+ return this.isSubtype(AbstractDeclaration, supertype) || this.isSubtype(TypeDeclaration, supertype);
310
267
  }
311
268
  case EnumField:
312
269
  case FunctionParam: {
@@ -325,18 +282,22 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
325
282
  const referenceId = `${refInfo.container.$type}:${refInfo.property}`;
326
283
  switch (referenceId) {
327
284
  case "AttributeParamType:reference":
328
- case "DataModelFieldType:reference":
285
+ case "DataFieldType:reference":
329
286
  case "FunctionParamType:reference": {
330
287
  return TypeDeclaration;
331
288
  }
332
- case "DataModel:superTypes": {
333
- return DataModel;
334
- }
289
+ case "DataFieldAttribute:decl":
335
290
  case "DataModelAttribute:decl":
336
- case "DataModelFieldAttribute:decl":
337
291
  case "InternalAttribute:decl": {
338
292
  return Attribute;
339
293
  }
294
+ case "DataModel:baseModel": {
295
+ return DataModel;
296
+ }
297
+ case "DataModel:mixins":
298
+ case "TypeDef:mixins": {
299
+ return TypeDef;
300
+ }
340
301
  case "InvocationExpr:function": {
341
302
  return FunctionDecl;
342
303
  }
@@ -346,9 +307,6 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
346
307
  case "ReferenceExpr:target": {
347
308
  return ReferenceTarget;
348
309
  }
349
- case "TypeDefFieldType:reference": {
350
- return TypeDefFieldTypes;
351
- }
352
310
  default: {
353
311
  throw new Error(`${referenceId} is not a valid reference id.`);
354
312
  }
@@ -535,9 +493,9 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
535
493
  ]
536
494
  };
537
495
  }
538
- case DataModel: {
496
+ case DataField: {
539
497
  return {
540
- name: DataModel,
498
+ name: DataField,
541
499
  properties: [
542
500
  {
543
501
  name: "attributes",
@@ -547,31 +505,18 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
547
505
  name: "comments",
548
506
  defaultValue: []
549
507
  },
550
- {
551
- name: "fields",
552
- defaultValue: []
553
- },
554
- {
555
- name: "isAbstract",
556
- defaultValue: false
557
- },
558
- {
559
- name: "isView",
560
- defaultValue: false
561
- },
562
508
  {
563
509
  name: "name"
564
510
  },
565
511
  {
566
- name: "superTypes",
567
- defaultValue: []
512
+ name: "type"
568
513
  }
569
514
  ]
570
515
  };
571
516
  }
572
- case DataModelAttribute: {
517
+ case DataFieldAttribute: {
573
518
  return {
574
- name: DataModelAttribute,
519
+ name: DataFieldAttribute,
575
520
  properties: [
576
521
  {
577
522
  name: "args",
@@ -583,61 +528,73 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
583
528
  ]
584
529
  };
585
530
  }
586
- case DataModelField: {
531
+ case DataFieldType: {
587
532
  return {
588
- name: DataModelField,
533
+ name: DataFieldType,
589
534
  properties: [
590
535
  {
591
- name: "attributes",
592
- defaultValue: []
536
+ name: "array",
537
+ defaultValue: false
593
538
  },
594
539
  {
595
- name: "comments",
596
- defaultValue: []
540
+ name: "optional",
541
+ defaultValue: false
597
542
  },
598
543
  {
599
- name: "name"
544
+ name: "reference"
600
545
  },
601
546
  {
602
547
  name: "type"
548
+ },
549
+ {
550
+ name: "unsupported"
603
551
  }
604
552
  ]
605
553
  };
606
554
  }
607
- case DataModelFieldAttribute: {
555
+ case DataModel: {
608
556
  return {
609
- name: DataModelFieldAttribute,
557
+ name: DataModel,
610
558
  properties: [
611
559
  {
612
- name: "args",
560
+ name: "attributes",
613
561
  defaultValue: []
614
562
  },
615
563
  {
616
- name: "decl"
617
- }
618
- ]
619
- };
620
- }
621
- case DataModelFieldType: {
622
- return {
623
- name: DataModelFieldType,
624
- properties: [
564
+ name: "baseModel"
565
+ },
625
566
  {
626
- name: "array",
627
- defaultValue: false
567
+ name: "comments",
568
+ defaultValue: []
628
569
  },
629
570
  {
630
- name: "optional",
571
+ name: "fields",
572
+ defaultValue: []
573
+ },
574
+ {
575
+ name: "isView",
631
576
  defaultValue: false
632
577
  },
633
578
  {
634
- name: "reference"
579
+ name: "mixins",
580
+ defaultValue: []
635
581
  },
636
582
  {
637
- name: "type"
583
+ name: "name"
584
+ }
585
+ ]
586
+ };
587
+ }
588
+ case DataModelAttribute: {
589
+ return {
590
+ name: DataModelAttribute,
591
+ properties: [
592
+ {
593
+ name: "args",
594
+ defaultValue: []
638
595
  },
639
596
  {
640
- name: "unsupported"
597
+ name: "decl"
641
598
  }
642
599
  ]
643
600
  };
@@ -1011,49 +968,11 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
1011
968
  defaultValue: []
1012
969
  },
1013
970
  {
1014
- name: "name"
1015
- }
1016
- ]
1017
- };
1018
- }
1019
- case TypeDefField: {
1020
- return {
1021
- name: TypeDefField,
1022
- properties: [
1023
- {
1024
- name: "attributes",
1025
- defaultValue: []
1026
- },
1027
- {
1028
- name: "comments",
971
+ name: "mixins",
1029
972
  defaultValue: []
1030
973
  },
1031
974
  {
1032
975
  name: "name"
1033
- },
1034
- {
1035
- name: "type"
1036
- }
1037
- ]
1038
- };
1039
- }
1040
- case TypeDefFieldType: {
1041
- return {
1042
- name: TypeDefFieldType,
1043
- properties: [
1044
- {
1045
- name: "array",
1046
- defaultValue: false
1047
- },
1048
- {
1049
- name: "optional",
1050
- defaultValue: false
1051
- },
1052
- {
1053
- name: "reference"
1054
- },
1055
- {
1056
- name: "type"
1057
976
  }
1058
977
  ]
1059
978
  };
@@ -1092,6 +1011,42 @@ var ZModelAstReflection = class extends langium.AbstractAstReflection {
1092
1011
  };
1093
1012
  var reflection = new ZModelAstReflection();
1094
1013
 
1014
+ // src/constants.ts
1015
+ var SUPPORTED_PROVIDERS = [
1016
+ "sqlite",
1017
+ "postgresql"
1018
+ ];
1019
+ var SCALAR_TYPES = [
1020
+ "String",
1021
+ "Int",
1022
+ "Float",
1023
+ "Decimal",
1024
+ "BigInt",
1025
+ "Boolean",
1026
+ "Bytes",
1027
+ "DateTime"
1028
+ ];
1029
+ var STD_LIB_MODULE_NAME = "stdlib.zmodel";
1030
+ var PLUGIN_MODULE_NAME = "plugin.zmodel";
1031
+ var IssueCodes = /* @__PURE__ */ function(IssueCodes2) {
1032
+ IssueCodes2["MissingOppositeRelation"] = "miss-opposite-relation";
1033
+ return IssueCodes2;
1034
+ }({});
1035
+ var ExpressionContext = /* @__PURE__ */ function(ExpressionContext2) {
1036
+ ExpressionContext2["DefaultValue"] = "DefaultValue";
1037
+ ExpressionContext2["AccessPolicy"] = "AccessPolicy";
1038
+ ExpressionContext2["ValidationRule"] = "ValidationRule";
1039
+ ExpressionContext2["Index"] = "Index";
1040
+ return ExpressionContext2;
1041
+ }({});
1042
+
1043
+ // src/module.ts
1044
+ import { DocumentState as DocumentState2, inject, URI as URI3 } from "langium";
1045
+ import { createDefaultModule, createDefaultSharedModule } from "langium/lsp";
1046
+ import { NodeFileSystem } from "langium/node";
1047
+ import path3 from "path";
1048
+ import { fileURLToPath as fileURLToPath3 } from "url";
1049
+
1095
1050
  // src/generated/grammar.ts
1096
1051
  import { loadGrammarFromJson } from "langium";
1097
1052
  var loadedZModelGrammar;
@@ -1214,7 +1169,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
1214
1169
  {
1215
1170
  "$type": "RuleCall",
1216
1171
  "rule": {
1217
- "$ref": "#/rules@40"
1172
+ "$ref": "#/rules@42"
1218
1173
  },
1219
1174
  "arguments": []
1220
1175
  },
@@ -3008,16 +2963,6 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3008
2963
  {
3009
2964
  "$type": "Group",
3010
2965
  "elements": [
3011
- {
3012
- "$type": "Assignment",
3013
- "feature": "isAbstract",
3014
- "operator": "?=",
3015
- "terminal": {
3016
- "$type": "Keyword",
3017
- "value": "abstract"
3018
- },
3019
- "cardinality": "?"
3020
- },
3021
2966
  {
3022
2967
  "$type": "Keyword",
3023
2968
  "value": "model"
@@ -3035,45 +2980,59 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3035
2980
  }
3036
2981
  },
3037
2982
  {
3038
- "$type": "Group",
2983
+ "$type": "Alternatives",
3039
2984
  "elements": [
3040
2985
  {
3041
- "$type": "Keyword",
3042
- "value": "extends"
2986
+ "$type": "RuleCall",
2987
+ "rule": {
2988
+ "$ref": "#/rules@38"
2989
+ },
2990
+ "arguments": []
2991
+ },
2992
+ {
2993
+ "$type": "RuleCall",
2994
+ "rule": {
2995
+ "$ref": "#/rules@39"
2996
+ },
2997
+ "arguments": []
3043
2998
  },
3044
2999
  {
3045
- "$type": "Assignment",
3046
- "feature": "superTypes",
3047
- "operator": "+=",
3048
- "terminal": {
3049
- "$type": "CrossReference",
3050
- "type": {
3051
- "$ref": "#/rules@37"
3000
+ "$type": "Group",
3001
+ "elements": [
3002
+ {
3003
+ "$type": "RuleCall",
3004
+ "rule": {
3005
+ "$ref": "#/rules@39"
3006
+ },
3007
+ "arguments": []
3052
3008
  },
3053
- "deprecatedSyntax": false
3054
- }
3009
+ {
3010
+ "$type": "RuleCall",
3011
+ "rule": {
3012
+ "$ref": "#/rules@38"
3013
+ },
3014
+ "arguments": []
3015
+ }
3016
+ ]
3055
3017
  },
3056
3018
  {
3057
3019
  "$type": "Group",
3058
3020
  "elements": [
3059
3021
  {
3060
- "$type": "Keyword",
3061
- "value": ","
3022
+ "$type": "RuleCall",
3023
+ "rule": {
3024
+ "$ref": "#/rules@38"
3025
+ },
3026
+ "arguments": []
3062
3027
  },
3063
3028
  {
3064
- "$type": "Assignment",
3065
- "feature": "superTypes",
3066
- "operator": "+=",
3067
- "terminal": {
3068
- "$type": "CrossReference",
3069
- "type": {
3070
- "$ref": "#/rules@37"
3071
- },
3072
- "deprecatedSyntax": false
3073
- }
3029
+ "$type": "RuleCall",
3030
+ "rule": {
3031
+ "$ref": "#/rules@39"
3032
+ },
3033
+ "arguments": []
3074
3034
  }
3075
- ],
3076
- "cardinality": "*"
3035
+ ]
3077
3036
  }
3078
3037
  ],
3079
3038
  "cardinality": "?"
@@ -3122,7 +3081,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3122
3081
  "terminal": {
3123
3082
  "$type": "RuleCall",
3124
3083
  "rule": {
3125
- "$ref": "#/rules@38"
3084
+ "$ref": "#/rules@40"
3126
3085
  },
3127
3086
  "arguments": []
3128
3087
  }
@@ -3157,53 +3116,138 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3157
3116
  },
3158
3117
  {
3159
3118
  "$type": "ParserRule",
3160
- "name": "DataModelField",
3119
+ "fragment": true,
3120
+ "name": "WithClause",
3161
3121
  "definition": {
3162
3122
  "$type": "Group",
3163
3123
  "elements": [
3164
3124
  {
3165
- "$type": "Assignment",
3166
- "feature": "comments",
3167
- "operator": "+=",
3168
- "terminal": {
3169
- "$type": "RuleCall",
3170
- "rule": {
3171
- "$ref": "#/rules@71"
3172
- },
3173
- "arguments": []
3174
- },
3175
- "cardinality": "*"
3125
+ "$type": "Keyword",
3126
+ "value": "with"
3176
3127
  },
3177
3128
  {
3178
3129
  "$type": "Assignment",
3179
- "feature": "name",
3180
- "operator": "=",
3130
+ "feature": "mixins",
3131
+ "operator": "+=",
3181
3132
  "terminal": {
3182
- "$type": "RuleCall",
3183
- "rule": {
3184
- "$ref": "#/rules@52"
3133
+ "$type": "CrossReference",
3134
+ "type": {
3135
+ "$ref": "#/rules@42"
3185
3136
  },
3186
- "arguments": []
3137
+ "deprecatedSyntax": false
3187
3138
  }
3188
3139
  },
3189
3140
  {
3190
- "$type": "Assignment",
3191
- "feature": "type",
3192
- "operator": "=",
3193
- "terminal": {
3194
- "$type": "RuleCall",
3195
- "rule": {
3196
- "$ref": "#/rules@39"
3141
+ "$type": "Group",
3142
+ "elements": [
3143
+ {
3144
+ "$type": "Keyword",
3145
+ "value": ",",
3146
+ "cardinality": "?"
3197
3147
  },
3198
- "arguments": []
3199
- }
3200
- },
3201
- {
3202
- "$type": "Assignment",
3203
- "feature": "attributes",
3204
- "operator": "+=",
3205
- "terminal": {
3206
- "$type": "RuleCall",
3148
+ {
3149
+ "$type": "Assignment",
3150
+ "feature": "mixins",
3151
+ "operator": "+=",
3152
+ "terminal": {
3153
+ "$type": "CrossReference",
3154
+ "type": {
3155
+ "$ref": "#/rules@42"
3156
+ },
3157
+ "deprecatedSyntax": false
3158
+ }
3159
+ }
3160
+ ],
3161
+ "cardinality": "*"
3162
+ }
3163
+ ]
3164
+ },
3165
+ "definesHiddenTokens": false,
3166
+ "entry": false,
3167
+ "hiddenTokens": [],
3168
+ "parameters": [],
3169
+ "wildcard": false
3170
+ },
3171
+ {
3172
+ "$type": "ParserRule",
3173
+ "fragment": true,
3174
+ "name": "ExtendsClause",
3175
+ "definition": {
3176
+ "$type": "Group",
3177
+ "elements": [
3178
+ {
3179
+ "$type": "Keyword",
3180
+ "value": "extends"
3181
+ },
3182
+ {
3183
+ "$type": "Assignment",
3184
+ "feature": "baseModel",
3185
+ "operator": "=",
3186
+ "terminal": {
3187
+ "$type": "CrossReference",
3188
+ "type": {
3189
+ "$ref": "#/rules@37"
3190
+ },
3191
+ "deprecatedSyntax": false
3192
+ }
3193
+ }
3194
+ ]
3195
+ },
3196
+ "definesHiddenTokens": false,
3197
+ "entry": false,
3198
+ "hiddenTokens": [],
3199
+ "parameters": [],
3200
+ "wildcard": false
3201
+ },
3202
+ {
3203
+ "$type": "ParserRule",
3204
+ "name": "DataField",
3205
+ "definition": {
3206
+ "$type": "Group",
3207
+ "elements": [
3208
+ {
3209
+ "$type": "Assignment",
3210
+ "feature": "comments",
3211
+ "operator": "+=",
3212
+ "terminal": {
3213
+ "$type": "RuleCall",
3214
+ "rule": {
3215
+ "$ref": "#/rules@71"
3216
+ },
3217
+ "arguments": []
3218
+ },
3219
+ "cardinality": "*"
3220
+ },
3221
+ {
3222
+ "$type": "Assignment",
3223
+ "feature": "name",
3224
+ "operator": "=",
3225
+ "terminal": {
3226
+ "$type": "RuleCall",
3227
+ "rule": {
3228
+ "$ref": "#/rules@52"
3229
+ },
3230
+ "arguments": []
3231
+ }
3232
+ },
3233
+ {
3234
+ "$type": "Assignment",
3235
+ "feature": "type",
3236
+ "operator": "=",
3237
+ "terminal": {
3238
+ "$type": "RuleCall",
3239
+ "rule": {
3240
+ "$ref": "#/rules@41"
3241
+ },
3242
+ "arguments": []
3243
+ }
3244
+ },
3245
+ {
3246
+ "$type": "Assignment",
3247
+ "feature": "attributes",
3248
+ "operator": "+=",
3249
+ "terminal": {
3250
+ "$type": "RuleCall",
3207
3251
  "rule": {
3208
3252
  "$ref": "#/rules@56"
3209
3253
  },
@@ -3222,7 +3266,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3222
3266
  },
3223
3267
  {
3224
3268
  "$type": "ParserRule",
3225
- "name": "DataModelFieldType",
3269
+ "name": "DataFieldType",
3226
3270
  "definition": {
3227
3271
  "$type": "Group",
3228
3272
  "elements": [
@@ -3260,7 +3304,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3260
3304
  "terminal": {
3261
3305
  "$type": "CrossReference",
3262
3306
  "type": {
3263
- "$ref": "#/types@3"
3307
+ "$ref": "#/types@2"
3264
3308
  },
3265
3309
  "terminal": {
3266
3310
  "$type": "RuleCall",
@@ -3347,6 +3391,14 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3347
3391
  "arguments": []
3348
3392
  }
3349
3393
  },
3394
+ {
3395
+ "$type": "RuleCall",
3396
+ "rule": {
3397
+ "$ref": "#/rules@38"
3398
+ },
3399
+ "arguments": [],
3400
+ "cardinality": "?"
3401
+ },
3350
3402
  {
3351
3403
  "$type": "Keyword",
3352
3404
  "value": "{"
@@ -3361,7 +3413,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3361
3413
  "terminal": {
3362
3414
  "$type": "RuleCall",
3363
3415
  "rule": {
3364
- "$ref": "#/rules@41"
3416
+ "$ref": "#/rules@40"
3365
3417
  },
3366
3418
  "arguments": []
3367
3419
  }
@@ -3394,151 +3446,6 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3394
3446
  "parameters": [],
3395
3447
  "wildcard": false
3396
3448
  },
3397
- {
3398
- "$type": "ParserRule",
3399
- "name": "TypeDefField",
3400
- "definition": {
3401
- "$type": "Group",
3402
- "elements": [
3403
- {
3404
- "$type": "Assignment",
3405
- "feature": "comments",
3406
- "operator": "+=",
3407
- "terminal": {
3408
- "$type": "RuleCall",
3409
- "rule": {
3410
- "$ref": "#/rules@71"
3411
- },
3412
- "arguments": []
3413
- },
3414
- "cardinality": "*"
3415
- },
3416
- {
3417
- "$type": "Assignment",
3418
- "feature": "name",
3419
- "operator": "=",
3420
- "terminal": {
3421
- "$type": "RuleCall",
3422
- "rule": {
3423
- "$ref": "#/rules@52"
3424
- },
3425
- "arguments": []
3426
- }
3427
- },
3428
- {
3429
- "$type": "Assignment",
3430
- "feature": "type",
3431
- "operator": "=",
3432
- "terminal": {
3433
- "$type": "RuleCall",
3434
- "rule": {
3435
- "$ref": "#/rules@42"
3436
- },
3437
- "arguments": []
3438
- }
3439
- },
3440
- {
3441
- "$type": "Assignment",
3442
- "feature": "attributes",
3443
- "operator": "+=",
3444
- "terminal": {
3445
- "$type": "RuleCall",
3446
- "rule": {
3447
- "$ref": "#/rules@56"
3448
- },
3449
- "arguments": []
3450
- },
3451
- "cardinality": "*"
3452
- }
3453
- ]
3454
- },
3455
- "definesHiddenTokens": false,
3456
- "entry": false,
3457
- "fragment": false,
3458
- "hiddenTokens": [],
3459
- "parameters": [],
3460
- "wildcard": false
3461
- },
3462
- {
3463
- "$type": "ParserRule",
3464
- "name": "TypeDefFieldType",
3465
- "definition": {
3466
- "$type": "Group",
3467
- "elements": [
3468
- {
3469
- "$type": "Alternatives",
3470
- "elements": [
3471
- {
3472
- "$type": "Assignment",
3473
- "feature": "type",
3474
- "operator": "=",
3475
- "terminal": {
3476
- "$type": "RuleCall",
3477
- "rule": {
3478
- "$ref": "#/rules@62"
3479
- },
3480
- "arguments": []
3481
- }
3482
- },
3483
- {
3484
- "$type": "Assignment",
3485
- "feature": "reference",
3486
- "operator": "=",
3487
- "terminal": {
3488
- "$type": "CrossReference",
3489
- "type": {
3490
- "$ref": "#/types@2"
3491
- },
3492
- "terminal": {
3493
- "$type": "RuleCall",
3494
- "rule": {
3495
- "$ref": "#/rules@51"
3496
- },
3497
- "arguments": []
3498
- },
3499
- "deprecatedSyntax": false
3500
- }
3501
- }
3502
- ]
3503
- },
3504
- {
3505
- "$type": "Group",
3506
- "elements": [
3507
- {
3508
- "$type": "Assignment",
3509
- "feature": "array",
3510
- "operator": "?=",
3511
- "terminal": {
3512
- "$type": "Keyword",
3513
- "value": "["
3514
- }
3515
- },
3516
- {
3517
- "$type": "Keyword",
3518
- "value": "]"
3519
- }
3520
- ],
3521
- "cardinality": "?"
3522
- },
3523
- {
3524
- "$type": "Assignment",
3525
- "feature": "optional",
3526
- "operator": "?=",
3527
- "terminal": {
3528
- "$type": "Keyword",
3529
- "value": "?"
3530
- },
3531
- "cardinality": "?"
3532
- }
3533
- ]
3534
- },
3535
- "definesHiddenTokens": false,
3536
- "entry": false,
3537
- "fragment": false,
3538
- "hiddenTokens": [],
3539
- "parameters": [],
3540
- "wildcard": false
3541
- },
3542
3449
  {
3543
3450
  "$type": "ParserRule",
3544
3451
  "name": "UnsupportedFieldType",
@@ -3939,7 +3846,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
3939
3846
  "terminal": {
3940
3847
  "$type": "CrossReference",
3941
3848
  "type": {
3942
- "$ref": "#/types@3"
3849
+ "$ref": "#/types@2"
3943
3850
  },
3944
3851
  "terminal": {
3945
3852
  "$type": "RuleCall",
@@ -4553,7 +4460,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
4553
4460
  "terminal": {
4554
4461
  "$type": "CrossReference",
4555
4462
  "type": {
4556
- "$ref": "#/types@3"
4463
+ "$ref": "#/types@2"
4557
4464
  },
4558
4465
  "terminal": {
4559
4466
  "$type": "RuleCall",
@@ -4607,7 +4514,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
4607
4514
  },
4608
4515
  {
4609
4516
  "$type": "ParserRule",
4610
- "name": "DataModelFieldAttribute",
4517
+ "name": "DataFieldAttribute",
4611
4518
  "definition": {
4612
4519
  "$type": "Group",
4613
4520
  "elements": [
@@ -5124,13 +5031,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
5124
5031
  {
5125
5032
  "$type": "SimpleType",
5126
5033
  "typeRef": {
5127
- "$ref": "#/rules@38"
5128
- }
5129
- },
5130
- {
5131
- "$type": "SimpleType",
5132
- "typeRef": {
5133
- "$ref": "#/rules@41"
5034
+ "$ref": "#/rules@40"
5134
5035
  }
5135
5036
  },
5136
5037
  {
@@ -5146,42 +5047,10 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
5146
5047
  "$type": "Type",
5147
5048
  "name": "MemberAccessTarget",
5148
5049
  "type": {
5149
- "$type": "UnionType",
5150
- "types": [
5151
- {
5152
- "$type": "SimpleType",
5153
- "typeRef": {
5154
- "$ref": "#/rules@38"
5155
- }
5156
- },
5157
- {
5158
- "$type": "SimpleType",
5159
- "typeRef": {
5160
- "$ref": "#/rules@41"
5161
- }
5162
- }
5163
- ]
5164
- }
5165
- },
5166
- {
5167
- "$type": "Type",
5168
- "name": "TypeDefFieldTypes",
5169
- "type": {
5170
- "$type": "UnionType",
5171
- "types": [
5172
- {
5173
- "$type": "SimpleType",
5174
- "typeRef": {
5175
- "$ref": "#/rules@40"
5176
- }
5177
- },
5178
- {
5179
- "$type": "SimpleType",
5180
- "typeRef": {
5181
- "$ref": "#/rules@44"
5182
- }
5183
- }
5184
- ]
5050
+ "$type": "SimpleType",
5051
+ "typeRef": {
5052
+ "$ref": "#/rules@40"
5053
+ }
5185
5054
  }
5186
5055
  },
5187
5056
  {
@@ -5199,7 +5068,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
5199
5068
  {
5200
5069
  "$type": "SimpleType",
5201
5070
  "typeRef": {
5202
- "$ref": "#/rules@40"
5071
+ "$ref": "#/rules@42"
5203
5072
  }
5204
5073
  },
5205
5074
  {
@@ -5221,7 +5090,7 @@ var ZModelGrammar = /* @__PURE__ */ __name(() => loadedZModelGrammar ?? (loadedZ
5221
5090
 
5222
5091
  // src/generated/module.ts
5223
5092
  var ZModelLanguageMetaData = {
5224
- languageId: "zmodel",
5093
+ languageId: "zmodel-v3",
5225
5094
  fileExtensions: [
5226
5095
  ".zmodel"
5227
5096
  ],
@@ -5237,14 +5106,12 @@ var ZModelGeneratedModule = {
5237
5106
  parser: {}
5238
5107
  };
5239
5108
 
5240
- // src/validators/attribute-application-validator.ts
5241
- import { AstUtils as AstUtils2 } from "langium";
5242
- import pluralize from "pluralize";
5243
-
5244
5109
  // src/utils.ts
5245
5110
  import { AstUtils, URI } from "langium";
5246
- import path from "path";
5247
5111
  import fs from "fs";
5112
+ import { createRequire } from "module";
5113
+ import path from "path";
5114
+ import { fileURLToPath, pathToFileURL } from "url";
5248
5115
  function hasAttribute(decl, name) {
5249
5116
  return !!getAttribute(decl, name);
5250
5117
  }
@@ -5316,18 +5183,14 @@ function isEnumFieldReference(node) {
5316
5183
  return isReferenceExpr(node) && isEnumField(node.target.ref);
5317
5184
  }
5318
5185
  __name(isEnumFieldReference, "isEnumFieldReference");
5319
- function isDataModelFieldReference(node) {
5320
- return isReferenceExpr(node) && isDataModelField(node.target.ref);
5186
+ function isDataFieldReference(node) {
5187
+ return isReferenceExpr(node) && isDataField(node.target.ref);
5321
5188
  }
5322
- __name(isDataModelFieldReference, "isDataModelFieldReference");
5189
+ __name(isDataFieldReference, "isDataFieldReference");
5323
5190
  function isRelationshipField(field) {
5324
5191
  return isDataModel(field.type.reference?.ref);
5325
5192
  }
5326
5193
  __name(isRelationshipField, "isRelationshipField");
5327
- function isFutureExpr(node) {
5328
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5329
- }
5330
- __name(isFutureExpr, "isFutureExpr");
5331
5194
  function isDelegateModel(node) {
5332
5195
  return isDataModel(node) && hasAttribute(node, "@@delegate");
5333
5196
  }
@@ -5339,43 +5202,20 @@ function resolved(ref) {
5339
5202
  return ref.ref;
5340
5203
  }
5341
5204
  __name(resolved, "resolved");
5342
- function findUpInheritance(start, target) {
5343
- for (const base of start.superTypes) {
5344
- if (base.ref === target) {
5345
- return [
5346
- base.ref
5347
- ];
5348
- }
5349
- const path4 = findUpInheritance(base.ref, target);
5350
- if (path4) {
5351
- return [
5352
- base.ref,
5353
- ...path4
5354
- ];
5355
- }
5356
- }
5357
- return void 0;
5358
- }
5359
- __name(findUpInheritance, "findUpInheritance");
5360
- function getModelFieldsWithBases(model, includeDelegate = true) {
5361
- if (model.$baseMerged) {
5362
- return model.fields;
5363
- } else {
5364
- return [
5365
- ...model.fields,
5366
- ...getRecursiveBases(model, includeDelegate).flatMap((base) => base.fields)
5367
- ];
5368
- }
5369
- }
5370
- __name(getModelFieldsWithBases, "getModelFieldsWithBases");
5371
- function getRecursiveBases(dataModel, includeDelegate = true, seen = /* @__PURE__ */ new Set()) {
5205
+ function getRecursiveBases(decl, includeDelegate = true, seen = /* @__PURE__ */ new Set()) {
5372
5206
  const result = [];
5373
- if (seen.has(dataModel)) {
5207
+ if (seen.has(decl)) {
5374
5208
  return result;
5375
5209
  }
5376
- seen.add(dataModel);
5377
- dataModel.superTypes.forEach((superType) => {
5378
- const baseDecl = superType.ref;
5210
+ seen.add(decl);
5211
+ const bases = [
5212
+ ...decl.mixins,
5213
+ ...isDataModel(decl) && decl.baseModel ? [
5214
+ decl.baseModel
5215
+ ] : []
5216
+ ];
5217
+ bases.forEach((base) => {
5218
+ const baseDecl = decl.$container.declarations.find((d) => isTypeDef(d) || isDataModel(d) && d.name === base.$refText);
5379
5219
  if (baseDecl) {
5380
5220
  if (!includeDelegate && isDelegateModel(baseDecl)) {
5381
5221
  return;
@@ -5388,14 +5228,13 @@ function getRecursiveBases(dataModel, includeDelegate = true, seen = /* @__PURE_
5388
5228
  }
5389
5229
  __name(getRecursiveBases, "getRecursiveBases");
5390
5230
  function getModelIdFields(model) {
5391
- const modelsToCheck = model.$baseMerged ? [
5392
- model
5393
- ] : [
5231
+ const modelsToCheck = [
5394
5232
  model,
5395
5233
  ...getRecursiveBases(model)
5396
5234
  ];
5397
5235
  for (const modelToCheck of modelsToCheck) {
5398
- const idAttr = modelToCheck.attributes.find((attr) => attr.decl.$refText === "@@id");
5236
+ const allAttributes = getAllAttributes(modelToCheck);
5237
+ const idAttr = allAttributes.find((attr) => attr.decl.$refText === "@@id");
5399
5238
  if (!idAttr) {
5400
5239
  continue;
5401
5240
  }
@@ -5409,14 +5248,13 @@ function getModelIdFields(model) {
5409
5248
  }
5410
5249
  __name(getModelIdFields, "getModelIdFields");
5411
5250
  function getModelUniqueFields(model) {
5412
- const modelsToCheck = model.$baseMerged ? [
5413
- model
5414
- ] : [
5251
+ const modelsToCheck = [
5415
5252
  model,
5416
5253
  ...getRecursiveBases(model)
5417
5254
  ];
5418
5255
  for (const modelToCheck of modelsToCheck) {
5419
- const uniqueAttr = modelToCheck.attributes.find((attr) => attr.decl.$refText === "@@unique");
5256
+ const allAttributes = getAllAttributes(modelToCheck);
5257
+ const uniqueAttr = allAttributes.find((attr) => attr.decl.$refText === "@@unique");
5420
5258
  if (!uniqueAttr) {
5421
5259
  continue;
5422
5260
  }
@@ -5517,7 +5355,7 @@ function getFunctionExpressionContext(funcDecl) {
5517
5355
  }
5518
5356
  __name(getFunctionExpressionContext, "getFunctionExpressionContext");
5519
5357
  function isCheckInvocation(node) {
5520
- return isInvocationExpr(node) && node.function.ref?.name === "check" && isFromStdlib(node.function.ref);
5358
+ return isInvocationExpr(node) && node.function.ref?.name === "check";
5521
5359
  }
5522
5360
  __name(isCheckInvocation, "isCheckInvocation");
5523
5361
  function resolveTransitiveImports(documents, model) {
@@ -5563,34 +5401,24 @@ function resolveImport(documents, imp) {
5563
5401
  }
5564
5402
  __name(resolveImport, "resolveImport");
5565
5403
  function resolveImportUri(imp) {
5566
- if (!imp.path) return void 0;
5567
- if (!imp.path.endsWith(".zmodel")) {
5568
- imp.path += ".zmodel";
5569
- }
5570
- if (!imp.path.startsWith(".") && // Respect relative paths
5571
- !path.isAbsolute(imp.path)) {
5572
- const contextPath = imp.$container.$document ? path.dirname(imp.$container.$document.uri.fsPath) : process.cwd();
5573
- imp.path = findNodeModulesFile(imp.path, contextPath) ?? imp.path;
5404
+ if (!imp.path) {
5405
+ return void 0;
5574
5406
  }
5575
5407
  const doc = AstUtils.getDocument(imp);
5576
5408
  const dir = path.dirname(doc.uri.fsPath);
5577
- return URI.file(path.resolve(dir, imp.path));
5409
+ const importPath = imp.path.endsWith(".zmodel") ? imp.path : `${imp.path}.zmodel`;
5410
+ return URI.file(path.resolve(dir, importPath));
5578
5411
  }
5579
5412
  __name(resolveImportUri, "resolveImportUri");
5580
- function findNodeModulesFile(name, cwd = process.cwd()) {
5581
- if (!name) return void 0;
5582
- try {
5583
- const resolvedPath = __require.resolve(name, {
5584
- paths: [
5585
- cwd
5586
- ]
5587
- });
5588
- return resolvedPath;
5589
- } catch {
5590
- return void 0;
5413
+ function getDataModelAndTypeDefs(model, includeIgnored = false) {
5414
+ const r = model.declarations.filter((d) => isDataModel(d) || isTypeDef(d));
5415
+ if (includeIgnored) {
5416
+ return r;
5417
+ } else {
5418
+ return r.filter((model2) => !hasAttribute(model2, "@@ignore"));
5591
5419
  }
5592
5420
  }
5593
- __name(findNodeModulesFile, "findNodeModulesFile");
5421
+ __name(getDataModelAndTypeDefs, "getDataModelAndTypeDefs");
5594
5422
  function getAllDeclarationsIncludingImports(documents, model) {
5595
5423
  const imports = resolveTransitiveImports(documents, model);
5596
5424
  return model.declarations.concat(...imports.map((imp) => imp.declarations));
@@ -5604,10 +5432,10 @@ function getAuthDecl(decls) {
5604
5432
  return authModel;
5605
5433
  }
5606
5434
  __name(getAuthDecl, "getAuthDecl");
5607
- function isFutureInvocation(node) {
5608
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5435
+ function isBeforeInvocation(node) {
5436
+ return isInvocationExpr(node) && node.function.ref?.name === "before";
5609
5437
  }
5610
- __name(isFutureInvocation, "isFutureInvocation");
5438
+ __name(isBeforeInvocation, "isBeforeInvocation");
5611
5439
  function isCollectionPredicate(node) {
5612
5440
  return isBinaryExpr(node) && [
5613
5441
  "?",
@@ -5655,8 +5483,131 @@ function isMemberContainer(node) {
5655
5483
  return isDataModel(node) || isTypeDef(node);
5656
5484
  }
5657
5485
  __name(isMemberContainer, "isMemberContainer");
5486
+ function getAllFields(decl, includeIgnored = false, seen = /* @__PURE__ */ new Set()) {
5487
+ if (seen.has(decl)) {
5488
+ return [];
5489
+ }
5490
+ seen.add(decl);
5491
+ const fields = [];
5492
+ for (const mixin of decl.mixins) {
5493
+ if (mixin.ref) {
5494
+ fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5495
+ }
5496
+ }
5497
+ if (isDataModel(decl) && decl.baseModel) {
5498
+ if (decl.baseModel.ref) {
5499
+ fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
5500
+ }
5501
+ }
5502
+ fields.push(...decl.fields.filter((f) => includeIgnored || !hasAttribute(f, "@ignore")));
5503
+ return fields;
5504
+ }
5505
+ __name(getAllFields, "getAllFields");
5506
+ function getAllAttributes(decl, seen = /* @__PURE__ */ new Set()) {
5507
+ if (seen.has(decl)) {
5508
+ return [];
5509
+ }
5510
+ seen.add(decl);
5511
+ const attributes = [];
5512
+ for (const mixin of decl.mixins) {
5513
+ if (mixin.ref) {
5514
+ attributes.push(...getAllAttributes(mixin.ref, seen));
5515
+ }
5516
+ }
5517
+ if (isDataModel(decl) && decl.baseModel) {
5518
+ if (decl.baseModel.ref) {
5519
+ attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
5520
+ }
5521
+ }
5522
+ attributes.push(...decl.attributes);
5523
+ return attributes;
5524
+ }
5525
+ __name(getAllAttributes, "getAllAttributes");
5526
+ function getDocument(node) {
5527
+ const rootNode = findRootNode(node);
5528
+ const result = rootNode.$document;
5529
+ if (!result) {
5530
+ throw new Error("AST node has no document.");
5531
+ }
5532
+ return result;
5533
+ }
5534
+ __name(getDocument, "getDocument");
5535
+ function getPluginDocuments(model, schemaPath) {
5536
+ const result = [];
5537
+ for (const decl of model.declarations.filter(isPlugin)) {
5538
+ const providerField = decl.fields.find((f) => f.name === "provider");
5539
+ if (!providerField) {
5540
+ continue;
5541
+ }
5542
+ const provider = getLiteral(providerField.value);
5543
+ if (!provider) {
5544
+ continue;
5545
+ }
5546
+ let pluginModelFile;
5547
+ let providerPath = path.resolve(path.dirname(schemaPath), provider);
5548
+ if (fs.existsSync(providerPath)) {
5549
+ if (fs.statSync(providerPath).isDirectory()) {
5550
+ providerPath = path.join(providerPath, "index.js");
5551
+ }
5552
+ pluginModelFile = path.resolve(path.dirname(providerPath), PLUGIN_MODULE_NAME);
5553
+ if (!fs.existsSync(pluginModelFile)) {
5554
+ pluginModelFile = findUp([
5555
+ PLUGIN_MODULE_NAME
5556
+ ], path.dirname(providerPath));
5557
+ }
5558
+ }
5559
+ if (!pluginModelFile) {
5560
+ if (typeof import.meta.resolve === "function") {
5561
+ try {
5562
+ const resolvedUrl = import.meta.resolve(`${provider}/${PLUGIN_MODULE_NAME}`);
5563
+ pluginModelFile = fileURLToPath(resolvedUrl);
5564
+ } catch {
5565
+ }
5566
+ }
5567
+ }
5568
+ if (!pluginModelFile) {
5569
+ try {
5570
+ const require2 = createRequire(pathToFileURL(schemaPath));
5571
+ pluginModelFile = require2.resolve(`${provider}/${PLUGIN_MODULE_NAME}`);
5572
+ } catch {
5573
+ }
5574
+ }
5575
+ if (pluginModelFile && fs.existsSync(pluginModelFile)) {
5576
+ result.push(pluginModelFile);
5577
+ }
5578
+ }
5579
+ return result;
5580
+ }
5581
+ __name(getPluginDocuments, "getPluginDocuments");
5582
+ function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
5583
+ if (!names.some((name) => !!name)) {
5584
+ return void 0;
5585
+ }
5586
+ const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
5587
+ if (multiple === false && target) {
5588
+ return path.join(cwd, target);
5589
+ }
5590
+ if (target) {
5591
+ result.push(path.join(cwd, target));
5592
+ }
5593
+ const up = path.resolve(cwd, "..");
5594
+ if (up === cwd) {
5595
+ return multiple && result.length > 0 ? result : void 0;
5596
+ }
5597
+ return findUp(names, up, multiple, result);
5598
+ }
5599
+ __name(findUp, "findUp");
5600
+ function findRootNode(node) {
5601
+ while (node.$container) {
5602
+ node = node.$container;
5603
+ }
5604
+ return node;
5605
+ }
5606
+ __name(findRootNode, "findRootNode");
5658
5607
 
5659
5608
  // src/validators/attribute-application-validator.ts
5609
+ import { AstUtils as AstUtils2 } from "langium";
5610
+ import pluralize from "pluralize";
5660
5611
  function _ts_decorate(decorators, target, key, desc) {
5661
5612
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5662
5613
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -5682,7 +5633,7 @@ var AttributeApplicationValidator = class {
5682
5633
  static {
5683
5634
  __name(this, "AttributeApplicationValidator");
5684
5635
  }
5685
- validate(attr, accept) {
5636
+ validate(attr, accept, contextDataModel) {
5686
5637
  const decl = attr.decl.ref;
5687
5638
  if (!decl) {
5688
5639
  return;
@@ -5694,21 +5645,13 @@ var AttributeApplicationValidator = class {
5694
5645
  });
5695
5646
  return;
5696
5647
  }
5697
- if (isDataModelField(targetDecl) && !isValidAttributeTarget(decl, targetDecl)) {
5648
+ if (isDataField(targetDecl) && !isValidAttributeTarget(decl, targetDecl)) {
5698
5649
  accept("error", `attribute "${decl.name}" cannot be used on this type of field`, {
5699
5650
  node: attr
5700
5651
  });
5701
5652
  }
5702
- if (isTypeDefField(targetDecl) && !hasAttribute(decl, "@@@supportTypeDef")) {
5703
- accept("error", `attribute "${decl.name}" cannot be used on type declaration fields`, {
5704
- node: attr
5705
- });
5706
- }
5707
- if (isTypeDef(targetDecl) && !hasAttribute(decl, "@@@supportTypeDef")) {
5708
- accept("error", `attribute "${decl.name}" cannot be used on type declarations`, {
5709
- node: attr
5710
- });
5711
- }
5653
+ this.checkDeprecation(attr, accept);
5654
+ this.checkDuplicatedAttributes(attr, accept, contextDataModel);
5712
5655
  const filledParams = /* @__PURE__ */ new Set();
5713
5656
  for (const arg of attr.args) {
5714
5657
  let paramDecl;
@@ -5756,6 +5699,29 @@ var AttributeApplicationValidator = class {
5756
5699
  checker.value.call(this, attr, accept);
5757
5700
  }
5758
5701
  }
5702
+ checkDeprecation(attr, accept) {
5703
+ const deprecateAttr = attr.decl.ref?.attributes.find((a) => a.decl.ref?.name === "@@@deprecated");
5704
+ if (deprecateAttr) {
5705
+ const message = getStringLiteral(deprecateAttr.args[0]?.value) ?? `Attribute "${attr.decl.ref?.name}" is deprecated`;
5706
+ accept("warning", message, {
5707
+ node: attr
5708
+ });
5709
+ }
5710
+ }
5711
+ checkDuplicatedAttributes(attr, accept, contextDataModel) {
5712
+ const attrDecl = attr.decl.ref;
5713
+ if (!attrDecl?.attributes.some((a) => a.decl.ref?.name === "@@@once")) {
5714
+ return;
5715
+ }
5716
+ const allAttributes = contextDataModel ? getAllAttributes(contextDataModel) : attr.$container.attributes;
5717
+ const duplicates = allAttributes.filter((a) => a.decl.ref === attrDecl && a !== attr);
5718
+ if (duplicates.length > 0) {
5719
+ accept("error", `Attribute "${attrDecl.name}" can only be applied once`, {
5720
+ node: attr
5721
+ });
5722
+ }
5723
+ }
5724
+ // TODO: design a way to let plugin register validation
5759
5725
  _checkModelLevelPolicy(attr, accept) {
5760
5726
  const kind = getStringLiteral(attr.args[0]?.value);
5761
5727
  if (!kind) {
@@ -5768,11 +5734,61 @@ var AttributeApplicationValidator = class {
5768
5734
  "create",
5769
5735
  "read",
5770
5736
  "update",
5737
+ "post-update",
5771
5738
  "delete",
5772
5739
  "all"
5773
5740
  ], attr, accept);
5774
- this.rejectEncryptedFields(attr, accept);
5741
+ if ((kind === "create" || kind === "all") && attr.args[1]?.value) {
5742
+ this.rejectNonOwnedRelationInExpression(attr.args[1].value, accept);
5743
+ }
5744
+ if (kind !== "post-update" && attr.args[1]?.value) {
5745
+ const beforeCall = AstUtils2.streamAst(attr.args[1]?.value).find(isBeforeInvocation);
5746
+ if (beforeCall) {
5747
+ accept("error", `"before()" is only allowed in "post-update" policy rules`, {
5748
+ node: beforeCall
5749
+ });
5750
+ }
5751
+ }
5752
+ }
5753
+ rejectNonOwnedRelationInExpression(expr, accept) {
5754
+ const contextModel = AstUtils2.getContainerOfType(expr, isDataModel);
5755
+ if (!contextModel) {
5756
+ return;
5757
+ }
5758
+ if (AstUtils2.streamAst(expr).some((node) => {
5759
+ if (!isDataFieldReference(node)) {
5760
+ return false;
5761
+ }
5762
+ if (node.target.ref?.$container !== contextModel) {
5763
+ return false;
5764
+ }
5765
+ const field = node.target.ref;
5766
+ if (!isRelationshipField(field)) {
5767
+ return false;
5768
+ }
5769
+ if (isAuthOrAuthMemberAccess(node)) {
5770
+ return false;
5771
+ }
5772
+ const startNode = isCollectionPredicate(node.$container) && node.$container.left === node ? node.$container : node;
5773
+ const collectionPredicate = AstUtils2.getContainerOfType(startNode.$container, isCollectionPredicate);
5774
+ if (collectionPredicate && isAuthOrAuthMemberAccess(collectionPredicate.left)) {
5775
+ return false;
5776
+ }
5777
+ const relationAttr = field.attributes.find((attr) => attr.decl.ref?.name === "@relation");
5778
+ if (!relationAttr) {
5779
+ return true;
5780
+ }
5781
+ if (!relationAttr.args.some((arg) => arg.name === "fields")) {
5782
+ return true;
5783
+ }
5784
+ return false;
5785
+ })) {
5786
+ accept("error", `non-owned relation fields are not allowed in "create" rules`, {
5787
+ node: expr
5788
+ });
5789
+ }
5775
5790
  }
5791
+ // TODO: design a way to let plugin register validation
5776
5792
  _checkFieldLevelPolicy(attr, accept) {
5777
5793
  const kind = getStringLiteral(attr.args[0]?.value);
5778
5794
  if (!kind) {
@@ -5787,8 +5803,8 @@ var AttributeApplicationValidator = class {
5787
5803
  "all"
5788
5804
  ], attr, accept);
5789
5805
  const expr = attr.args[1]?.value;
5790
- if (expr && AstUtils2.streamAst(expr).some((node) => isFutureExpr(node))) {
5791
- accept("error", `"future()" is not allowed in field-level policy rules`, {
5806
+ if (expr && AstUtils2.streamAst(expr).some((node) => isBeforeInvocation(node))) {
5807
+ accept("error", `"before()" is not allowed in field-level policy rules`, {
5792
5808
  node: expr
5793
5809
  });
5794
5810
  }
@@ -5800,11 +5816,10 @@ var AttributeApplicationValidator = class {
5800
5816
  });
5801
5817
  }
5802
5818
  }
5803
- this.rejectEncryptedFields(attr, accept);
5804
5819
  }
5805
5820
  _checkValidate(attr, accept) {
5806
5821
  const condition = attr.args[0]?.value;
5807
- if (condition && AstUtils2.streamAst(condition).some((node) => isDataModelFieldReference(node) && isDataModel(node.$resolvedType?.decl))) {
5822
+ if (condition && AstUtils2.streamAst(condition).some((node) => isDataFieldReference(node) && isDataModel(node.$resolvedType?.decl))) {
5808
5823
  accept("error", `\`@@validate\` condition cannot use relation fields`, {
5809
5824
  node: condition
5810
5825
  });
@@ -5813,9 +5828,18 @@ var AttributeApplicationValidator = class {
5813
5828
  _checkUnique(attr, accept) {
5814
5829
  const fields = attr.args[0]?.value;
5815
5830
  if (!fields) {
5831
+ accept("error", `expects an array of field references`, {
5832
+ node: attr.args[0]
5833
+ });
5816
5834
  return;
5817
5835
  }
5818
5836
  if (isArrayExpr(fields)) {
5837
+ if (fields.items.length === 0) {
5838
+ accept("error", `\`@@unique\` expects at least one field reference`, {
5839
+ node: fields
5840
+ });
5841
+ return;
5842
+ }
5819
5843
  fields.items.forEach((item) => {
5820
5844
  if (!isReferenceExpr(item)) {
5821
5845
  accept("error", `Expecting a field reference`, {
@@ -5823,7 +5847,7 @@ var AttributeApplicationValidator = class {
5823
5847
  });
5824
5848
  return;
5825
5849
  }
5826
- if (!isDataModelField(item.target.ref)) {
5850
+ if (!isDataField(item.target.ref)) {
5827
5851
  accept("error", `Expecting a field reference`, {
5828
5852
  node: item
5829
5853
  });
@@ -5841,15 +5865,6 @@ var AttributeApplicationValidator = class {
5841
5865
  });
5842
5866
  }
5843
5867
  }
5844
- rejectEncryptedFields(attr, accept) {
5845
- AstUtils2.streamAllContents(attr).forEach((node) => {
5846
- if (isDataModelFieldReference(node) && hasAttribute(node.target.ref, "@encrypted")) {
5847
- accept("error", `Encrypted fields cannot be used in policy rules`, {
5848
- node
5849
- });
5850
- }
5851
- });
5852
- }
5853
5868
  validatePolicyKinds(kind, candidates, attr, accept) {
5854
5869
  const items = kind.split(",").map((x) => x.trim());
5855
5870
  items.forEach((item) => {
@@ -5893,6 +5908,7 @@ _ts_decorate([
5893
5908
  ], AttributeApplicationValidator.prototype, "_checkValidate", null);
5894
5909
  _ts_decorate([
5895
5910
  check("@@unique"),
5911
+ check("@@id"),
5896
5912
  _ts_metadata("design:type", Function),
5897
5913
  _ts_metadata("design:paramtypes", [
5898
5914
  typeof AttributeApplication === "undefined" ? Object : AttributeApplication,
@@ -5908,7 +5924,11 @@ function assignableToAttributeParam(arg, param, attr) {
5908
5924
  let dstType = param.type.type;
5909
5925
  let dstIsArray = param.type.array;
5910
5926
  if (dstType === "ContextType") {
5911
- if (isDataModelField(attr.$container)) {
5927
+ if (isDataField(attr.$container)) {
5928
+ const dstIsTypedJson = hasAttribute(attr.$container, "@json");
5929
+ if (dstIsTypedJson && attr.decl.ref?.name === "@default") {
5930
+ return argResolvedType.decl === "String";
5931
+ }
5912
5932
  dstIsArray = attr.$container.type.array;
5913
5933
  }
5914
5934
  }
@@ -5925,14 +5945,14 @@ function assignableToAttributeParam(arg, param, attr) {
5925
5945
  }
5926
5946
  if (dstType === "FieldReference" || dstType === "TransitiveFieldReference") {
5927
5947
  if (dstIsArray) {
5928
- return isArrayExpr(arg.value) && !arg.value.items.find((item) => !isReferenceExpr(item) || !isDataModelField(item.target.ref));
5948
+ return isArrayExpr(arg.value) && !arg.value.items.find((item) => !isReferenceExpr(item) || !isDataField(item.target.ref));
5929
5949
  } else {
5930
- return isReferenceExpr(arg.value) && isDataModelField(arg.value.target.ref);
5950
+ return isReferenceExpr(arg.value) && isDataField(arg.value.target.ref);
5931
5951
  }
5932
5952
  }
5933
5953
  if (isEnum(argResolvedType.decl)) {
5934
5954
  let attrArgDeclType = dstRef?.ref;
5935
- if (dstType === "ContextType" && isDataModelField(attr.$container) && attr.$container?.type?.reference) {
5955
+ if (dstType === "ContextType" && isDataField(attr.$container) && attr.$container?.type?.reference) {
5936
5956
  attrArgDeclType = resolved(attr.$container.type.reference);
5937
5957
  dstIsArray = attr.$container.type.array;
5938
5958
  }
@@ -5942,7 +5962,7 @@ function assignableToAttributeParam(arg, param, attr) {
5942
5962
  return false;
5943
5963
  }
5944
5964
  if (dstType === "ContextType") {
5945
- if (isDataModelField(attr.$container)) {
5965
+ if (isDataField(attr.$container)) {
5946
5966
  if (!attr.$container?.type?.type) {
5947
5967
  return false;
5948
5968
  }
@@ -6000,6 +6020,9 @@ function isValidAttributeTarget(attrDecl, targetDecl) {
6000
6020
  case "TypeDefField":
6001
6021
  allowed = allowed || isTypeDef(targetDecl.type.reference?.ref);
6002
6022
  break;
6023
+ case "ListField":
6024
+ allowed = allowed || !isDataModel(targetDecl.type.reference?.ref) && targetDecl.type.array;
6025
+ break;
6003
6026
  default:
6004
6027
  break;
6005
6028
  }
@@ -6010,8 +6033,8 @@ function isValidAttributeTarget(attrDecl, targetDecl) {
6010
6033
  return allowed;
6011
6034
  }
6012
6035
  __name(isValidAttributeTarget, "isValidAttributeTarget");
6013
- function validateAttributeApplication(attr, accept) {
6014
- new AttributeApplicationValidator().validate(attr, accept);
6036
+ function validateAttributeApplication(attr, accept, contextDataModel) {
6037
+ new AttributeApplicationValidator().validate(attr, accept, contextDataModel);
6015
6038
  }
6016
6039
  __name(validateAttributeApplication, "validateAttributeApplication");
6017
6040
 
@@ -6026,6 +6049,7 @@ var AttributeValidator = class {
6026
6049
  };
6027
6050
 
6028
6051
  // src/validators/datamodel-validator.ts
6052
+ import { invariant } from "@zenstackhq/common-helpers";
6029
6053
  import { AstUtils as AstUtils3 } from "langium";
6030
6054
 
6031
6055
  // src/validators/common.ts
@@ -6038,8 +6062,8 @@ function validateDuplicatedDeclarations(container, decls, accept) {
6038
6062
  for (const [name, decls2] of Object.entries(groupByName)) {
6039
6063
  if (decls2.length > 1) {
6040
6064
  let errorField = decls2[1];
6041
- if (isDataModelField(decls2[0])) {
6042
- const nonInheritedFields = decls2.filter((x) => !(isDataModelField(x) && x.$container !== container));
6065
+ if (isDataField(decls2[0])) {
6066
+ const nonInheritedFields = decls2.filter((x) => !(isDataField(x) && x.$container !== container));
6043
6067
  if (nonInheritedFields.length > 0) {
6044
6068
  errorField = nonInheritedFields.slice(-1)[0];
6045
6069
  }
@@ -6058,22 +6082,21 @@ var DataModelValidator = class {
6058
6082
  __name(this, "DataModelValidator");
6059
6083
  }
6060
6084
  validate(dm, accept) {
6061
- this.validateBaseAbstractModel(dm, accept);
6062
- this.validateBaseDelegateModel(dm, accept);
6063
- validateDuplicatedDeclarations(dm, getModelFieldsWithBases(dm), accept);
6085
+ validateDuplicatedDeclarations(dm, getAllFields(dm), accept);
6064
6086
  this.validateAttributes(dm, accept);
6065
6087
  this.validateFields(dm, accept);
6066
- if (dm.superTypes.length > 0) {
6067
- this.validateInheritance(dm, accept);
6088
+ if (dm.mixins.length > 0) {
6089
+ this.validateMixins(dm, accept);
6068
6090
  }
6091
+ this.validateInherits(dm, accept);
6069
6092
  }
6070
6093
  validateFields(dm, accept) {
6071
- const allFields = getModelFieldsWithBases(dm);
6094
+ const allFields = getAllFields(dm);
6072
6095
  const idFields = allFields.filter((f) => f.attributes.find((attr) => attr.decl.ref?.name === "@id"));
6073
6096
  const uniqueFields = allFields.filter((f) => f.attributes.find((attr) => attr.decl.ref?.name === "@unique"));
6074
6097
  const modelLevelIds = getModelIdFields(dm);
6075
6098
  const modelUniqueFields = getModelUniqueFields(dm);
6076
- if (!dm.isAbstract && idFields.length === 0 && modelLevelIds.length === 0 && uniqueFields.length === 0 && modelUniqueFields.length === 0) {
6099
+ if (idFields.length === 0 && modelLevelIds.length === 0 && uniqueFields.length === 0 && modelUniqueFields.length === 0) {
6077
6100
  accept("error", "Model must have at least one unique criteria. Either mark a single field with `@id`, `@unique` or add a multi field criterion with `@@id([])` or `@@unique([])` to the model.", {
6078
6101
  node: dm
6079
6102
  });
@@ -6104,11 +6127,9 @@ var DataModelValidator = class {
6104
6127
  });
6105
6128
  }
6106
6129
  dm.fields.forEach((field) => this.validateField(field, accept));
6107
- if (!dm.isAbstract) {
6108
- allFields.filter((x) => isDataModel(x.type.reference?.ref)).forEach((y) => {
6109
- this.validateRelationField(dm, y, accept);
6110
- });
6111
- }
6130
+ allFields.filter((x) => isDataModel(x.type.reference?.ref)).forEach((y) => {
6131
+ this.validateRelationField(dm, y, accept);
6132
+ });
6112
6133
  }
6113
6134
  validateField(field, accept) {
6114
6135
  if (field.type.array && field.type.optional) {
@@ -6124,7 +6145,7 @@ var DataModelValidator = class {
6124
6145
  if (field.type.array && !isDataModel(field.type.reference?.ref)) {
6125
6146
  const provider = this.getDataSourceProvider(AstUtils3.getContainerOfType(field, isModel));
6126
6147
  if (provider === "sqlite") {
6127
- accept("error", `Array type is not supported for "${provider}" provider.`, {
6148
+ accept("error", `List type is not supported for "${provider}" provider.`, {
6128
6149
  node: field.type
6129
6150
  });
6130
6151
  }
@@ -6150,7 +6171,7 @@ var DataModelValidator = class {
6150
6171
  return getLiteral(provider.value);
6151
6172
  }
6152
6173
  validateAttributes(dm, accept) {
6153
- dm.attributes.forEach((attr) => validateAttributeApplication(attr, accept));
6174
+ getAllAttributes(dm).forEach((attr) => validateAttributeApplication(attr, accept, dm));
6154
6175
  }
6155
6176
  parseRelation(field, accept) {
6156
6177
  const relAttr = field.attributes.find((attr) => attr.decl.ref?.name === "@relation");
@@ -6269,11 +6290,20 @@ var DataModelValidator = class {
6269
6290
  if (!thisRelation.valid) {
6270
6291
  return;
6271
6292
  }
6272
- if (this.isFieldInheritedFromDelegateModel(field, contextModel)) {
6293
+ if (this.isFieldInheritedFromDelegateModel(field)) {
6273
6294
  return;
6274
6295
  }
6296
+ if (this.isSelfRelation(field)) {
6297
+ if (!thisRelation.name) {
6298
+ accept("error", "Self-relation field must have a name in @relation attribute", {
6299
+ node: field
6300
+ });
6301
+ return;
6302
+ }
6303
+ }
6275
6304
  const oppositeModel = field.type.reference.ref;
6276
- let oppositeFields = getModelFieldsWithBases(oppositeModel, false).filter((f) => f.type.reference?.ref?.name === contextModel.name);
6305
+ let oppositeFields = getAllFields(oppositeModel, false).filter((f) => f !== field && // exclude self in case of self relation
6306
+ f.type.reference?.ref?.name === contextModel.name);
6277
6307
  oppositeFields = oppositeFields.filter((f) => {
6278
6308
  const fieldRel = this.parseRelation(f);
6279
6309
  return fieldRel.valid && fieldRel.name === thisRelation.name;
@@ -6310,26 +6340,37 @@ var DataModelValidator = class {
6310
6340
  const oppositeField = oppositeFields[0];
6311
6341
  const oppositeRelation = this.parseRelation(oppositeField);
6312
6342
  let relationOwner;
6313
- if (thisRelation?.references?.length && thisRelation.fields?.length) {
6314
- if (oppositeRelation?.references || oppositeRelation?.fields) {
6315
- accept("error", '"fields" and "references" must be provided only on one side of relation field', {
6316
- node: oppositeField
6317
- });
6318
- return;
6319
- } else {
6320
- relationOwner = oppositeField;
6321
- }
6322
- } else if (oppositeRelation?.references?.length && oppositeRelation.fields?.length) {
6323
- if (thisRelation?.references || thisRelation?.fields) {
6324
- accept("error", '"fields" and "references" must be provided only on one side of relation field', {
6325
- node: field
6326
- });
6327
- return;
6328
- } else {
6329
- relationOwner = field;
6343
+ if (field.type.array && oppositeField.type.array) {
6344
+ for (const r of [
6345
+ thisRelation,
6346
+ oppositeRelation
6347
+ ]) {
6348
+ if (r.fields?.length || r.references?.length) {
6349
+ accept("error", 'Implicit many-to-many relation cannot have "fields" or "references" in @relation attribute', {
6350
+ node: r === thisRelation ? field : oppositeField
6351
+ });
6352
+ }
6330
6353
  }
6331
6354
  } else {
6332
- if (!(field.type.array && oppositeField.type.array)) {
6355
+ if (thisRelation?.references?.length && thisRelation.fields?.length) {
6356
+ if (oppositeRelation?.references || oppositeRelation?.fields) {
6357
+ accept("error", '"fields" and "references" must be provided only on one side of relation field', {
6358
+ node: oppositeField
6359
+ });
6360
+ return;
6361
+ } else {
6362
+ relationOwner = oppositeField;
6363
+ }
6364
+ } else if (oppositeRelation?.references?.length && oppositeRelation.fields?.length) {
6365
+ if (thisRelation?.references || thisRelation?.fields) {
6366
+ accept("error", '"fields" and "references" must be provided only on one side of relation field', {
6367
+ node: field
6368
+ });
6369
+ return;
6370
+ } else {
6371
+ relationOwner = field;
6372
+ }
6373
+ } else {
6333
6374
  [
6334
6375
  field,
6335
6376
  oppositeField
@@ -6340,78 +6381,85 @@ var DataModelValidator = class {
6340
6381
  });
6341
6382
  }
6342
6383
  });
6384
+ return;
6343
6385
  }
6344
- return;
6345
- }
6346
- if (!relationOwner.type.array && !relationOwner.type.optional) {
6347
- accept("error", "Relation field needs to be list or optional", {
6348
- node: relationOwner
6349
- });
6350
- return;
6351
- }
6352
- if (relationOwner !== field && !relationOwner.type.array) {
6353
- const containingModel = field.$container;
6354
- const uniqueFieldList = getUniqueFields(containingModel);
6355
- if (containingModel !== contextModel) {
6356
- uniqueFieldList.push(...getUniqueFields(contextModel));
6386
+ if (!relationOwner.type.array && !relationOwner.type.optional) {
6387
+ accept("error", "Relation field needs to be list or optional", {
6388
+ node: relationOwner
6389
+ });
6390
+ return;
6357
6391
  }
6358
- thisRelation.fields?.forEach((ref) => {
6359
- const refField = ref.target.ref;
6360
- if (refField) {
6361
- if (refField.attributes.find((a) => a.decl.ref?.name === "@id" || a.decl.ref?.name === "@unique")) {
6362
- return;
6363
- }
6364
- if (uniqueFieldList.some((list) => list.includes(refField))) {
6365
- return;
6366
- }
6367
- accept("error", `Field "${refField.name}" on model "${containingModel.name}" is part of a one-to-one relation and must be marked as @unique or be part of a model-level @@unique attribute`, {
6368
- node: refField
6369
- });
6392
+ if (relationOwner !== field && !relationOwner.type.array) {
6393
+ const containingModel = field.$container;
6394
+ const uniqueFieldList = getUniqueFields(containingModel);
6395
+ if (containingModel !== contextModel) {
6396
+ uniqueFieldList.push(...getUniqueFields(contextModel));
6370
6397
  }
6371
- });
6398
+ thisRelation.fields?.forEach((ref) => {
6399
+ const refField = ref.target.ref;
6400
+ if (refField) {
6401
+ if (refField.attributes.find((a) => a.decl.ref?.name === "@id" || a.decl.ref?.name === "@unique")) {
6402
+ return;
6403
+ }
6404
+ if (uniqueFieldList.some((list) => list.includes(refField))) {
6405
+ return;
6406
+ }
6407
+ accept("error", `Field "${refField.name}" on model "${containingModel.name}" is part of a one-to-one relation and must be marked as @unique or be part of a model-level @@unique attribute`, {
6408
+ node: refField
6409
+ });
6410
+ }
6411
+ });
6412
+ }
6372
6413
  }
6373
6414
  }
6374
6415
  // checks if the given field is inherited directly or indirectly from a delegate model
6375
- isFieldInheritedFromDelegateModel(field, contextModel) {
6376
- const basePath = findUpInheritance(contextModel, field.$container);
6377
- if (basePath && basePath.some(isDelegateModel)) {
6378
- return true;
6379
- } else {
6380
- return false;
6381
- }
6382
- }
6383
- validateBaseAbstractModel(model, accept) {
6384
- model.superTypes.forEach((superType, index) => {
6385
- if (!superType.ref?.isAbstract && !superType.ref?.attributes.some((attr) => attr.decl.ref?.name === "@@delegate")) accept("error", `Model ${superType.$refText} cannot be extended because it's neither abstract nor marked as "@@delegate"`, {
6386
- node: model,
6387
- property: "superTypes",
6388
- index
6389
- });
6390
- });
6416
+ isFieldInheritedFromDelegateModel(field) {
6417
+ return isDelegateModel(field.$container);
6391
6418
  }
6392
- validateBaseDelegateModel(model, accept) {
6393
- if (model.superTypes.filter((base) => base.ref && isDelegateModel(base.ref)).length > 1) {
6394
- accept("error", "Extending from multiple delegate models is not supported", {
6419
+ validateInherits(model, accept) {
6420
+ if (!model.baseModel) {
6421
+ return;
6422
+ }
6423
+ invariant(model.baseModel.ref, "baseModel must be resolved");
6424
+ if (!isDelegateModel(model.baseModel.ref)) {
6425
+ accept("error", `Model ${model.baseModel.$refText} cannot be extended because it's not a delegate model`, {
6395
6426
  node: model,
6396
- property: "superTypes"
6427
+ property: "baseModel"
6397
6428
  });
6429
+ return;
6398
6430
  }
6399
- }
6400
- validateInheritance(dm, accept) {
6401
- const seen = [
6402
- dm
6431
+ const seen = [];
6432
+ const todo = [
6433
+ model.baseModel.ref
6403
6434
  ];
6404
- const todo = dm.superTypes.map((superType) => superType.ref);
6405
6435
  while (todo.length > 0) {
6406
6436
  const current = todo.shift();
6407
6437
  if (seen.includes(current)) {
6408
- accept("error", `Circular inheritance detected: ${seen.map((m) => m.name).join(" -> ")} -> ${current.name}`, {
6438
+ accept("error", `Cyclic inheritance detected: ${seen.map((m) => m.name).join(" -> ")} -> ${current.name}`, {
6439
+ node: model
6440
+ });
6441
+ return;
6442
+ }
6443
+ seen.push(current);
6444
+ if (current.baseModel) {
6445
+ invariant(current.baseModel.ref, "baseModel must be resolved");
6446
+ todo.push(current.baseModel.ref);
6447
+ }
6448
+ }
6449
+ }
6450
+ validateMixins(dm, accept) {
6451
+ const seen = [];
6452
+ const todo = dm.mixins.map((mixin) => mixin.ref);
6453
+ while (todo.length > 0) {
6454
+ const current = todo.shift();
6455
+ if (seen.includes(current)) {
6456
+ accept("error", `Cyclic mixin detected: ${seen.map((m) => m.name).join(" -> ")} -> ${current.name}`, {
6409
6457
  node: dm
6410
6458
  });
6411
6459
  return;
6412
6460
  }
6413
6461
  seen.push(current);
6414
- todo.push(...current.superTypes.map((superType) => superType.ref));
6462
+ todo.push(...current.mixins.map((mixin) => mixin.ref));
6415
6463
  }
6416
6464
  }
6417
6465
  };
@@ -6447,26 +6495,15 @@ var DataSourceValidator = class {
6447
6495
  }
6448
6496
  }
6449
6497
  validateUrl(ds, accept) {
6450
- const url = ds.fields.find((f) => f.name === "url");
6451
- if (!url) {
6452
- accept("error", 'datasource must include a "url" field', {
6453
- node: ds
6454
- });
6498
+ const urlField = ds.fields.find((f) => f.name === "url");
6499
+ if (!urlField) {
6500
+ return;
6455
6501
  }
6456
- for (const fieldName of [
6457
- "url",
6458
- "shadowDatabaseUrl"
6459
- ]) {
6460
- const field = ds.fields.find((f) => f.name === fieldName);
6461
- if (!field) {
6462
- continue;
6463
- }
6464
- const value = getStringLiteral(field.value);
6465
- if (!value && !(isInvocationExpr(field.value) && field.value.function.ref?.name === "env")) {
6466
- accept("error", `"${fieldName}" must be set to a string literal or an invocation of "env" function`, {
6467
- node: field.value
6468
- });
6469
- }
6502
+ const value = getStringLiteral(urlField.value);
6503
+ if (!value && !(isInvocationExpr(urlField.value) && urlField.value.function.ref?.name === "env")) {
6504
+ accept("error", `"${urlField.name}" must be set to a string literal or an invocation of "env" function`, {
6505
+ node: urlField.value
6506
+ });
6470
6507
  }
6471
6508
  }
6472
6509
  validateRelationMode(ds, accept) {
@@ -6535,11 +6572,21 @@ var ExpressionValidator = class {
6535
6572
  }
6536
6573
  }
6537
6574
  switch (expr.$type) {
6575
+ case "MemberAccessExpr":
6576
+ this.validateMemberAccessExpr(expr, accept);
6577
+ break;
6538
6578
  case "BinaryExpr":
6539
6579
  this.validateBinaryExpr(expr, accept);
6540
6580
  break;
6541
6581
  }
6542
6582
  }
6583
+ validateMemberAccessExpr(expr, accept) {
6584
+ if (isBeforeInvocation(expr.operand) && isDataModel(expr.$resolvedType?.decl)) {
6585
+ accept("error", "relation fields cannot be accessed from `before()`", {
6586
+ node: expr
6587
+ });
6588
+ }
6589
+ }
6543
6590
  validateBinaryExpr(expr, accept) {
6544
6591
  switch (expr.operator) {
6545
6592
  case "in": {
@@ -6592,23 +6639,25 @@ var ExpressionValidator = class {
6592
6639
  "Any"
6593
6640
  ];
6594
6641
  }
6595
- if (typeof expr.left.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.left.$resolvedType.decl)) {
6642
+ const leftResolvedDecl = expr.left.$resolvedType?.decl;
6643
+ const rightResolvedDecl = expr.right.$resolvedType?.decl;
6644
+ if (leftResolvedDecl && (typeof leftResolvedDecl !== "string" || !supportedShapes.includes(leftResolvedDecl))) {
6596
6645
  accept("error", `invalid operand type for "${expr.operator}" operator`, {
6597
6646
  node: expr.left
6598
6647
  });
6599
6648
  return;
6600
6649
  }
6601
- if (typeof expr.right.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.right.$resolvedType.decl)) {
6650
+ if (rightResolvedDecl && (typeof rightResolvedDecl !== "string" || !supportedShapes.includes(rightResolvedDecl))) {
6602
6651
  accept("error", `invalid operand type for "${expr.operator}" operator`, {
6603
6652
  node: expr.right
6604
6653
  });
6605
6654
  return;
6606
6655
  }
6607
- if (expr.left.$resolvedType.decl === "DateTime" && expr.right.$resolvedType.decl !== "DateTime") {
6656
+ if (leftResolvedDecl === "DateTime" && rightResolvedDecl && rightResolvedDecl !== "DateTime") {
6608
6657
  accept("error", "incompatible operand types", {
6609
6658
  node: expr
6610
6659
  });
6611
- } else if (expr.right.$resolvedType.decl === "DateTime" && expr.left.$resolvedType.decl !== "DateTime") {
6660
+ } else if (rightResolvedDecl === "DateTime" && leftResolvedDecl && leftResolvedDecl !== "DateTime") {
6612
6661
  accept("error", "incompatible operand types", {
6613
6662
  node: expr
6614
6663
  });
@@ -6618,7 +6667,7 @@ var ExpressionValidator = class {
6618
6667
  case "==":
6619
6668
  case "!=": {
6620
6669
  if (this.isInValidationContext(expr)) {
6621
- if (isDataModelFieldReference(expr.left) && isNullExpr(expr.right) || isDataModelFieldReference(expr.right) && isNullExpr(expr.left)) {
6670
+ if (isDataFieldReference(expr.left) && isNullExpr(expr.right) || isDataFieldReference(expr.right) && isNullExpr(expr.left)) {
6622
6671
  return;
6623
6672
  }
6624
6673
  }
@@ -6647,12 +6696,12 @@ var ExpressionValidator = class {
6647
6696
  node: expr
6648
6697
  });
6649
6698
  }
6650
- if (isDataModelFieldReference(expr.left) && (isThisExpr(expr.right) || isDataModelFieldReference(expr.right))) {
6651
- accept("error", "comparison between model-typed fields are not supported", {
6699
+ if (isDataFieldReference(expr.left) && (isThisExpr(expr.right) || isDataFieldReference(expr.right))) {
6700
+ accept("error", "comparison between models is not supported", {
6652
6701
  node: expr
6653
6702
  });
6654
- } else if (isDataModelFieldReference(expr.right) && (isThisExpr(expr.left) || isDataModelFieldReference(expr.left))) {
6655
- accept("error", "comparison between model-typed fields are not supported", {
6703
+ } else if (isDataFieldReference(expr.right) && (isThisExpr(expr.left) || isDataFieldReference(expr.left))) {
6704
+ accept("error", "comparison between models is not supported", {
6656
6705
  node: expr
6657
6706
  });
6658
6707
  }
@@ -6742,41 +6791,39 @@ var FunctionInvocationValidator = class {
6742
6791
  if (!this.validateArgs(funcDecl, expr.args, accept)) {
6743
6792
  return;
6744
6793
  }
6745
- if (isFromStdlib(funcDecl)) {
6746
- let curr = expr.$container;
6747
- let containerAttribute;
6748
- while (curr) {
6749
- if (isDataModelAttribute(curr) || isDataModelFieldAttribute(curr)) {
6750
- containerAttribute = curr;
6751
- break;
6752
- }
6753
- curr = curr.$container;
6794
+ let curr = expr.$container;
6795
+ let containerAttribute;
6796
+ while (curr) {
6797
+ if (isDataModelAttribute(curr) || isDataFieldAttribute(curr)) {
6798
+ containerAttribute = curr;
6799
+ break;
6754
6800
  }
6755
- const exprContext = match(containerAttribute?.decl.$refText).with("@default", () => ExpressionContext.DefaultValue).with(P.union("@@allow", "@@deny", "@allow", "@deny"), () => ExpressionContext.AccessPolicy).with("@@validate", () => ExpressionContext.ValidationRule).with("@@index", () => ExpressionContext.Index).otherwise(() => void 0);
6756
- const funcAllowedContext = getFunctionExpressionContext(funcDecl);
6757
- if (exprContext && !funcAllowedContext.includes(exprContext)) {
6758
- accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
6759
- node: expr
6801
+ curr = curr.$container;
6802
+ }
6803
+ const exprContext = this.getExpressionContext(containerAttribute);
6804
+ const funcAllowedContext = getFunctionExpressionContext(funcDecl);
6805
+ if (exprContext && !funcAllowedContext.includes(exprContext)) {
6806
+ accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
6807
+ node: expr
6808
+ });
6809
+ return;
6810
+ }
6811
+ const allCasing = [
6812
+ "original",
6813
+ "upper",
6814
+ "lower",
6815
+ "capitalize",
6816
+ "uncapitalize"
6817
+ ];
6818
+ if ([
6819
+ "currentModel",
6820
+ "currentOperation"
6821
+ ].includes(funcDecl.name)) {
6822
+ const arg = getLiteral(expr.args[0]?.value);
6823
+ if (arg && !allCasing.includes(arg)) {
6824
+ accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
6825
+ node: expr.args[0]
6760
6826
  });
6761
- return;
6762
- }
6763
- const allCasing = [
6764
- "original",
6765
- "upper",
6766
- "lower",
6767
- "capitalize",
6768
- "uncapitalize"
6769
- ];
6770
- if ([
6771
- "currentModel",
6772
- "currentOperation"
6773
- ].includes(funcDecl.name)) {
6774
- const arg = getLiteral(expr.args[0]?.value);
6775
- if (arg && !allCasing.includes(arg)) {
6776
- accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
6777
- node: expr.args[0]
6778
- });
6779
- }
6780
6827
  }
6781
6828
  }
6782
6829
  const checker = invocationCheckers.get(expr.function.$refText);
@@ -6784,6 +6831,18 @@ var FunctionInvocationValidator = class {
6784
6831
  checker.value.call(this, expr, accept);
6785
6832
  }
6786
6833
  }
6834
+ getExpressionContext(containerAttribute) {
6835
+ if (!containerAttribute) {
6836
+ return void 0;
6837
+ }
6838
+ if (this.isValidationAttribute(containerAttribute)) {
6839
+ return ExpressionContext.ValidationRule;
6840
+ }
6841
+ return match(containerAttribute?.decl.$refText).with("@default", () => ExpressionContext.DefaultValue).with(P.union("@@allow", "@@deny", "@allow", "@deny"), () => ExpressionContext.AccessPolicy).with("@@index", () => ExpressionContext.Index).otherwise(() => void 0);
6842
+ }
6843
+ isValidationAttribute(attr) {
6844
+ return !!attr.decl.ref?.attributes.some((attr2) => attr2.decl.$refText === "@@@validation");
6845
+ }
6787
6846
  validateArgs(funcDecl, args, accept) {
6788
6847
  let success = true;
6789
6848
  for (let i = 0; i < funcDecl.params.length; i++) {
@@ -6844,10 +6903,48 @@ var FunctionInvocationValidator = class {
6844
6903
  }
6845
6904
  return true;
6846
6905
  }
6906
+ _checkLength(expr, accept) {
6907
+ const msg = "argument must be a string or list field";
6908
+ const fieldArg = expr.args[0].value;
6909
+ if (!isDataFieldReference(fieldArg)) {
6910
+ accept("error", msg, {
6911
+ node: expr.args[0]
6912
+ });
6913
+ return;
6914
+ }
6915
+ if (isDataModel(fieldArg.$resolvedType?.decl)) {
6916
+ accept("error", msg, {
6917
+ node: expr.args[0]
6918
+ });
6919
+ return;
6920
+ }
6921
+ if (!fieldArg.$resolvedType?.array && fieldArg.$resolvedType?.decl !== "String") {
6922
+ accept("error", msg, {
6923
+ node: expr.args[0]
6924
+ });
6925
+ }
6926
+ }
6927
+ _checkRegex(expr, accept) {
6928
+ const regex = expr.args[1]?.value;
6929
+ if (!isStringLiteral(regex)) {
6930
+ accept("error", "second argument must be a string literal", {
6931
+ node: expr.args[1]
6932
+ });
6933
+ return;
6934
+ }
6935
+ try {
6936
+ new RegExp(regex.value);
6937
+ } catch (e) {
6938
+ accept("error", "invalid regular expression: " + e.message, {
6939
+ node: expr.args[1]
6940
+ });
6941
+ }
6942
+ }
6943
+ // TODO: move this to policy plugin
6847
6944
  _checkCheck(expr, accept) {
6848
6945
  let valid = true;
6849
6946
  const fieldArg = expr.args[0].value;
6850
- if (!isDataModelFieldReference(fieldArg) || !isDataModel(fieldArg.$resolvedType?.decl)) {
6947
+ if (!isDataFieldReference(fieldArg) || !isDataModel(fieldArg.$resolvedType?.decl)) {
6851
6948
  accept("error", "argument must be a relation field", {
6852
6949
  node: expr.args[0]
6853
6950
  });
@@ -6915,6 +7012,24 @@ var FunctionInvocationValidator = class {
6915
7012
  }
6916
7013
  }
6917
7014
  };
7015
+ _ts_decorate2([
7016
+ func("length"),
7017
+ _ts_metadata2("design:type", Function),
7018
+ _ts_metadata2("design:paramtypes", [
7019
+ typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
7020
+ typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
7021
+ ]),
7022
+ _ts_metadata2("design:returntype", void 0)
7023
+ ], FunctionInvocationValidator.prototype, "_checkLength", null);
7024
+ _ts_decorate2([
7025
+ func("regex"),
7026
+ _ts_metadata2("design:type", Function),
7027
+ _ts_metadata2("design:paramtypes", [
7028
+ typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
7029
+ typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
7030
+ ]),
7031
+ _ts_metadata2("design:returntype", void 0)
7032
+ ], FunctionInvocationValidator.prototype, "_checkRegex", null);
6918
7033
  _ts_decorate2([
6919
7034
  func("check"),
6920
7035
  _ts_metadata2("design:type", Function),
@@ -6962,8 +7077,8 @@ var SchemaValidator = class {
6962
7077
  validateImports(model, accept) {
6963
7078
  model.imports.forEach((imp) => {
6964
7079
  const importedModel = resolveImport(this.documents, imp);
6965
- const importPath = imp.path.endsWith(".zmodel") ? imp.path : `${imp.path}.zmodel`;
6966
7080
  if (!importedModel) {
7081
+ const importPath = imp.path.endsWith(".zmodel") ? imp.path : `${imp.path}.zmodel`;
6967
7082
  accept("error", `Cannot find model file ${importPath}`, {
6968
7083
  node: imp
6969
7084
  });
@@ -6989,6 +7104,11 @@ var TypeDefValidator = class {
6989
7104
  typeDef.fields.forEach((field) => this.validateField(field, accept));
6990
7105
  }
6991
7106
  validateField(field, accept) {
7107
+ if (isDataModel(field.type.reference?.ref)) {
7108
+ accept("error", "Type field cannot be a relation", {
7109
+ node: field.type
7110
+ });
7111
+ }
6992
7112
  field.attributes.forEach((attr) => validateAttributeApplication(attr, accept));
6993
7113
  }
6994
7114
  };
@@ -7019,49 +7139,66 @@ var ZModelValidator = class {
7019
7139
  constructor(services) {
7020
7140
  this.services = services;
7021
7141
  }
7022
- shouldCheck(node) {
7023
- let doc;
7024
- let currNode = node;
7025
- while (currNode) {
7026
- if (currNode.$document) {
7027
- doc = currNode.$document;
7028
- break;
7029
- }
7030
- currNode = currNode.$container;
7031
- }
7032
- return doc?.parseResult.lexerErrors.length === 0 && doc?.parseResult.parserErrors.length === 0;
7033
- }
7034
7142
  checkModel(node, accept) {
7035
- this.shouldCheck(node) && new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
7143
+ new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
7036
7144
  }
7037
7145
  checkDataSource(node, accept) {
7038
- this.shouldCheck(node) && new DataSourceValidator().validate(node, accept);
7146
+ new DataSourceValidator().validate(node, accept);
7039
7147
  }
7040
7148
  checkDataModel(node, accept) {
7041
- this.shouldCheck(node) && new DataModelValidator().validate(node, accept);
7149
+ new DataModelValidator().validate(node, accept);
7042
7150
  }
7043
7151
  checkTypeDef(node, accept) {
7044
- this.shouldCheck(node) && new TypeDefValidator().validate(node, accept);
7152
+ new TypeDefValidator().validate(node, accept);
7045
7153
  }
7046
7154
  checkEnum(node, accept) {
7047
- this.shouldCheck(node) && new EnumValidator().validate(node, accept);
7155
+ new EnumValidator().validate(node, accept);
7048
7156
  }
7049
7157
  checkAttribute(node, accept) {
7050
- this.shouldCheck(node) && new AttributeValidator().validate(node, accept);
7158
+ new AttributeValidator().validate(node, accept);
7051
7159
  }
7052
7160
  checkExpression(node, accept) {
7053
- this.shouldCheck(node) && new ExpressionValidator().validate(node, accept);
7161
+ new ExpressionValidator().validate(node, accept);
7054
7162
  }
7055
7163
  checkFunctionInvocation(node, accept) {
7056
- this.shouldCheck(node) && new FunctionInvocationValidator().validate(node, accept);
7164
+ new FunctionInvocationValidator().validate(node, accept);
7057
7165
  }
7058
7166
  checkFunctionDecl(node, accept) {
7059
- this.shouldCheck(node) && new FunctionDeclValidator().validate(node, accept);
7167
+ new FunctionDeclValidator().validate(node, accept);
7168
+ }
7169
+ };
7170
+
7171
+ // src/zmodel-document-builder.ts
7172
+ import { DefaultDocumentBuilder } from "langium";
7173
+ var ZModelDocumentBuilder = class extends DefaultDocumentBuilder {
7174
+ static {
7175
+ __name(this, "ZModelDocumentBuilder");
7176
+ }
7177
+ constructor(services) {
7178
+ super(services);
7179
+ let validationOptions = this.updateBuildOptions.validation;
7180
+ const stopFlags = {
7181
+ stopAfterLinkingErrors: true,
7182
+ stopAfterLexingErrors: true,
7183
+ stopAfterParsingErrors: true
7184
+ };
7185
+ if (validationOptions === true) {
7186
+ validationOptions = stopFlags;
7187
+ } else if (typeof validationOptions === "object") {
7188
+ validationOptions = {
7189
+ ...validationOptions,
7190
+ ...stopFlags
7191
+ };
7192
+ }
7193
+ this.updateBuildOptions = {
7194
+ ...this.updateBuildOptions,
7195
+ validation: validationOptions
7196
+ };
7060
7197
  }
7061
7198
  };
7062
7199
 
7063
7200
  // src/zmodel-linker.ts
7064
- import { AstUtils as AstUtils6, Cancellation, DefaultLinker, DocumentState, interruptAndCheck, isReference } from "langium";
7201
+ import { AstUtils as AstUtils6, Cancellation, DefaultLinker, DocumentState, interruptAndCheck } from "langium";
7065
7202
  import { match as match2 } from "ts-pattern";
7066
7203
  var ZModelLinker = class extends DefaultLinker {
7067
7204
  static {
@@ -7083,21 +7220,19 @@ var ZModelLinker = class extends DefaultLinker {
7083
7220
  }
7084
7221
  document.state = DocumentState.Linked;
7085
7222
  }
7086
- linkReference(container, property, document, extraScopes) {
7087
- if (this.resolveFromScopeProviders(container, property, document, extraScopes)) {
7223
+ linkReference(refInfo, document, extraScopes) {
7224
+ const defaultRef = refInfo.reference;
7225
+ if (defaultRef._ref) {
7226
+ return;
7227
+ }
7228
+ if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
7088
7229
  return;
7089
7230
  }
7090
- const reference = container[property];
7091
- this.doLink({
7092
- reference,
7093
- container,
7094
- property
7095
- }, document);
7231
+ this.doLink(refInfo, document);
7096
7232
  }
7097
7233
  //#endregion
7098
7234
  //#region Expression type resolving
7099
- resolveFromScopeProviders(node, property, document, providers) {
7100
- const reference = node[property];
7235
+ resolveFromScopeProviders(reference, document, providers) {
7101
7236
  for (const provider of providers) {
7102
7237
  const target = provider(reference.$refText);
7103
7238
  if (target) {
@@ -7149,8 +7284,8 @@ var ZModelLinker = class extends DefaultLinker {
7149
7284
  case DataModel:
7150
7285
  this.resolveDataModel(node, document, extraScopes);
7151
7286
  break;
7152
- case DataModelField:
7153
- this.resolveDataModelField(node, document, extraScopes);
7287
+ case DataField:
7288
+ this.resolveDataField(node, document, extraScopes);
7154
7289
  break;
7155
7290
  default:
7156
7291
  this.resolveDefault(node, document, extraScopes);
@@ -7226,7 +7361,11 @@ var ZModelLinker = class extends DefaultLinker {
7226
7361
  }
7227
7362
  }
7228
7363
  resolveInvocation(node, document, extraScopes) {
7229
- this.linkReference(node, "function", document, extraScopes);
7364
+ this.linkReference({
7365
+ reference: node.function,
7366
+ container: node,
7367
+ property: "function"
7368
+ }, document, extraScopes);
7230
7369
  node.args.forEach((arg) => this.resolve(arg, document, extraScopes));
7231
7370
  if (node.function.ref) {
7232
7371
  const funcDecl = node.function.ref;
@@ -7239,7 +7378,7 @@ var ZModelLinker = class extends DefaultLinker {
7239
7378
  nullable: true
7240
7379
  };
7241
7380
  }
7242
- } else if (isFutureExpr(node)) {
7381
+ } else if (isBeforeInvocation(node)) {
7243
7382
  node.$resolvedType = {
7244
7383
  decl: getContainingDataModel(node)
7245
7384
  };
@@ -7296,14 +7435,14 @@ var ZModelLinker = class extends DefaultLinker {
7296
7435
  resolveAttributeArg(node, document, extraScopes) {
7297
7436
  const attrParam = this.findAttrParamForArg(node);
7298
7437
  const attrAppliedOn = node.$container.$container;
7299
- if (attrParam?.type.type === "TransitiveFieldReference" && isDataModelField(attrAppliedOn)) {
7438
+ if (attrParam?.type.type === "TransitiveFieldReference" && isDataField(attrAppliedOn)) {
7300
7439
  const transitiveDataModel = attrAppliedOn.type.reference?.ref;
7301
7440
  if (transitiveDataModel) {
7302
- const scopeProvider = /* @__PURE__ */ __name((name) => getModelFieldsWithBases(transitiveDataModel).find((f) => f.name === name), "scopeProvider");
7441
+ const scopeProvider = /* @__PURE__ */ __name((name) => getAllFields(transitiveDataModel).find((f) => f.name === name), "scopeProvider");
7303
7442
  if (isArrayExpr(node.value)) {
7304
7443
  node.value.items.forEach((item) => {
7305
7444
  if (isReferenceExpr(item)) {
7306
- const resolved2 = this.resolveFromScopeProviders(item, "target", document, [
7445
+ const resolved2 = this.resolveFromScopeProviders(item.target, document, [
7307
7446
  scopeProvider
7308
7447
  ]);
7309
7448
  if (resolved2) {
@@ -7317,7 +7456,7 @@ var ZModelLinker = class extends DefaultLinker {
7317
7456
  this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true);
7318
7457
  }
7319
7458
  } else if (isReferenceExpr(node.value)) {
7320
- const resolved2 = this.resolveFromScopeProviders(node.value, "target", document, [
7459
+ const resolved2 = this.resolveFromScopeProviders(node.value.target, document, [
7321
7460
  scopeProvider
7322
7461
  ]);
7323
7462
  if (resolved2) {
@@ -7355,7 +7494,7 @@ var ZModelLinker = class extends DefaultLinker {
7355
7494
  resolveDataModel(node, document, extraScopes) {
7356
7495
  return this.resolveDefault(node, document, extraScopes);
7357
7496
  }
7358
- resolveDataModelField(node, document, extraScopes) {
7497
+ resolveDataField(node, document, extraScopes) {
7359
7498
  this.resolve(node.type, document, extraScopes);
7360
7499
  let scopes = extraScopes;
7361
7500
  if (node.type.reference?.ref && isEnum(node.type.reference.ref)) {
@@ -7369,13 +7508,9 @@ var ZModelLinker = class extends DefaultLinker {
7369
7508
  this.resolveDefault(node, document, scopes);
7370
7509
  }
7371
7510
  resolveDefault(node, document, extraScopes) {
7372
- for (const [property, value] of Object.entries(node)) {
7373
- if (!property.startsWith("$")) {
7374
- if (isReference(value)) {
7375
- this.linkReference(node, property, document, extraScopes);
7376
- }
7377
- }
7378
- }
7511
+ AstUtils6.streamReferences(node).forEach((ref) => {
7512
+ this.linkReference(ref, document, extraScopes);
7513
+ });
7379
7514
  for (const child of AstUtils6.streamContents(node)) {
7380
7515
  this.resolve(child, document, extraScopes);
7381
7516
  }
@@ -7384,7 +7519,7 @@ var ZModelLinker = class extends DefaultLinker {
7384
7519
  //#region Utils
7385
7520
  resolveToDeclaredType(node, type) {
7386
7521
  let nullable = false;
7387
- if (isDataModelFieldType(type) || isTypeDefField(type)) {
7522
+ if (isDataFieldType(type)) {
7388
7523
  nullable = type.optional;
7389
7524
  if (type.unsupported) {
7390
7525
  node.$resolvedType = {
@@ -7445,6 +7580,14 @@ var ZModelScopeComputation = class extends DefaultScopeComputation {
7445
7580
  }
7446
7581
  processNode(node, document, scopes) {
7447
7582
  super.processNode(node, document, scopes);
7583
+ if (isDataModel(node) || isTypeDef(node)) {
7584
+ const bases = getRecursiveBases(node);
7585
+ for (const base of bases) {
7586
+ for (const field of base.fields) {
7587
+ scopes.add(node, this.descriptions.createDescription(field, this.nameProvider.getName(field)));
7588
+ }
7589
+ }
7590
+ }
7448
7591
  }
7449
7592
  };
7450
7593
  var ZModelScopeProvider = class extends DefaultScopeProvider {
@@ -7492,16 +7635,13 @@ var ZModelScopeProvider = class extends DefaultScopeProvider {
7492
7635
  );
7493
7636
  return match3(node.operand).when(isReferenceExpr, (operand) => {
7494
7637
  const ref = operand.target.ref;
7495
- if (isDataModelField(ref) || isTypeDefField(ref)) {
7638
+ if (isDataField(ref)) {
7496
7639
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7497
7640
  }
7498
7641
  return EMPTY_SCOPE;
7499
7642
  }).when(isMemberAccessExpr, (operand) => {
7500
7643
  const ref = operand.member.ref;
7501
- if (isDataModelField(ref) && !ref.type.array) {
7502
- return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7503
- }
7504
- if (isTypeDefField(ref) && !ref.type.array) {
7644
+ if (isDataField(ref) && !ref.type.array) {
7505
7645
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7506
7646
  }
7507
7647
  return EMPTY_SCOPE;
@@ -7511,7 +7651,7 @@ var ZModelScopeProvider = class extends DefaultScopeProvider {
7511
7651
  if (isAuthInvocation(operand)) {
7512
7652
  return this.createScopeForAuth(node, globalScope);
7513
7653
  }
7514
- if (isFutureInvocation(operand)) {
7654
+ if (isBeforeInvocation(operand)) {
7515
7655
  return this.createScopeForContainingModel(node, globalScope);
7516
7656
  }
7517
7657
  return EMPTY_SCOPE;
@@ -7524,13 +7664,13 @@ var ZModelScopeProvider = class extends DefaultScopeProvider {
7524
7664
  const allowTypeDefScope = false;
7525
7665
  return match3(collection).when(isReferenceExpr, (expr) => {
7526
7666
  const ref = expr.target.ref;
7527
- if (isDataModelField(ref) || isTypeDefField(ref)) {
7667
+ if (isDataField(ref)) {
7528
7668
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7529
7669
  }
7530
7670
  return EMPTY_SCOPE;
7531
7671
  }).when(isMemberAccessExpr, (expr) => {
7532
7672
  const ref = expr.member.ref;
7533
- if (isDataModelField(ref) || isTypeDefField(ref)) {
7673
+ if (isDataField(ref)) {
7534
7674
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7535
7675
  }
7536
7676
  return EMPTY_SCOPE;
@@ -7555,7 +7695,7 @@ var ZModelScopeProvider = class extends DefaultScopeProvider {
7555
7695
  }
7556
7696
  createScopeForContainer(node, globalScope, includeTypeDefScope = false) {
7557
7697
  if (isDataModel(node)) {
7558
- return this.createScopeForNodes(getModelFieldsWithBases(node), globalScope);
7698
+ return this.createScopeForNodes(getAllFields(node), globalScope);
7559
7699
  } else if (includeTypeDefScope && isTypeDef(node)) {
7560
7700
  return this.createScopeForNodes(node.fields, globalScope);
7561
7701
  } else {
@@ -7588,7 +7728,7 @@ __name(getCollectionPredicateContext, "getCollectionPredicateContext");
7588
7728
  import { DefaultWorkspaceManager, URI as URI2 } from "langium";
7589
7729
  import fs2 from "fs";
7590
7730
  import path2 from "path";
7591
- import { fileURLToPath } from "url";
7731
+ import { fileURLToPath as fileURLToPath2 } from "url";
7592
7732
  var ZModelWorkspaceManager = class extends DefaultWorkspaceManager {
7593
7733
  static {
7594
7734
  __name(this, "ZModelWorkspaceManager");
@@ -7624,7 +7764,7 @@ var ZModelWorkspaceManager = class extends DefaultWorkspaceManager {
7624
7764
  if (installedStdlibPath) {
7625
7765
  stdLibPath = installedStdlibPath;
7626
7766
  } else {
7627
- const _dirname = typeof __dirname !== "undefined" ? __dirname : path2.dirname(fileURLToPath(import.meta.url));
7767
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : path2.dirname(fileURLToPath2(import.meta.url));
7628
7768
  stdLibPath = path2.join(_dirname, "../res", STD_LIB_MODULE_NAME);
7629
7769
  console.log(`Using bundled stdlib in extension:`, stdLibPath);
7630
7770
  }
@@ -7646,10 +7786,11 @@ var ZModelLanguageModule = {
7646
7786
  };
7647
7787
  var ZModelSharedModule = {
7648
7788
  workspace: {
7789
+ DocumentBuilder: /* @__PURE__ */ __name((services) => new ZModelDocumentBuilder(services), "DocumentBuilder"),
7649
7790
  WorkspaceManager: /* @__PURE__ */ __name((services) => new ZModelWorkspaceManager(services), "WorkspaceManager")
7650
7791
  }
7651
7792
  };
7652
- function createZModelLanguageServices(context) {
7793
+ function createZModelLanguageServices(context, logToConsole = false) {
7653
7794
  const shared = inject(createDefaultSharedModule(context), ZModelGeneratedSharedModule, ZModelSharedModule);
7654
7795
  const ZModelLanguage = inject(createDefaultModule({
7655
7796
  shared
@@ -7659,30 +7800,38 @@ function createZModelLanguageServices(context) {
7659
7800
  if (!context.connection) {
7660
7801
  shared.workspace.ConfigurationProvider.initialized({});
7661
7802
  }
7803
+ shared.workspace.DocumentBuilder.onBuildPhase(DocumentState2.Parsed, async (documents) => {
7804
+ for (const doc of documents) {
7805
+ if (doc.parseResult.lexerErrors.length > 0 || doc.parseResult.parserErrors.length > 0) {
7806
+ continue;
7807
+ }
7808
+ const schemaPath = fileURLToPath3(doc.uri.toString());
7809
+ const pluginSchemas = getPluginDocuments(doc.parseResult.value, schemaPath);
7810
+ for (const plugin of pluginSchemas) {
7811
+ const pluginDoc = await shared.workspace.LangiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(plugin)));
7812
+ shared.workspace.IndexManager.updateContent(pluginDoc);
7813
+ if (logToConsole) {
7814
+ console.log(`Loaded plugin model: ${plugin}`);
7815
+ }
7816
+ }
7817
+ }
7818
+ });
7662
7819
  return {
7663
7820
  shared,
7664
7821
  ZModelLanguage
7665
7822
  };
7666
7823
  }
7667
7824
  __name(createZModelLanguageServices, "createZModelLanguageServices");
7668
-
7669
- // src/index.ts
7670
- function createZModelServices() {
7671
- return createZModelLanguageServices(NodeFileSystem);
7825
+ function createZModelServices(logToConsole = false) {
7826
+ return createZModelLanguageServices(NodeFileSystem, logToConsole);
7672
7827
  }
7673
7828
  __name(createZModelServices, "createZModelServices");
7674
- var DocumentLoadError = class extends Error {
7675
- static {
7676
- __name(this, "DocumentLoadError");
7677
- }
7678
- constructor(message) {
7679
- super(message);
7680
- }
7681
- };
7682
- async function loadDocument(fileName, pluginModelFiles = []) {
7683
- const { ZModelLanguage: services } = createZModelServices();
7829
+
7830
+ // src/document.ts
7831
+ async function loadDocument(fileName, additionalModelFiles = []) {
7832
+ const { ZModelLanguage: services } = createZModelServices(false);
7684
7833
  const extensions = services.LanguageMetaData.fileExtensions;
7685
- if (!extensions.includes(path3.extname(fileName))) {
7834
+ if (!extensions.includes(path4.extname(fileName))) {
7686
7835
  return {
7687
7836
  success: false,
7688
7837
  errors: [
@@ -7700,17 +7849,27 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7700
7849
  warnings: []
7701
7850
  };
7702
7851
  }
7703
- const _dirname = typeof __dirname !== "undefined" ? __dirname : path3.dirname(fileURLToPath2(import.meta.url));
7704
- const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(path3.join(_dirname, "../res", STD_LIB_MODULE_NAME))));
7705
- const pluginDocs = await Promise.all(pluginModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(file)))));
7852
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : path4.dirname(fileURLToPath4(import.meta.url));
7853
+ const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI4.file(path4.resolve(path4.join(_dirname, "../res", STD_LIB_MODULE_NAME))));
7706
7854
  const langiumDocuments = services.shared.workspace.LangiumDocuments;
7707
- const document = await langiumDocuments.getOrCreateDocument(URI3.file(path3.resolve(fileName)));
7855
+ const document = await langiumDocuments.getOrCreateDocument(URI4.file(path4.resolve(fileName)));
7856
+ const importedURIs = await loadImports(document, langiumDocuments);
7857
+ const importedDocuments = [];
7858
+ for (const uri of importedURIs) {
7859
+ importedDocuments.push(await langiumDocuments.getOrCreateDocument(uri));
7860
+ }
7861
+ const additionalDocs = await Promise.all(additionalModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(URI4.file(path4.resolve(file)))));
7708
7862
  await services.shared.workspace.DocumentBuilder.build([
7709
7863
  stdLib,
7710
- ...pluginDocs,
7711
- document
7864
+ ...additionalDocs,
7865
+ document,
7866
+ ...importedDocuments
7712
7867
  ], {
7713
- validation: true
7868
+ validation: {
7869
+ stopAfterLexingErrors: true,
7870
+ stopAfterParsingErrors: true,
7871
+ stopAfterLinkingErrors: true
7872
+ }
7714
7873
  });
7715
7874
  const diagnostics = langiumDocuments.all.flatMap((doc) => (doc.diagnostics ?? []).map((diag) => ({
7716
7875
  doc,
@@ -7720,7 +7879,7 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7720
7879
  const warnings = [];
7721
7880
  if (diagnostics.length > 0) {
7722
7881
  for (const { doc, diag } of diagnostics) {
7723
- const message = `${path3.relative(process.cwd(), doc.uri.fsPath)}:${diag.range.start.line + 1}:${diag.range.start.character + 1} - ${diag.message}`;
7882
+ const message = `${path4.relative(process.cwd(), doc.uri.fsPath)}:${diag.range.start.line + 1}:${diag.range.start.character + 1} - ${diag.message}`;
7724
7883
  if (diag.severity === 1) {
7725
7884
  errors.push(message);
7726
7885
  } else {
@@ -7735,6 +7894,20 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7735
7894
  warnings
7736
7895
  };
7737
7896
  }
7897
+ const model = document.parseResult.value;
7898
+ const imported = mergeImportsDeclarations(langiumDocuments, model);
7899
+ imported.forEach((model2) => {
7900
+ langiumDocuments.deleteDocument(model2.$document.uri);
7901
+ services.shared.workspace.IndexManager.remove(model2.$document.uri);
7902
+ });
7903
+ const additionalErrors = validationAfterImportMerge(model);
7904
+ if (additionalErrors.length > 0) {
7905
+ return {
7906
+ success: false,
7907
+ errors: additionalErrors,
7908
+ warnings
7909
+ };
7910
+ }
7738
7911
  return {
7739
7912
  success: true,
7740
7913
  model: document.parseResult.value,
@@ -7742,8 +7915,69 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7742
7915
  };
7743
7916
  }
7744
7917
  __name(loadDocument, "loadDocument");
7918
+ async function loadImports(document, documents, uris = /* @__PURE__ */ new Set()) {
7919
+ const uriString = document.uri.toString();
7920
+ if (!uris.has(uriString)) {
7921
+ uris.add(uriString);
7922
+ const model = document.parseResult.value;
7923
+ for (const imp of model.imports) {
7924
+ const importedModel = resolveImport(documents, imp);
7925
+ if (importedModel) {
7926
+ const importedDoc = getDocument(importedModel);
7927
+ await loadImports(importedDoc, documents, uris);
7928
+ }
7929
+ }
7930
+ }
7931
+ return Array.from(uris).filter((x) => uriString != x).map((e) => URI4.parse(e));
7932
+ }
7933
+ __name(loadImports, "loadImports");
7934
+ function mergeImportsDeclarations(documents, model) {
7935
+ const importedModels = resolveTransitiveImports(documents, model);
7936
+ const importedDeclarations = importedModels.flatMap((m) => m.declarations);
7937
+ model.declarations.push(...importedDeclarations);
7938
+ model.imports = [];
7939
+ linkContentToContainer(model);
7940
+ return importedModels;
7941
+ }
7942
+ __name(mergeImportsDeclarations, "mergeImportsDeclarations");
7943
+ function linkContentToContainer(node) {
7944
+ for (const [name, value] of Object.entries(node)) {
7945
+ if (!name.startsWith("$")) {
7946
+ if (Array.isArray(value)) {
7947
+ value.forEach((item, index) => {
7948
+ if (isAstNode(item)) {
7949
+ item.$container = node;
7950
+ item.$containerProperty = name;
7951
+ item.$containerIndex = index;
7952
+ }
7953
+ });
7954
+ } else if (isAstNode(value)) {
7955
+ value.$container = node;
7956
+ value.$containerProperty = name;
7957
+ }
7958
+ }
7959
+ }
7960
+ }
7961
+ __name(linkContentToContainer, "linkContentToContainer");
7962
+ function validationAfterImportMerge(model) {
7963
+ const errors = [];
7964
+ const dataSources = model.declarations.filter((d) => isDataSource(d));
7965
+ if (dataSources.length === 0) {
7966
+ errors.push("Validation error: schema must have a datasource declaration");
7967
+ } else {
7968
+ if (dataSources.length > 1) {
7969
+ errors.push("Validation error: multiple datasource declarations are not allowed");
7970
+ }
7971
+ }
7972
+ const decls = getDataModelAndTypeDefs(model, true);
7973
+ const authDecls = decls.filter((d) => hasAttribute(d, "@@auth"));
7974
+ if (authDecls.length > 1) {
7975
+ errors.push("Validation error: Multiple `@@auth` declarations are not allowed");
7976
+ }
7977
+ return errors;
7978
+ }
7979
+ __name(validationAfterImportMerge, "validationAfterImportMerge");
7745
7980
  export {
7746
- DocumentLoadError,
7747
7981
  ZModelLanguageMetaData,
7748
7982
  ZModelLanguageModule,
7749
7983
  ZModelSharedModule,