@zenstackhq/language 3.0.0-beta.1 → 3.0.0-beta.11

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.cjs CHANGED
@@ -31,7 +31,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var src_exports = {};
33
33
  __export(src_exports, {
34
- DocumentLoadError: () => DocumentLoadError,
35
34
  ZModelLanguageMetaData: () => ZModelLanguageMetaData,
36
35
  ZModelLanguageModule: () => ZModelLanguageModule,
37
36
  ZModelSharedModule: () => ZModelSharedModule,
@@ -40,11 +39,12 @@ __export(src_exports, {
40
39
  loadDocument: () => loadDocument
41
40
  });
42
41
  module.exports = __toCommonJS(src_exports);
43
- var import_langium11 = require("langium");
44
- var import_node = require("langium/node");
42
+
43
+ // src/document.ts
44
+ var import_langium12 = require("langium");
45
45
  var import_node_fs3 = __toESM(require("fs"), 1);
46
- var import_node_path2 = __toESM(require("path"), 1);
47
- var import_node_url2 = require("url");
46
+ var import_node_path4 = __toESM(require("path"), 1);
47
+ var import_node_url4 = require("url");
48
48
 
49
49
  // src/generated/ast.ts
50
50
  var langium = __toESM(require("langium"), 1);
@@ -1074,8 +1074,11 @@ var ExpressionContext = /* @__PURE__ */ function(ExpressionContext2) {
1074
1074
  }({});
1075
1075
 
1076
1076
  // src/module.ts
1077
- var import_langium10 = require("langium");
1077
+ var import_langium11 = require("langium");
1078
1078
  var import_lsp = require("langium/lsp");
1079
+ var import_node = require("langium/node");
1080
+ var import_node_path3 = __toESM(require("path"), 1);
1081
+ var import_node_url3 = require("url");
1079
1082
 
1080
1083
  // src/generated/grammar.ts
1081
1084
  var import_langium = require("langium");
@@ -5136,15 +5139,13 @@ var ZModelGeneratedModule = {
5136
5139
  parser: {}
5137
5140
  };
5138
5141
 
5139
- // src/validators/attribute-application-validator.ts
5140
- var import_langium3 = require("langium");
5141
- var import_pluralize = __toESM(require("pluralize"), 1);
5142
-
5143
5142
  // src/utils.ts
5144
- var import_common_helpers = require("@zenstackhq/common-helpers");
5145
5143
  var import_langium2 = require("langium");
5146
5144
  var import_node_fs = __toESM(require("fs"), 1);
5147
- var import_path = __toESM(require("path"), 1);
5145
+ var import_node_module = require("module");
5146
+ var import_node_path = __toESM(require("path"), 1);
5147
+ var import_node_url = require("url");
5148
+ var import_meta = {};
5148
5149
  function hasAttribute(decl, name) {
5149
5150
  return !!getAttribute(decl, name);
5150
5151
  }
@@ -5224,10 +5225,6 @@ function isRelationshipField(field) {
5224
5225
  return isDataModel(field.type.reference?.ref);
5225
5226
  }
5226
5227
  __name(isRelationshipField, "isRelationshipField");
5227
- function isFutureExpr(node) {
5228
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5229
- }
5230
- __name(isFutureExpr, "isFutureExpr");
5231
5228
  function isDelegateModel(node) {
5232
5229
  return isDataModel(node) && hasAttribute(node, "@@delegate");
5233
5230
  }
@@ -5245,8 +5242,14 @@ function getRecursiveBases(decl, includeDelegate = true, seen = /* @__PURE__ */
5245
5242
  return result;
5246
5243
  }
5247
5244
  seen.add(decl);
5248
- decl.mixins.forEach((mixin) => {
5249
- const baseDecl = mixin.ref;
5245
+ const bases = [
5246
+ ...decl.mixins,
5247
+ ...isDataModel(decl) && decl.baseModel ? [
5248
+ decl.baseModel
5249
+ ] : []
5250
+ ];
5251
+ bases.forEach((base) => {
5252
+ const baseDecl = decl.$container.declarations.find((d) => isTypeDef(d) || isDataModel(d) && d.name === base.$refText);
5250
5253
  if (baseDecl) {
5251
5254
  if (!includeDelegate && isDelegateModel(baseDecl)) {
5252
5255
  return;
@@ -5386,7 +5389,7 @@ function getFunctionExpressionContext(funcDecl) {
5386
5389
  }
5387
5390
  __name(getFunctionExpressionContext, "getFunctionExpressionContext");
5388
5391
  function isCheckInvocation(node) {
5389
- return isInvocationExpr(node) && node.function.ref?.name === "check" && isFromStdlib(node.function.ref);
5392
+ return isInvocationExpr(node) && node.function.ref?.name === "check";
5390
5393
  }
5391
5394
  __name(isCheckInvocation, "isCheckInvocation");
5392
5395
  function resolveTransitiveImports(documents, model) {
@@ -5436,9 +5439,9 @@ function resolveImportUri(imp) {
5436
5439
  return void 0;
5437
5440
  }
5438
5441
  const doc = import_langium2.AstUtils.getDocument(imp);
5439
- const dir = import_path.default.dirname(doc.uri.fsPath);
5442
+ const dir = import_node_path.default.dirname(doc.uri.fsPath);
5440
5443
  const importPath = imp.path.endsWith(".zmodel") ? imp.path : `${imp.path}.zmodel`;
5441
- return import_langium2.URI.file(import_path.default.resolve(dir, importPath));
5444
+ return import_langium2.URI.file(import_node_path.default.resolve(dir, importPath));
5442
5445
  }
5443
5446
  __name(resolveImportUri, "resolveImportUri");
5444
5447
  function getDataModelAndTypeDefs(model, includeIgnored = false) {
@@ -5456,17 +5459,17 @@ function getAllDeclarationsIncludingImports(documents, model) {
5456
5459
  }
5457
5460
  __name(getAllDeclarationsIncludingImports, "getAllDeclarationsIncludingImports");
5458
5461
  function getAuthDecl(decls) {
5459
- let authModel = decls.find((m) => hasAttribute(m, "@@auth"));
5462
+ let authModel = decls.find((d) => hasAttribute(d, "@@auth"));
5460
5463
  if (!authModel) {
5461
- authModel = decls.find((m) => m.name === "User");
5464
+ authModel = decls.find((d) => d.name === "User");
5462
5465
  }
5463
5466
  return authModel;
5464
5467
  }
5465
5468
  __name(getAuthDecl, "getAuthDecl");
5466
- function isFutureInvocation(node) {
5467
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5469
+ function isBeforeInvocation(node) {
5470
+ return isInvocationExpr(node) && node.function.ref?.name === "before";
5468
5471
  }
5469
- __name(isFutureInvocation, "isFutureInvocation");
5472
+ __name(isBeforeInvocation, "isBeforeInvocation");
5470
5473
  function isCollectionPredicate(node) {
5471
5474
  return isBinaryExpr(node) && [
5472
5475
  "?",
@@ -5521,12 +5524,14 @@ function getAllFields(decl, includeIgnored = false, seen = /* @__PURE__ */ new S
5521
5524
  seen.add(decl);
5522
5525
  const fields = [];
5523
5526
  for (const mixin of decl.mixins) {
5524
- (0, import_common_helpers.invariant)(mixin.ref, `Mixin ${mixin.$refText} is not resolved`);
5525
- fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5527
+ if (mixin.ref) {
5528
+ fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5529
+ }
5526
5530
  }
5527
5531
  if (isDataModel(decl) && decl.baseModel) {
5528
- (0, import_common_helpers.invariant)(decl.baseModel.ref, `Base model ${decl.baseModel.$refText} is not resolved`);
5529
- fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
5532
+ if (decl.baseModel.ref) {
5533
+ fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
5534
+ }
5530
5535
  }
5531
5536
  fields.push(...decl.fields.filter((f) => includeIgnored || !hasAttribute(f, "@ignore")));
5532
5537
  return fields;
@@ -5539,12 +5544,14 @@ function getAllAttributes(decl, seen = /* @__PURE__ */ new Set()) {
5539
5544
  seen.add(decl);
5540
5545
  const attributes = [];
5541
5546
  for (const mixin of decl.mixins) {
5542
- (0, import_common_helpers.invariant)(mixin.ref, `Mixin ${mixin.$refText} is not resolved`);
5543
- attributes.push(...getAllAttributes(mixin.ref, seen));
5547
+ if (mixin.ref) {
5548
+ attributes.push(...getAllAttributes(mixin.ref, seen));
5549
+ }
5544
5550
  }
5545
5551
  if (isDataModel(decl) && decl.baseModel) {
5546
- (0, import_common_helpers.invariant)(decl.baseModel.ref, `Base model ${decl.baseModel.$refText} is not resolved`);
5547
- attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
5552
+ if (decl.baseModel.ref) {
5553
+ attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
5554
+ }
5548
5555
  }
5549
5556
  attributes.push(...decl.attributes);
5550
5557
  return attributes;
@@ -5559,6 +5566,71 @@ function getDocument(node) {
5559
5566
  return result;
5560
5567
  }
5561
5568
  __name(getDocument, "getDocument");
5569
+ function getPluginDocuments(model, schemaPath) {
5570
+ const result = [];
5571
+ for (const decl of model.declarations.filter(isPlugin)) {
5572
+ const providerField = decl.fields.find((f) => f.name === "provider");
5573
+ if (!providerField) {
5574
+ continue;
5575
+ }
5576
+ const provider = getLiteral(providerField.value);
5577
+ if (!provider) {
5578
+ continue;
5579
+ }
5580
+ let pluginModelFile;
5581
+ let providerPath = import_node_path.default.resolve(import_node_path.default.dirname(schemaPath), provider);
5582
+ if (import_node_fs.default.existsSync(providerPath)) {
5583
+ if (import_node_fs.default.statSync(providerPath).isDirectory()) {
5584
+ providerPath = import_node_path.default.join(providerPath, "index.js");
5585
+ }
5586
+ pluginModelFile = import_node_path.default.resolve(import_node_path.default.dirname(providerPath), PLUGIN_MODULE_NAME);
5587
+ if (!import_node_fs.default.existsSync(pluginModelFile)) {
5588
+ pluginModelFile = findUp([
5589
+ PLUGIN_MODULE_NAME
5590
+ ], import_node_path.default.dirname(providerPath));
5591
+ }
5592
+ }
5593
+ if (!pluginModelFile) {
5594
+ if (typeof import_meta.resolve === "function") {
5595
+ try {
5596
+ const resolvedUrl = import_meta.resolve(`${provider}/${PLUGIN_MODULE_NAME}`);
5597
+ pluginModelFile = (0, import_node_url.fileURLToPath)(resolvedUrl);
5598
+ } catch {
5599
+ }
5600
+ }
5601
+ }
5602
+ if (!pluginModelFile) {
5603
+ try {
5604
+ const require2 = (0, import_node_module.createRequire)((0, import_node_url.pathToFileURL)(schemaPath));
5605
+ pluginModelFile = require2.resolve(`${provider}/${PLUGIN_MODULE_NAME}`);
5606
+ } catch {
5607
+ }
5608
+ }
5609
+ if (pluginModelFile && import_node_fs.default.existsSync(pluginModelFile)) {
5610
+ result.push(pluginModelFile);
5611
+ }
5612
+ }
5613
+ return result;
5614
+ }
5615
+ __name(getPluginDocuments, "getPluginDocuments");
5616
+ function findUp(names, cwd = process.cwd(), multiple = false, result = []) {
5617
+ if (!names.some((name) => !!name)) {
5618
+ return void 0;
5619
+ }
5620
+ const target = names.find((name) => import_node_fs.default.existsSync(import_node_path.default.join(cwd, name)));
5621
+ if (multiple === false && target) {
5622
+ return import_node_path.default.join(cwd, target);
5623
+ }
5624
+ if (target) {
5625
+ result.push(import_node_path.default.join(cwd, target));
5626
+ }
5627
+ const up = import_node_path.default.resolve(cwd, "..");
5628
+ if (up === cwd) {
5629
+ return multiple && result.length > 0 ? result : void 0;
5630
+ }
5631
+ return findUp(names, up, multiple, result);
5632
+ }
5633
+ __name(findUp, "findUp");
5562
5634
  function findRootNode(node) {
5563
5635
  while (node.$container) {
5564
5636
  node = node.$container;
@@ -5568,6 +5640,8 @@ function findRootNode(node) {
5568
5640
  __name(findRootNode, "findRootNode");
5569
5641
 
5570
5642
  // src/validators/attribute-application-validator.ts
5643
+ var import_langium3 = require("langium");
5644
+ var import_pluralize = __toESM(require("pluralize"), 1);
5571
5645
  function _ts_decorate(decorators, target, key, desc) {
5572
5646
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5573
5647
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -5681,6 +5755,7 @@ var AttributeApplicationValidator = class {
5681
5755
  });
5682
5756
  }
5683
5757
  }
5758
+ // TODO: design a way to let plugin register validation
5684
5759
  _checkModelLevelPolicy(attr, accept) {
5685
5760
  const kind = getStringLiteral(attr.args[0]?.value);
5686
5761
  if (!kind) {
@@ -5693,11 +5768,61 @@ var AttributeApplicationValidator = class {
5693
5768
  "create",
5694
5769
  "read",
5695
5770
  "update",
5771
+ "post-update",
5696
5772
  "delete",
5697
5773
  "all"
5698
5774
  ], attr, accept);
5699
- this.rejectEncryptedFields(attr, accept);
5775
+ if ((kind === "create" || kind === "all") && attr.args[1]?.value) {
5776
+ this.rejectNonOwnedRelationInExpression(attr.args[1].value, accept);
5777
+ }
5778
+ if (kind !== "post-update" && attr.args[1]?.value) {
5779
+ const beforeCall = import_langium3.AstUtils.streamAst(attr.args[1]?.value).find(isBeforeInvocation);
5780
+ if (beforeCall) {
5781
+ accept("error", `"before()" is only allowed in "post-update" policy rules`, {
5782
+ node: beforeCall
5783
+ });
5784
+ }
5785
+ }
5700
5786
  }
5787
+ rejectNonOwnedRelationInExpression(expr, accept) {
5788
+ const contextModel = import_langium3.AstUtils.getContainerOfType(expr, isDataModel);
5789
+ if (!contextModel) {
5790
+ return;
5791
+ }
5792
+ if (import_langium3.AstUtils.streamAst(expr).some((node) => {
5793
+ if (!isDataFieldReference(node)) {
5794
+ return false;
5795
+ }
5796
+ if (node.target.ref?.$container !== contextModel) {
5797
+ return false;
5798
+ }
5799
+ const field = node.target.ref;
5800
+ if (!isRelationshipField(field)) {
5801
+ return false;
5802
+ }
5803
+ if (isAuthOrAuthMemberAccess(node)) {
5804
+ return false;
5805
+ }
5806
+ const startNode = isCollectionPredicate(node.$container) && node.$container.left === node ? node.$container : node;
5807
+ const collectionPredicate = import_langium3.AstUtils.getContainerOfType(startNode.$container, isCollectionPredicate);
5808
+ if (collectionPredicate && isAuthOrAuthMemberAccess(collectionPredicate.left)) {
5809
+ return false;
5810
+ }
5811
+ const relationAttr = field.attributes.find((attr) => attr.decl.ref?.name === "@relation");
5812
+ if (!relationAttr) {
5813
+ return true;
5814
+ }
5815
+ if (!relationAttr.args.some((arg) => arg.name === "fields")) {
5816
+ return true;
5817
+ }
5818
+ return false;
5819
+ })) {
5820
+ accept("error", `non-owned relation fields are not allowed in "create" rules`, {
5821
+ node: expr
5822
+ });
5823
+ }
5824
+ }
5825
+ // TODO: design a way to let plugin register validation
5701
5826
  _checkFieldLevelPolicy(attr, accept) {
5702
5827
  const kind = getStringLiteral(attr.args[0]?.value);
5703
5828
  if (!kind) {
@@ -5712,8 +5837,8 @@ var AttributeApplicationValidator = class {
5712
5837
  "all"
5713
5838
  ], attr, accept);
5714
5839
  const expr = attr.args[1]?.value;
5715
- if (expr && import_langium3.AstUtils.streamAst(expr).some((node) => isFutureExpr(node))) {
5716
- accept("error", `"future()" is not allowed in field-level policy rules`, {
5840
+ if (expr && import_langium3.AstUtils.streamAst(expr).some((node) => isBeforeInvocation(node))) {
5841
+ accept("error", `"before()" is not allowed in field-level policy rules`, {
5717
5842
  node: expr
5718
5843
  });
5719
5844
  }
@@ -5725,7 +5850,6 @@ var AttributeApplicationValidator = class {
5725
5850
  });
5726
5851
  }
5727
5852
  }
5728
- this.rejectEncryptedFields(attr, accept);
5729
5853
  }
5730
5854
  _checkValidate(attr, accept) {
5731
5855
  const condition = attr.args[0]?.value;
@@ -5735,8 +5859,9 @@ var AttributeApplicationValidator = class {
5735
5859
  });
5736
5860
  }
5737
5861
  }
5738
- _checkUnique(attr, accept) {
5862
+ _checkConstraint(attr, accept) {
5739
5863
  const fields = attr.args[0]?.value;
5864
+ const attrName = attr.decl.ref?.name;
5740
5865
  if (!fields) {
5741
5866
  accept("error", `expects an array of field references`, {
5742
5867
  node: attr.args[0]
@@ -5745,7 +5870,7 @@ var AttributeApplicationValidator = class {
5745
5870
  }
5746
5871
  if (isArrayExpr(fields)) {
5747
5872
  if (fields.items.length === 0) {
5748
- accept("error", `\`@@unique\` expects at least one field reference`, {
5873
+ accept("error", `\`${attrName}\` expects at least one field reference`, {
5749
5874
  node: fields
5750
5875
  });
5751
5876
  return;
@@ -5764,7 +5889,7 @@ var AttributeApplicationValidator = class {
5764
5889
  return;
5765
5890
  }
5766
5891
  if (item.target.ref.$container !== attr.$container && isDelegateModel(item.target.ref.$container)) {
5767
- accept("error", `Cannot use fields inherited from a polymorphic base model in \`@@unique\``, {
5892
+ accept("error", `Cannot use fields inherited from a polymorphic base model in \`${attrName}\``, {
5768
5893
  node: item
5769
5894
  });
5770
5895
  }
@@ -5775,15 +5900,6 @@ var AttributeApplicationValidator = class {
5775
5900
  });
5776
5901
  }
5777
5902
  }
5778
- rejectEncryptedFields(attr, accept) {
5779
- import_langium3.AstUtils.streamAllContents(attr).forEach((node) => {
5780
- if (isDataFieldReference(node) && hasAttribute(node.target.ref, "@encrypted")) {
5781
- accept("error", `Encrypted fields cannot be used in policy rules`, {
5782
- node
5783
- });
5784
- }
5785
- });
5786
- }
5787
5903
  validatePolicyKinds(kind, candidates, attr, accept) {
5788
5904
  const items = kind.split(",").map((x) => x.trim());
5789
5905
  items.forEach((item) => {
@@ -5826,15 +5942,16 @@ _ts_decorate([
5826
5942
  _ts_metadata("design:returntype", void 0)
5827
5943
  ], AttributeApplicationValidator.prototype, "_checkValidate", null);
5828
5944
  _ts_decorate([
5829
- check("@@unique"),
5830
5945
  check("@@id"),
5946
+ check("@@index"),
5947
+ check("@@unique"),
5831
5948
  _ts_metadata("design:type", Function),
5832
5949
  _ts_metadata("design:paramtypes", [
5833
5950
  typeof AttributeApplication === "undefined" ? Object : AttributeApplication,
5834
5951
  typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
5835
5952
  ]),
5836
5953
  _ts_metadata("design:returntype", void 0)
5837
- ], AttributeApplicationValidator.prototype, "_checkUnique", null);
5954
+ ], AttributeApplicationValidator.prototype, "_checkConstraint", null);
5838
5955
  function assignableToAttributeParam(arg, param, attr) {
5839
5956
  const argResolvedType = arg.$resolvedType;
5840
5957
  if (!argResolvedType) {
@@ -5844,6 +5961,10 @@ function assignableToAttributeParam(arg, param, attr) {
5844
5961
  let dstIsArray = param.type.array;
5845
5962
  if (dstType === "ContextType") {
5846
5963
  if (isDataField(attr.$container)) {
5964
+ const dstIsTypedJson = hasAttribute(attr.$container, "@json");
5965
+ if (dstIsTypedJson && attr.decl.ref?.name === "@default") {
5966
+ return argResolvedType.decl === "String";
5967
+ }
5847
5968
  dstIsArray = attr.$container.type.array;
5848
5969
  }
5849
5970
  }
@@ -5935,6 +6056,9 @@ function isValidAttributeTarget(attrDecl, targetDecl) {
5935
6056
  case "TypeDefField":
5936
6057
  allowed = allowed || isTypeDef(targetDecl.type.reference?.ref);
5937
6058
  break;
6059
+ case "ListField":
6060
+ allowed = allowed || !isDataModel(targetDecl.type.reference?.ref) && targetDecl.type.array;
6061
+ break;
5938
6062
  default:
5939
6063
  break;
5940
6064
  }
@@ -5961,7 +6085,7 @@ var AttributeValidator = class {
5961
6085
  };
5962
6086
 
5963
6087
  // src/validators/datamodel-validator.ts
5964
- var import_common_helpers2 = require("@zenstackhq/common-helpers");
6088
+ var import_common_helpers = require("@zenstackhq/common-helpers");
5965
6089
  var import_langium4 = require("langium");
5966
6090
 
5967
6091
  // src/validators/common.ts
@@ -6332,7 +6456,7 @@ var DataModelValidator = class {
6332
6456
  if (!model.baseModel) {
6333
6457
  return;
6334
6458
  }
6335
- (0, import_common_helpers2.invariant)(model.baseModel.ref, "baseModel must be resolved");
6459
+ (0, import_common_helpers.invariant)(model.baseModel.ref, "baseModel must be resolved");
6336
6460
  if (!isDelegateModel(model.baseModel.ref)) {
6337
6461
  accept("error", `Model ${model.baseModel.$refText} cannot be extended because it's not a delegate model`, {
6338
6462
  node: model,
@@ -6354,7 +6478,7 @@ var DataModelValidator = class {
6354
6478
  }
6355
6479
  seen.push(current);
6356
6480
  if (current.baseModel) {
6357
- (0, import_common_helpers2.invariant)(current.baseModel.ref, "baseModel must be resolved");
6481
+ (0, import_common_helpers.invariant)(current.baseModel.ref, "baseModel must be resolved");
6358
6482
  todo.push(current.baseModel.ref);
6359
6483
  }
6360
6484
  }
@@ -6484,11 +6608,21 @@ var ExpressionValidator = class {
6484
6608
  }
6485
6609
  }
6486
6610
  switch (expr.$type) {
6611
+ case "MemberAccessExpr":
6612
+ this.validateMemberAccessExpr(expr, accept);
6613
+ break;
6487
6614
  case "BinaryExpr":
6488
6615
  this.validateBinaryExpr(expr, accept);
6489
6616
  break;
6490
6617
  }
6491
6618
  }
6619
+ validateMemberAccessExpr(expr, accept) {
6620
+ if (isBeforeInvocation(expr.operand) && isDataModel(expr.$resolvedType?.decl)) {
6621
+ accept("error", "relation fields cannot be accessed from `before()`", {
6622
+ node: expr
6623
+ });
6624
+ }
6625
+ }
6492
6626
  validateBinaryExpr(expr, accept) {
6493
6627
  switch (expr.operator) {
6494
6628
  case "in": {
@@ -6541,23 +6675,25 @@ var ExpressionValidator = class {
6541
6675
  "Any"
6542
6676
  ];
6543
6677
  }
6544
- if (typeof expr.left.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.left.$resolvedType.decl)) {
6678
+ const leftResolvedDecl = expr.left.$resolvedType?.decl;
6679
+ const rightResolvedDecl = expr.right.$resolvedType?.decl;
6680
+ if (leftResolvedDecl && (typeof leftResolvedDecl !== "string" || !supportedShapes.includes(leftResolvedDecl))) {
6545
6681
  accept("error", `invalid operand type for "${expr.operator}" operator`, {
6546
6682
  node: expr.left
6547
6683
  });
6548
6684
  return;
6549
6685
  }
6550
- if (typeof expr.right.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.right.$resolvedType.decl)) {
6686
+ if (rightResolvedDecl && (typeof rightResolvedDecl !== "string" || !supportedShapes.includes(rightResolvedDecl))) {
6551
6687
  accept("error", `invalid operand type for "${expr.operator}" operator`, {
6552
6688
  node: expr.right
6553
6689
  });
6554
6690
  return;
6555
6691
  }
6556
- if (expr.left.$resolvedType.decl === "DateTime" && expr.right.$resolvedType.decl !== "DateTime") {
6692
+ if (leftResolvedDecl === "DateTime" && rightResolvedDecl && rightResolvedDecl !== "DateTime") {
6557
6693
  accept("error", "incompatible operand types", {
6558
6694
  node: expr
6559
6695
  });
6560
- } else if (expr.right.$resolvedType.decl === "DateTime" && expr.left.$resolvedType.decl !== "DateTime") {
6696
+ } else if (rightResolvedDecl === "DateTime" && leftResolvedDecl && leftResolvedDecl !== "DateTime") {
6561
6697
  accept("error", "incompatible operand types", {
6562
6698
  node: expr
6563
6699
  });
@@ -6597,11 +6733,11 @@ var ExpressionValidator = class {
6597
6733
  });
6598
6734
  }
6599
6735
  if (isDataFieldReference(expr.left) && (isThisExpr(expr.right) || isDataFieldReference(expr.right))) {
6600
- accept("error", "comparison between model-typed fields are not supported", {
6736
+ accept("error", "comparison between models is not supported", {
6601
6737
  node: expr
6602
6738
  });
6603
6739
  } else if (isDataFieldReference(expr.right) && (isThisExpr(expr.left) || isDataFieldReference(expr.left))) {
6604
- accept("error", "comparison between model-typed fields are not supported", {
6740
+ accept("error", "comparison between models is not supported", {
6605
6741
  node: expr
6606
6742
  });
6607
6743
  }
@@ -6691,41 +6827,39 @@ var FunctionInvocationValidator = class {
6691
6827
  if (!this.validateArgs(funcDecl, expr.args, accept)) {
6692
6828
  return;
6693
6829
  }
6694
- if (isFromStdlib(funcDecl)) {
6695
- let curr = expr.$container;
6696
- let containerAttribute;
6697
- while (curr) {
6698
- if (isDataModelAttribute(curr) || isDataFieldAttribute(curr)) {
6699
- containerAttribute = curr;
6700
- break;
6701
- }
6702
- curr = curr.$container;
6830
+ let curr = expr.$container;
6831
+ let containerAttribute;
6832
+ while (curr) {
6833
+ if (isDataModelAttribute(curr) || isDataFieldAttribute(curr)) {
6834
+ containerAttribute = curr;
6835
+ break;
6703
6836
  }
6704
- const exprContext = (0, import_ts_pattern.match)(containerAttribute?.decl.$refText).with("@default", () => ExpressionContext.DefaultValue).with(import_ts_pattern.P.union("@@allow", "@@deny", "@allow", "@deny"), () => ExpressionContext.AccessPolicy).with("@@validate", () => ExpressionContext.ValidationRule).with("@@index", () => ExpressionContext.Index).otherwise(() => void 0);
6705
- const funcAllowedContext = getFunctionExpressionContext(funcDecl);
6706
- if (exprContext && !funcAllowedContext.includes(exprContext)) {
6707
- accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
6708
- node: expr
6837
+ curr = curr.$container;
6838
+ }
6839
+ const exprContext = this.getExpressionContext(containerAttribute);
6840
+ const funcAllowedContext = getFunctionExpressionContext(funcDecl);
6841
+ if (exprContext && !funcAllowedContext.includes(exprContext)) {
6842
+ accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
6843
+ node: expr
6844
+ });
6845
+ return;
6846
+ }
6847
+ const allCasing = [
6848
+ "original",
6849
+ "upper",
6850
+ "lower",
6851
+ "capitalize",
6852
+ "uncapitalize"
6853
+ ];
6854
+ if ([
6855
+ "currentModel",
6856
+ "currentOperation"
6857
+ ].includes(funcDecl.name)) {
6858
+ const arg = getLiteral(expr.args[0]?.value);
6859
+ if (arg && !allCasing.includes(arg)) {
6860
+ accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
6861
+ node: expr.args[0]
6709
6862
  });
6710
- return;
6711
- }
6712
- const allCasing = [
6713
- "original",
6714
- "upper",
6715
- "lower",
6716
- "capitalize",
6717
- "uncapitalize"
6718
- ];
6719
- if ([
6720
- "currentModel",
6721
- "currentOperation"
6722
- ].includes(funcDecl.name)) {
6723
- const arg = getLiteral(expr.args[0]?.value);
6724
- if (arg && !allCasing.includes(arg)) {
6725
- accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
6726
- node: expr.args[0]
6727
- });
6728
- }
6729
6863
  }
6730
6864
  }
6731
6865
  const checker = invocationCheckers.get(expr.function.$refText);
@@ -6733,6 +6867,18 @@ var FunctionInvocationValidator = class {
6733
6867
  checker.value.call(this, expr, accept);
6734
6868
  }
6735
6869
  }
6870
+ getExpressionContext(containerAttribute) {
6871
+ if (!containerAttribute) {
6872
+ return void 0;
6873
+ }
6874
+ if (this.isValidationAttribute(containerAttribute)) {
6875
+ return ExpressionContext.ValidationRule;
6876
+ }
6877
+ return (0, import_ts_pattern.match)(containerAttribute?.decl.$refText).with("@default", () => ExpressionContext.DefaultValue).with(import_ts_pattern.P.union("@@allow", "@@deny", "@allow", "@deny"), () => ExpressionContext.AccessPolicy).with("@@index", () => ExpressionContext.Index).otherwise(() => void 0);
6878
+ }
6879
+ isValidationAttribute(attr) {
6880
+ return !!attr.decl.ref?.attributes.some((attr2) => attr2.decl.$refText === "@@@validation");
6881
+ }
6736
6882
  validateArgs(funcDecl, args, accept) {
6737
6883
  let success = true;
6738
6884
  for (let i = 0; i < funcDecl.params.length; i++) {
@@ -6793,6 +6939,44 @@ var FunctionInvocationValidator = class {
6793
6939
  }
6794
6940
  return true;
6795
6941
  }
6942
+ _checkLength(expr, accept) {
6943
+ const msg = "argument must be a string or list field";
6944
+ const fieldArg = expr.args[0].value;
6945
+ if (!isDataFieldReference(fieldArg)) {
6946
+ accept("error", msg, {
6947
+ node: expr.args[0]
6948
+ });
6949
+ return;
6950
+ }
6951
+ if (isDataModel(fieldArg.$resolvedType?.decl)) {
6952
+ accept("error", msg, {
6953
+ node: expr.args[0]
6954
+ });
6955
+ return;
6956
+ }
6957
+ if (!fieldArg.$resolvedType?.array && fieldArg.$resolvedType?.decl !== "String") {
6958
+ accept("error", msg, {
6959
+ node: expr.args[0]
6960
+ });
6961
+ }
6962
+ }
6963
+ _checkRegex(expr, accept) {
6964
+ const regex = expr.args[1]?.value;
6965
+ if (!isStringLiteral(regex)) {
6966
+ accept("error", "second argument must be a string literal", {
6967
+ node: expr.args[1]
6968
+ });
6969
+ return;
6970
+ }
6971
+ try {
6972
+ new RegExp(regex.value);
6973
+ } catch (e) {
6974
+ accept("error", "invalid regular expression: " + e.message, {
6975
+ node: expr.args[1]
6976
+ });
6977
+ }
6978
+ }
6979
+ // TODO: move this to policy plugin
6796
6980
  _checkCheck(expr, accept) {
6797
6981
  let valid = true;
6798
6982
  const fieldArg = expr.args[0].value;
@@ -6864,6 +7048,24 @@ var FunctionInvocationValidator = class {
6864
7048
  }
6865
7049
  }
6866
7050
  };
7051
+ _ts_decorate2([
7052
+ func("length"),
7053
+ _ts_metadata2("design:type", Function),
7054
+ _ts_metadata2("design:paramtypes", [
7055
+ typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
7056
+ typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
7057
+ ]),
7058
+ _ts_metadata2("design:returntype", void 0)
7059
+ ], FunctionInvocationValidator.prototype, "_checkLength", null);
7060
+ _ts_decorate2([
7061
+ func("regex"),
7062
+ _ts_metadata2("design:type", Function),
7063
+ _ts_metadata2("design:paramtypes", [
7064
+ typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
7065
+ typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
7066
+ ]),
7067
+ _ts_metadata2("design:returntype", void 0)
7068
+ ], FunctionInvocationValidator.prototype, "_checkRegex", null);
6867
7069
  _ts_decorate2([
6868
7070
  func("check"),
6869
7071
  _ts_metadata2("design:type", Function),
@@ -6973,51 +7175,68 @@ var ZModelValidator = class {
6973
7175
  constructor(services) {
6974
7176
  this.services = services;
6975
7177
  }
6976
- shouldCheck(node) {
6977
- let doc;
6978
- let currNode = node;
6979
- while (currNode) {
6980
- if (currNode.$document) {
6981
- doc = currNode.$document;
6982
- break;
6983
- }
6984
- currNode = currNode.$container;
6985
- }
6986
- return doc?.parseResult.lexerErrors.length === 0 && doc?.parseResult.parserErrors.length === 0;
6987
- }
6988
7178
  checkModel(node, accept) {
6989
- this.shouldCheck(node) && new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
7179
+ new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
6990
7180
  }
6991
7181
  checkDataSource(node, accept) {
6992
- this.shouldCheck(node) && new DataSourceValidator().validate(node, accept);
7182
+ new DataSourceValidator().validate(node, accept);
6993
7183
  }
6994
7184
  checkDataModel(node, accept) {
6995
- this.shouldCheck(node) && new DataModelValidator().validate(node, accept);
7185
+ new DataModelValidator().validate(node, accept);
6996
7186
  }
6997
7187
  checkTypeDef(node, accept) {
6998
- this.shouldCheck(node) && new TypeDefValidator().validate(node, accept);
7188
+ new TypeDefValidator().validate(node, accept);
6999
7189
  }
7000
7190
  checkEnum(node, accept) {
7001
- this.shouldCheck(node) && new EnumValidator().validate(node, accept);
7191
+ new EnumValidator().validate(node, accept);
7002
7192
  }
7003
7193
  checkAttribute(node, accept) {
7004
- this.shouldCheck(node) && new AttributeValidator().validate(node, accept);
7194
+ new AttributeValidator().validate(node, accept);
7005
7195
  }
7006
7196
  checkExpression(node, accept) {
7007
- this.shouldCheck(node) && new ExpressionValidator().validate(node, accept);
7197
+ new ExpressionValidator().validate(node, accept);
7008
7198
  }
7009
7199
  checkFunctionInvocation(node, accept) {
7010
- this.shouldCheck(node) && new FunctionInvocationValidator().validate(node, accept);
7200
+ new FunctionInvocationValidator().validate(node, accept);
7011
7201
  }
7012
7202
  checkFunctionDecl(node, accept) {
7013
- this.shouldCheck(node) && new FunctionDeclValidator().validate(node, accept);
7203
+ new FunctionDeclValidator().validate(node, accept);
7014
7204
  }
7015
7205
  };
7016
7206
 
7017
- // src/zmodel-linker.ts
7207
+ // src/zmodel-document-builder.ts
7018
7208
  var import_langium7 = require("langium");
7209
+ var ZModelDocumentBuilder = class extends import_langium7.DefaultDocumentBuilder {
7210
+ static {
7211
+ __name(this, "ZModelDocumentBuilder");
7212
+ }
7213
+ constructor(services) {
7214
+ super(services);
7215
+ let validationOptions = this.updateBuildOptions.validation;
7216
+ const stopFlags = {
7217
+ stopAfterLinkingErrors: true,
7218
+ stopAfterLexingErrors: true,
7219
+ stopAfterParsingErrors: true
7220
+ };
7221
+ if (validationOptions === true) {
7222
+ validationOptions = stopFlags;
7223
+ } else if (typeof validationOptions === "object") {
7224
+ validationOptions = {
7225
+ ...validationOptions,
7226
+ ...stopFlags
7227
+ };
7228
+ }
7229
+ this.updateBuildOptions = {
7230
+ ...this.updateBuildOptions,
7231
+ validation: validationOptions
7232
+ };
7233
+ }
7234
+ };
7235
+
7236
+ // src/zmodel-linker.ts
7237
+ var import_langium8 = require("langium");
7019
7238
  var import_ts_pattern2 = require("ts-pattern");
7020
- var ZModelLinker = class extends import_langium7.DefaultLinker {
7239
+ var ZModelLinker = class extends import_langium8.DefaultLinker {
7021
7240
  static {
7022
7241
  __name(this, "ZModelLinker");
7023
7242
  }
@@ -7027,31 +7246,29 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7027
7246
  this.descriptions = services.workspace.AstNodeDescriptionProvider;
7028
7247
  }
7029
7248
  //#region Reference linking
7030
- async link(document, cancelToken = import_langium7.Cancellation.CancellationToken.None) {
7249
+ async link(document, cancelToken = import_langium8.Cancellation.CancellationToken.None) {
7031
7250
  if (document.parseResult.lexerErrors?.length > 0 || document.parseResult.parserErrors?.length > 0) {
7032
7251
  return;
7033
7252
  }
7034
- for (const node of import_langium7.AstUtils.streamContents(document.parseResult.value)) {
7035
- await (0, import_langium7.interruptAndCheck)(cancelToken);
7253
+ for (const node of import_langium8.AstUtils.streamContents(document.parseResult.value)) {
7254
+ await (0, import_langium8.interruptAndCheck)(cancelToken);
7036
7255
  this.resolve(node, document);
7037
7256
  }
7038
- document.state = import_langium7.DocumentState.Linked;
7257
+ document.state = import_langium8.DocumentState.Linked;
7039
7258
  }
7040
- linkReference(container, property, document, extraScopes) {
7041
- if (this.resolveFromScopeProviders(container, property, document, extraScopes)) {
7259
+ linkReference(refInfo, document, extraScopes) {
7260
+ const defaultRef = refInfo.reference;
7261
+ if (defaultRef._ref) {
7042
7262
  return;
7043
7263
  }
7044
- const reference = container[property];
7045
- this.doLink({
7046
- reference,
7047
- container,
7048
- property
7049
- }, document);
7264
+ if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
7265
+ return;
7266
+ }
7267
+ this.doLink(refInfo, document);
7050
7268
  }
7051
7269
  //#endregion
7052
7270
  //#region Expression type resolving
7053
- resolveFromScopeProviders(node, property, document, providers) {
7054
- const reference = node[property];
7271
+ resolveFromScopeProviders(reference, document, providers) {
7055
7272
  for (const provider of providers) {
7056
7273
  const target = provider(reference.$refText);
7057
7274
  if (target) {
@@ -7180,12 +7397,16 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7180
7397
  }
7181
7398
  }
7182
7399
  resolveInvocation(node, document, extraScopes) {
7183
- this.linkReference(node, "function", document, extraScopes);
7400
+ this.linkReference({
7401
+ reference: node.function,
7402
+ container: node,
7403
+ property: "function"
7404
+ }, document, extraScopes);
7184
7405
  node.args.forEach((arg) => this.resolve(arg, document, extraScopes));
7185
7406
  if (node.function.ref) {
7186
7407
  const funcDecl = node.function.ref;
7187
7408
  if (isAuthInvocation(node)) {
7188
- const allDecls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.langiumDocuments(), import_langium7.AstUtils.getContainerOfType(node, isDataModel));
7409
+ const allDecls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.langiumDocuments(), import_langium8.AstUtils.getContainerOfType(node, isDataModel));
7189
7410
  const authDecl = getAuthDecl(allDecls);
7190
7411
  if (authDecl) {
7191
7412
  node.$resolvedType = {
@@ -7193,7 +7414,7 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7193
7414
  nullable: true
7194
7415
  };
7195
7416
  }
7196
- } else if (isFutureExpr(node)) {
7417
+ } else if (isBeforeInvocation(node)) {
7197
7418
  node.$resolvedType = {
7198
7419
  decl: getContainingDataModel(node)
7199
7420
  };
@@ -7257,7 +7478,7 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7257
7478
  if (isArrayExpr(node.value)) {
7258
7479
  node.value.items.forEach((item) => {
7259
7480
  if (isReferenceExpr(item)) {
7260
- const resolved2 = this.resolveFromScopeProviders(item, "target", document, [
7481
+ const resolved2 = this.resolveFromScopeProviders(item.target, document, [
7261
7482
  scopeProvider
7262
7483
  ]);
7263
7484
  if (resolved2) {
@@ -7271,7 +7492,7 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7271
7492
  this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true);
7272
7493
  }
7273
7494
  } else if (isReferenceExpr(node.value)) {
7274
- const resolved2 = this.resolveFromScopeProviders(node.value, "target", document, [
7495
+ const resolved2 = this.resolveFromScopeProviders(node.value.target, document, [
7275
7496
  scopeProvider
7276
7497
  ]);
7277
7498
  if (resolved2) {
@@ -7323,14 +7544,10 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7323
7544
  this.resolveDefault(node, document, scopes);
7324
7545
  }
7325
7546
  resolveDefault(node, document, extraScopes) {
7326
- for (const [property, value] of Object.entries(node)) {
7327
- if (!property.startsWith("$")) {
7328
- if ((0, import_langium7.isReference)(value)) {
7329
- this.linkReference(node, property, document, extraScopes);
7330
- }
7331
- }
7332
- }
7333
- for (const child of import_langium7.AstUtils.streamContents(node)) {
7547
+ import_langium8.AstUtils.streamReferences(node).forEach((ref) => {
7548
+ this.linkReference(ref, document, extraScopes);
7549
+ });
7550
+ for (const child of import_langium8.AstUtils.streamContents(node)) {
7334
7551
  this.resolve(child, document, extraScopes);
7335
7552
  }
7336
7553
  }
@@ -7374,9 +7591,9 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7374
7591
  };
7375
7592
 
7376
7593
  // src/zmodel-scope.ts
7377
- var import_langium8 = require("langium");
7594
+ var import_langium9 = require("langium");
7378
7595
  var import_ts_pattern3 = require("ts-pattern");
7379
- var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputation {
7596
+ var ZModelScopeComputation = class extends import_langium9.DefaultScopeComputation {
7380
7597
  static {
7381
7598
  __name(this, "ZModelScopeComputation");
7382
7599
  }
@@ -7386,9 +7603,9 @@ var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputati
7386
7603
  }
7387
7604
  async computeExports(document, cancelToken) {
7388
7605
  const result = await super.computeExports(document, cancelToken);
7389
- for (const node of import_langium8.AstUtils.streamAllContents(document.parseResult.value)) {
7606
+ for (const node of import_langium9.AstUtils.streamAllContents(document.parseResult.value)) {
7390
7607
  if (cancelToken) {
7391
- await (0, import_langium8.interruptAndCheck)(cancelToken);
7608
+ await (0, import_langium9.interruptAndCheck)(cancelToken);
7392
7609
  }
7393
7610
  if (isEnumField(node)) {
7394
7611
  const desc = this.services.workspace.AstNodeDescriptionProvider.createDescription(node, node.name, document);
@@ -7399,7 +7616,7 @@ var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputati
7399
7616
  }
7400
7617
  processNode(node, document, scopes) {
7401
7618
  super.processNode(node, document, scopes);
7402
- if (isDataModel(node)) {
7619
+ if (isDataModel(node) || isTypeDef(node)) {
7403
7620
  const bases = getRecursiveBases(node);
7404
7621
  for (const base of bases) {
7405
7622
  for (const field of base.fields) {
@@ -7409,7 +7626,7 @@ var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputati
7409
7626
  }
7410
7627
  }
7411
7628
  };
7412
- var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7629
+ var ZModelScopeProvider = class extends import_langium9.DefaultScopeProvider {
7413
7630
  static {
7414
7631
  __name(this, "ZModelScopeProvider");
7415
7632
  }
@@ -7418,19 +7635,19 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7418
7635
  super(services), this.services = services;
7419
7636
  }
7420
7637
  getGlobalScope(referenceType, context) {
7421
- const model = import_langium8.AstUtils.getContainerOfType(context.container, isModel);
7638
+ const model = import_langium9.AstUtils.getContainerOfType(context.container, isModel);
7422
7639
  if (!model) {
7423
- return import_langium8.EMPTY_SCOPE;
7640
+ return import_langium9.EMPTY_SCOPE;
7424
7641
  }
7425
7642
  const importedUris = model.imports.map(resolveImportUri).filter((url) => !!url);
7426
7643
  const importedElements = this.indexManager.allElements(referenceType).filter((des) => (
7427
7644
  // allow current document
7428
- import_langium8.UriUtils.equals(des.documentUri, model.$document?.uri) || // allow stdlib
7645
+ import_langium9.UriUtils.equals(des.documentUri, model.$document?.uri) || // allow stdlib
7429
7646
  des.documentUri.path.endsWith(STD_LIB_MODULE_NAME) || // allow plugin models
7430
7647
  des.documentUri.path.endsWith(PLUGIN_MODULE_NAME) || // allow imported documents
7431
- importedUris.some((importedUri) => import_langium8.UriUtils.equals(des.documentUri, importedUri))
7648
+ importedUris.some((importedUri) => import_langium9.UriUtils.equals(des.documentUri, importedUri))
7432
7649
  ));
7433
- return new import_langium8.StreamScope(importedElements);
7650
+ return new import_langium9.StreamScope(importedElements);
7434
7651
  }
7435
7652
  getScope(context) {
7436
7653
  if (isMemberAccessExpr(context.container) && context.container.operand && context.property === "member") {
@@ -7450,31 +7667,31 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7450
7667
  const node = context.container;
7451
7668
  const allowTypeDefScope = (
7452
7669
  // isAuthOrAuthMemberAccess(node.operand) ||
7453
- !!import_langium8.AstUtils.getContainerOfType(node, isTypeDef)
7670
+ !!import_langium9.AstUtils.getContainerOfType(node, isTypeDef)
7454
7671
  );
7455
7672
  return (0, import_ts_pattern3.match)(node.operand).when(isReferenceExpr, (operand) => {
7456
7673
  const ref = operand.target.ref;
7457
7674
  if (isDataField(ref)) {
7458
7675
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7459
7676
  }
7460
- return import_langium8.EMPTY_SCOPE;
7677
+ return import_langium9.EMPTY_SCOPE;
7461
7678
  }).when(isMemberAccessExpr, (operand) => {
7462
7679
  const ref = operand.member.ref;
7463
7680
  if (isDataField(ref) && !ref.type.array) {
7464
7681
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7465
7682
  }
7466
- return import_langium8.EMPTY_SCOPE;
7683
+ return import_langium9.EMPTY_SCOPE;
7467
7684
  }).when(isThisExpr, () => {
7468
7685
  return this.createScopeForContainingModel(node, globalScope);
7469
7686
  }).when(isInvocationExpr, (operand) => {
7470
7687
  if (isAuthInvocation(operand)) {
7471
7688
  return this.createScopeForAuth(node, globalScope);
7472
7689
  }
7473
- if (isFutureInvocation(operand)) {
7690
+ if (isBeforeInvocation(operand)) {
7474
7691
  return this.createScopeForContainingModel(node, globalScope);
7475
7692
  }
7476
- return import_langium8.EMPTY_SCOPE;
7477
- }).otherwise(() => import_langium8.EMPTY_SCOPE);
7693
+ return import_langium9.EMPTY_SCOPE;
7694
+ }).otherwise(() => import_langium9.EMPTY_SCOPE);
7478
7695
  }
7479
7696
  getCollectionPredicateScope(context, collectionPredicate) {
7480
7697
  const referenceType = this.reflection.getReferenceType(context);
@@ -7486,30 +7703,30 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7486
7703
  if (isDataField(ref)) {
7487
7704
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7488
7705
  }
7489
- return import_langium8.EMPTY_SCOPE;
7706
+ return import_langium9.EMPTY_SCOPE;
7490
7707
  }).when(isMemberAccessExpr, (expr) => {
7491
7708
  const ref = expr.member.ref;
7492
7709
  if (isDataField(ref)) {
7493
7710
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7494
7711
  }
7495
- return import_langium8.EMPTY_SCOPE;
7712
+ return import_langium9.EMPTY_SCOPE;
7496
7713
  }).when(isInvocationExpr, (expr) => {
7497
7714
  const returnTypeDecl = expr.function.ref?.returnType.reference?.ref;
7498
7715
  if (isDataModel(returnTypeDecl)) {
7499
7716
  return this.createScopeForContainer(returnTypeDecl, globalScope, allowTypeDefScope);
7500
7717
  } else {
7501
- return import_langium8.EMPTY_SCOPE;
7718
+ return import_langium9.EMPTY_SCOPE;
7502
7719
  }
7503
7720
  }).when(isAuthInvocation, (expr) => {
7504
7721
  return this.createScopeForAuth(expr, globalScope);
7505
- }).otherwise(() => import_langium8.EMPTY_SCOPE);
7722
+ }).otherwise(() => import_langium9.EMPTY_SCOPE);
7506
7723
  }
7507
7724
  createScopeForContainingModel(node, globalScope) {
7508
- const model = import_langium8.AstUtils.getContainerOfType(node, isDataModel);
7725
+ const model = import_langium9.AstUtils.getContainerOfType(node, isDataModel);
7509
7726
  if (model) {
7510
7727
  return this.createScopeForContainer(model, globalScope);
7511
7728
  } else {
7512
- return import_langium8.EMPTY_SCOPE;
7729
+ return import_langium9.EMPTY_SCOPE;
7513
7730
  }
7514
7731
  }
7515
7732
  createScopeForContainer(node, globalScope, includeTypeDefScope = false) {
@@ -7518,16 +7735,16 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7518
7735
  } else if (includeTypeDefScope && isTypeDef(node)) {
7519
7736
  return this.createScopeForNodes(node.fields, globalScope);
7520
7737
  } else {
7521
- return import_langium8.EMPTY_SCOPE;
7738
+ return import_langium9.EMPTY_SCOPE;
7522
7739
  }
7523
7740
  }
7524
7741
  createScopeForAuth(node, globalScope) {
7525
- const decls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.services.shared.workspace.LangiumDocuments, import_langium8.AstUtils.getContainerOfType(node, isDataModel));
7742
+ const decls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.services.shared.workspace.LangiumDocuments, import_langium9.AstUtils.getContainerOfType(node, isDataModel));
7526
7743
  const authDecl = getAuthDecl(decls);
7527
7744
  if (authDecl) {
7528
7745
  return this.createScopeForContainer(authDecl, globalScope, true);
7529
7746
  } else {
7530
- return import_langium8.EMPTY_SCOPE;
7747
+ return import_langium9.EMPTY_SCOPE;
7531
7748
  }
7532
7749
  }
7533
7750
  };
@@ -7544,12 +7761,12 @@ function getCollectionPredicateContext(node) {
7544
7761
  __name(getCollectionPredicateContext, "getCollectionPredicateContext");
7545
7762
 
7546
7763
  // src/zmodel-workspace-manager.ts
7547
- var import_langium9 = require("langium");
7764
+ var import_langium10 = require("langium");
7548
7765
  var import_node_fs2 = __toESM(require("fs"), 1);
7549
- var import_node_path = __toESM(require("path"), 1);
7550
- var import_node_url = require("url");
7551
- var import_meta = {};
7552
- var ZModelWorkspaceManager = class extends import_langium9.DefaultWorkspaceManager {
7766
+ var import_node_path2 = __toESM(require("path"), 1);
7767
+ var import_node_url2 = require("url");
7768
+ var import_meta2 = {};
7769
+ var ZModelWorkspaceManager = class extends import_langium10.DefaultWorkspaceManager {
7553
7770
  static {
7554
7771
  __name(this, "ZModelWorkspaceManager");
7555
7772
  }
@@ -7570,8 +7787,8 @@ var ZModelWorkspaceManager = class extends import_langium9.DefaultWorkspaceManag
7570
7787
  folderPath
7571
7788
  ]
7572
7789
  });
7573
- const languagePackageDir = import_node_path.default.dirname(languagePackagePath);
7574
- const candidateStdlibPath = import_node_path.default.join(languagePackageDir, "res", STD_LIB_MODULE_NAME);
7790
+ const languagePackageDir = import_node_path2.default.dirname(languagePackagePath);
7791
+ const candidateStdlibPath = import_node_path2.default.join(languagePackageDir, "res", STD_LIB_MODULE_NAME);
7575
7792
  if (import_node_fs2.default.existsSync(candidateStdlibPath)) {
7576
7793
  installedStdlibPath = candidateStdlibPath;
7577
7794
  console.log(`Found installed zenstack package stdlib at: ${installedStdlibPath}`);
@@ -7584,73 +7801,12 @@ var ZModelWorkspaceManager = class extends import_langium9.DefaultWorkspaceManag
7584
7801
  if (installedStdlibPath) {
7585
7802
  stdLibPath = installedStdlibPath;
7586
7803
  } else {
7587
- const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
7588
- stdLibPath = import_node_path.default.join(_dirname, "../res", STD_LIB_MODULE_NAME);
7804
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path2.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
7805
+ stdLibPath = import_node_path2.default.join(_dirname, "../res", STD_LIB_MODULE_NAME);
7589
7806
  console.log(`Using bundled stdlib in extension:`, stdLibPath);
7590
7807
  }
7591
- const stdlib = await this.documentFactory.fromUri(import_langium9.URI.file(stdLibPath));
7808
+ const stdlib = await this.documentFactory.fromUri(import_langium10.URI.file(stdLibPath));
7592
7809
  collector(stdlib);
7593
- const documents = this.langiumDocuments.all;
7594
- const pluginModels = /* @__PURE__ */ new Set();
7595
- documents.forEach((doc) => {
7596
- const parsed = doc.parseResult.value;
7597
- parsed.declarations.forEach((decl) => {
7598
- if (isPlugin(decl)) {
7599
- const providerField = decl.fields.find((f) => f.name === "provider");
7600
- if (providerField) {
7601
- const provider = getLiteral(providerField.value);
7602
- if (provider) {
7603
- pluginModels.add(provider);
7604
- }
7605
- }
7606
- }
7607
- });
7608
- });
7609
- if (pluginModels.size > 0) {
7610
- console.log(`Used plugin modules: ${Array.from(pluginModels)}`);
7611
- const pendingPluginModules = new Set(pluginModels);
7612
- await Promise.all(folders.map((wf) => [
7613
- wf,
7614
- this.getRootFolder(wf)
7615
- ]).map(async (entry) => this.loadPluginModels(...entry, pendingPluginModules, collector)));
7616
- }
7617
- }
7618
- async loadPluginModels(workspaceFolder, folderPath, pendingPluginModels, collector) {
7619
- const content = (await this.fileSystemProvider.readDirectory(folderPath)).sort((a, b) => {
7620
- if (a.isDirectory && b.isDirectory) {
7621
- const aName = import_langium9.UriUtils.basename(a.uri);
7622
- if (aName === "node_modules") {
7623
- return -1;
7624
- } else {
7625
- return 1;
7626
- }
7627
- } else {
7628
- return 0;
7629
- }
7630
- });
7631
- for (const entry of content) {
7632
- if (entry.isDirectory) {
7633
- const name = import_langium9.UriUtils.basename(entry.uri);
7634
- if (name === "node_modules") {
7635
- for (const plugin of Array.from(pendingPluginModels)) {
7636
- const path4 = import_langium9.UriUtils.joinPath(entry.uri, plugin, PLUGIN_MODULE_NAME);
7637
- try {
7638
- await this.fileSystemProvider.readFile(path4);
7639
- const document = await this.langiumDocuments.getOrCreateDocument(path4);
7640
- collector(document);
7641
- console.log(`Adding plugin document from ${path4.path}`);
7642
- pendingPluginModels.delete(plugin);
7643
- if (pendingPluginModels.size === 0) {
7644
- return;
7645
- }
7646
- } catch {
7647
- }
7648
- }
7649
- } else {
7650
- await this.loadPluginModels(workspaceFolder, entry.uri, pendingPluginModels, collector);
7651
- }
7652
- }
7653
- }
7654
7810
  }
7655
7811
  };
7656
7812
 
@@ -7667,12 +7823,13 @@ var ZModelLanguageModule = {
7667
7823
  };
7668
7824
  var ZModelSharedModule = {
7669
7825
  workspace: {
7826
+ DocumentBuilder: /* @__PURE__ */ __name((services) => new ZModelDocumentBuilder(services), "DocumentBuilder"),
7670
7827
  WorkspaceManager: /* @__PURE__ */ __name((services) => new ZModelWorkspaceManager(services), "WorkspaceManager")
7671
7828
  }
7672
7829
  };
7673
- function createZModelLanguageServices(context) {
7674
- const shared = (0, import_langium10.inject)((0, import_lsp.createDefaultSharedModule)(context), ZModelGeneratedSharedModule, ZModelSharedModule);
7675
- const ZModelLanguage = (0, import_langium10.inject)((0, import_lsp.createDefaultModule)({
7830
+ function createZModelLanguageServices(context, logToConsole = false) {
7831
+ const shared = (0, import_langium11.inject)((0, import_lsp.createDefaultSharedModule)(context), ZModelGeneratedSharedModule, ZModelSharedModule);
7832
+ const ZModelLanguage = (0, import_langium11.inject)((0, import_lsp.createDefaultModule)({
7676
7833
  shared
7677
7834
  }), ZModelGeneratedModule, ZModelLanguageModule);
7678
7835
  shared.ServiceRegistry.register(ZModelLanguage);
@@ -7680,31 +7837,42 @@ function createZModelLanguageServices(context) {
7680
7837
  if (!context.connection) {
7681
7838
  shared.workspace.ConfigurationProvider.initialized({});
7682
7839
  }
7840
+ shared.workspace.DocumentBuilder.onBuildPhase(import_langium11.DocumentState.Parsed, async (documents) => {
7841
+ for (const doc of documents) {
7842
+ if (doc.parseResult.lexerErrors.length > 0 || doc.parseResult.parserErrors.length > 0) {
7843
+ continue;
7844
+ }
7845
+ if (doc.uri.scheme !== "file") {
7846
+ continue;
7847
+ }
7848
+ const schemaPath = (0, import_node_url3.fileURLToPath)(doc.uri.toString());
7849
+ const pluginSchemas = getPluginDocuments(doc.parseResult.value, schemaPath);
7850
+ for (const plugin of pluginSchemas) {
7851
+ const pluginDoc = await shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium11.URI.file(import_node_path3.default.resolve(plugin)));
7852
+ shared.workspace.IndexManager.updateContent(pluginDoc);
7853
+ if (logToConsole) {
7854
+ console.log(`Loaded plugin model: ${plugin}`);
7855
+ }
7856
+ }
7857
+ }
7858
+ });
7683
7859
  return {
7684
7860
  shared,
7685
7861
  ZModelLanguage
7686
7862
  };
7687
7863
  }
7688
7864
  __name(createZModelLanguageServices, "createZModelLanguageServices");
7689
-
7690
- // src/index.ts
7691
- var import_meta2 = {};
7692
- function createZModelServices() {
7693
- return createZModelLanguageServices(import_node.NodeFileSystem);
7865
+ function createZModelServices(logToConsole = false) {
7866
+ return createZModelLanguageServices(import_node.NodeFileSystem, logToConsole);
7694
7867
  }
7695
7868
  __name(createZModelServices, "createZModelServices");
7696
- var DocumentLoadError = class extends Error {
7697
- static {
7698
- __name(this, "DocumentLoadError");
7699
- }
7700
- constructor(message) {
7701
- super(message);
7702
- }
7703
- };
7704
- async function loadDocument(fileName, pluginModelFiles = []) {
7705
- const { ZModelLanguage: services } = createZModelServices();
7869
+
7870
+ // src/document.ts
7871
+ var import_meta3 = {};
7872
+ async function loadDocument(fileName, additionalModelFiles = []) {
7873
+ const { ZModelLanguage: services } = createZModelServices(false);
7706
7874
  const extensions = services.LanguageMetaData.fileExtensions;
7707
- if (!extensions.includes(import_node_path2.default.extname(fileName))) {
7875
+ if (!extensions.includes(import_node_path4.default.extname(fileName))) {
7708
7876
  return {
7709
7877
  success: false,
7710
7878
  errors: [
@@ -7722,23 +7890,27 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7722
7890
  warnings: []
7723
7891
  };
7724
7892
  }
7725
- const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path2.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
7726
- const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium11.URI.file(import_node_path2.default.resolve(import_node_path2.default.join(_dirname, "../res", STD_LIB_MODULE_NAME))));
7727
- const pluginDocs = await Promise.all(pluginModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium11.URI.file(import_node_path2.default.resolve(file)))));
7893
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path4.default.dirname((0, import_node_url4.fileURLToPath)(import_meta3.url));
7894
+ const stdLib = await services.shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium12.URI.file(import_node_path4.default.resolve(import_node_path4.default.join(_dirname, "../res", STD_LIB_MODULE_NAME))));
7728
7895
  const langiumDocuments = services.shared.workspace.LangiumDocuments;
7729
- const document = await langiumDocuments.getOrCreateDocument(import_langium11.URI.file(import_node_path2.default.resolve(fileName)));
7896
+ const document = await langiumDocuments.getOrCreateDocument(import_langium12.URI.file(import_node_path4.default.resolve(fileName)));
7730
7897
  const importedURIs = await loadImports(document, langiumDocuments);
7731
7898
  const importedDocuments = [];
7732
7899
  for (const uri of importedURIs) {
7733
7900
  importedDocuments.push(await langiumDocuments.getOrCreateDocument(uri));
7734
7901
  }
7902
+ const additionalDocs = await Promise.all(additionalModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium12.URI.file(import_node_path4.default.resolve(file)))));
7735
7903
  await services.shared.workspace.DocumentBuilder.build([
7736
7904
  stdLib,
7737
- ...pluginDocs,
7905
+ ...additionalDocs,
7738
7906
  document,
7739
7907
  ...importedDocuments
7740
7908
  ], {
7741
- validation: true
7909
+ validation: {
7910
+ stopAfterLexingErrors: true,
7911
+ stopAfterParsingErrors: true,
7912
+ stopAfterLinkingErrors: true
7913
+ }
7742
7914
  });
7743
7915
  const diagnostics = langiumDocuments.all.flatMap((doc) => (doc.diagnostics ?? []).map((diag) => ({
7744
7916
  doc,
@@ -7748,7 +7920,7 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7748
7920
  const warnings = [];
7749
7921
  if (diagnostics.length > 0) {
7750
7922
  for (const { doc, diag } of diagnostics) {
7751
- const message = `${import_node_path2.default.relative(process.cwd(), doc.uri.fsPath)}:${diag.range.start.line + 1}:${diag.range.start.character + 1} - ${diag.message}`;
7923
+ const message = `${import_node_path4.default.relative(process.cwd(), doc.uri.fsPath)}:${diag.range.start.line + 1}:${diag.range.start.character + 1} - ${diag.message}`;
7752
7924
  if (diag.severity === 1) {
7753
7925
  errors.push(message);
7754
7926
  } else {
@@ -7797,7 +7969,7 @@ async function loadImports(document, documents, uris = /* @__PURE__ */ new Set()
7797
7969
  }
7798
7970
  }
7799
7971
  }
7800
- return Array.from(uris).filter((x) => uriString != x).map((e) => import_langium11.URI.parse(e));
7972
+ return Array.from(uris).filter((x) => uriString != x).map((e) => import_langium12.URI.parse(e));
7801
7973
  }
7802
7974
  __name(loadImports, "loadImports");
7803
7975
  function mergeImportsDeclarations(documents, model) {
@@ -7814,13 +7986,13 @@ function linkContentToContainer(node) {
7814
7986
  if (!name.startsWith("$")) {
7815
7987
  if (Array.isArray(value)) {
7816
7988
  value.forEach((item, index) => {
7817
- if ((0, import_langium11.isAstNode)(item)) {
7989
+ if ((0, import_langium12.isAstNode)(item)) {
7818
7990
  item.$container = node;
7819
7991
  item.$containerProperty = name;
7820
7992
  item.$containerIndex = index;
7821
7993
  }
7822
7994
  });
7823
- } else if ((0, import_langium11.isAstNode)(value)) {
7995
+ } else if ((0, import_langium12.isAstNode)(value)) {
7824
7996
  value.$container = node;
7825
7997
  value.$containerProperty = name;
7826
7998
  }
@@ -7848,7 +8020,6 @@ function validationAfterImportMerge(model) {
7848
8020
  __name(validationAfterImportMerge, "validationAfterImportMerge");
7849
8021
  // Annotate the CommonJS export names for ESM import in node:
7850
8022
  0 && (module.exports = {
7851
- DocumentLoadError,
7852
8023
  ZModelLanguageMetaData,
7853
8024
  ZModelLanguageModule,
7854
8025
  ZModelSharedModule,