@zenstackhq/language 3.0.0-beta.1 → 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.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) {
@@ -5463,10 +5466,10 @@ function getAuthDecl(decls) {
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;
@@ -5775,15 +5899,6 @@ var AttributeApplicationValidator = class {
5775
5899
  });
5776
5900
  }
5777
5901
  }
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
5902
  validatePolicyKinds(kind, candidates, attr, accept) {
5788
5903
  const items = kind.split(",").map((x) => x.trim());
5789
5904
  items.forEach((item) => {
@@ -5844,6 +5959,10 @@ function assignableToAttributeParam(arg, param, attr) {
5844
5959
  let dstIsArray = param.type.array;
5845
5960
  if (dstType === "ContextType") {
5846
5961
  if (isDataField(attr.$container)) {
5962
+ const dstIsTypedJson = hasAttribute(attr.$container, "@json");
5963
+ if (dstIsTypedJson && attr.decl.ref?.name === "@default") {
5964
+ return argResolvedType.decl === "String";
5965
+ }
5847
5966
  dstIsArray = attr.$container.type.array;
5848
5967
  }
5849
5968
  }
@@ -5935,6 +6054,9 @@ function isValidAttributeTarget(attrDecl, targetDecl) {
5935
6054
  case "TypeDefField":
5936
6055
  allowed = allowed || isTypeDef(targetDecl.type.reference?.ref);
5937
6056
  break;
6057
+ case "ListField":
6058
+ allowed = allowed || !isDataModel(targetDecl.type.reference?.ref) && targetDecl.type.array;
6059
+ break;
5938
6060
  default:
5939
6061
  break;
5940
6062
  }
@@ -5961,7 +6083,7 @@ var AttributeValidator = class {
5961
6083
  };
5962
6084
 
5963
6085
  // src/validators/datamodel-validator.ts
5964
- var import_common_helpers2 = require("@zenstackhq/common-helpers");
6086
+ var import_common_helpers = require("@zenstackhq/common-helpers");
5965
6087
  var import_langium4 = require("langium");
5966
6088
 
5967
6089
  // src/validators/common.ts
@@ -6332,7 +6454,7 @@ var DataModelValidator = class {
6332
6454
  if (!model.baseModel) {
6333
6455
  return;
6334
6456
  }
6335
- (0, import_common_helpers2.invariant)(model.baseModel.ref, "baseModel must be resolved");
6457
+ (0, import_common_helpers.invariant)(model.baseModel.ref, "baseModel must be resolved");
6336
6458
  if (!isDelegateModel(model.baseModel.ref)) {
6337
6459
  accept("error", `Model ${model.baseModel.$refText} cannot be extended because it's not a delegate model`, {
6338
6460
  node: model,
@@ -6354,7 +6476,7 @@ var DataModelValidator = class {
6354
6476
  }
6355
6477
  seen.push(current);
6356
6478
  if (current.baseModel) {
6357
- (0, import_common_helpers2.invariant)(current.baseModel.ref, "baseModel must be resolved");
6479
+ (0, import_common_helpers.invariant)(current.baseModel.ref, "baseModel must be resolved");
6358
6480
  todo.push(current.baseModel.ref);
6359
6481
  }
6360
6482
  }
@@ -6484,11 +6606,21 @@ var ExpressionValidator = class {
6484
6606
  }
6485
6607
  }
6486
6608
  switch (expr.$type) {
6609
+ case "MemberAccessExpr":
6610
+ this.validateMemberAccessExpr(expr, accept);
6611
+ break;
6487
6612
  case "BinaryExpr":
6488
6613
  this.validateBinaryExpr(expr, accept);
6489
6614
  break;
6490
6615
  }
6491
6616
  }
6617
+ validateMemberAccessExpr(expr, accept) {
6618
+ if (isBeforeInvocation(expr.operand) && isDataModel(expr.$resolvedType?.decl)) {
6619
+ accept("error", "relation fields cannot be accessed from `before()`", {
6620
+ node: expr
6621
+ });
6622
+ }
6623
+ }
6492
6624
  validateBinaryExpr(expr, accept) {
6493
6625
  switch (expr.operator) {
6494
6626
  case "in": {
@@ -6541,23 +6673,25 @@ var ExpressionValidator = class {
6541
6673
  "Any"
6542
6674
  ];
6543
6675
  }
6544
- if (typeof expr.left.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.left.$resolvedType.decl)) {
6676
+ const leftResolvedDecl = expr.left.$resolvedType?.decl;
6677
+ const rightResolvedDecl = expr.right.$resolvedType?.decl;
6678
+ if (leftResolvedDecl && (typeof leftResolvedDecl !== "string" || !supportedShapes.includes(leftResolvedDecl))) {
6545
6679
  accept("error", `invalid operand type for "${expr.operator}" operator`, {
6546
6680
  node: expr.left
6547
6681
  });
6548
6682
  return;
6549
6683
  }
6550
- if (typeof expr.right.$resolvedType?.decl !== "string" || !supportedShapes.includes(expr.right.$resolvedType.decl)) {
6684
+ if (rightResolvedDecl && (typeof rightResolvedDecl !== "string" || !supportedShapes.includes(rightResolvedDecl))) {
6551
6685
  accept("error", `invalid operand type for "${expr.operator}" operator`, {
6552
6686
  node: expr.right
6553
6687
  });
6554
6688
  return;
6555
6689
  }
6556
- if (expr.left.$resolvedType.decl === "DateTime" && expr.right.$resolvedType.decl !== "DateTime") {
6690
+ if (leftResolvedDecl === "DateTime" && rightResolvedDecl && rightResolvedDecl !== "DateTime") {
6557
6691
  accept("error", "incompatible operand types", {
6558
6692
  node: expr
6559
6693
  });
6560
- } else if (expr.right.$resolvedType.decl === "DateTime" && expr.left.$resolvedType.decl !== "DateTime") {
6694
+ } else if (rightResolvedDecl === "DateTime" && leftResolvedDecl && leftResolvedDecl !== "DateTime") {
6561
6695
  accept("error", "incompatible operand types", {
6562
6696
  node: expr
6563
6697
  });
@@ -6597,11 +6731,11 @@ var ExpressionValidator = class {
6597
6731
  });
6598
6732
  }
6599
6733
  if (isDataFieldReference(expr.left) && (isThisExpr(expr.right) || isDataFieldReference(expr.right))) {
6600
- accept("error", "comparison between model-typed fields are not supported", {
6734
+ accept("error", "comparison between models is not supported", {
6601
6735
  node: expr
6602
6736
  });
6603
6737
  } else if (isDataFieldReference(expr.right) && (isThisExpr(expr.left) || isDataFieldReference(expr.left))) {
6604
- accept("error", "comparison between model-typed fields are not supported", {
6738
+ accept("error", "comparison between models is not supported", {
6605
6739
  node: expr
6606
6740
  });
6607
6741
  }
@@ -6691,41 +6825,39 @@ var FunctionInvocationValidator = class {
6691
6825
  if (!this.validateArgs(funcDecl, expr.args, accept)) {
6692
6826
  return;
6693
6827
  }
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;
6828
+ let curr = expr.$container;
6829
+ let containerAttribute;
6830
+ while (curr) {
6831
+ if (isDataModelAttribute(curr) || isDataFieldAttribute(curr)) {
6832
+ containerAttribute = curr;
6833
+ break;
6703
6834
  }
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
6835
+ curr = curr.$container;
6836
+ }
6837
+ const exprContext = this.getExpressionContext(containerAttribute);
6838
+ const funcAllowedContext = getFunctionExpressionContext(funcDecl);
6839
+ if (exprContext && !funcAllowedContext.includes(exprContext)) {
6840
+ accept("error", `function "${funcDecl.name}" is not allowed in the current context: ${exprContext}`, {
6841
+ node: expr
6842
+ });
6843
+ return;
6844
+ }
6845
+ const allCasing = [
6846
+ "original",
6847
+ "upper",
6848
+ "lower",
6849
+ "capitalize",
6850
+ "uncapitalize"
6851
+ ];
6852
+ if ([
6853
+ "currentModel",
6854
+ "currentOperation"
6855
+ ].includes(funcDecl.name)) {
6856
+ const arg = getLiteral(expr.args[0]?.value);
6857
+ if (arg && !allCasing.includes(arg)) {
6858
+ accept("error", `argument must be one of: ${allCasing.map((c) => '"' + c + '"').join(", ")}`, {
6859
+ node: expr.args[0]
6709
6860
  });
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
6861
  }
6730
6862
  }
6731
6863
  const checker = invocationCheckers.get(expr.function.$refText);
@@ -6733,6 +6865,18 @@ var FunctionInvocationValidator = class {
6733
6865
  checker.value.call(this, expr, accept);
6734
6866
  }
6735
6867
  }
6868
+ getExpressionContext(containerAttribute) {
6869
+ if (!containerAttribute) {
6870
+ return void 0;
6871
+ }
6872
+ if (this.isValidationAttribute(containerAttribute)) {
6873
+ return ExpressionContext.ValidationRule;
6874
+ }
6875
+ 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);
6876
+ }
6877
+ isValidationAttribute(attr) {
6878
+ return !!attr.decl.ref?.attributes.some((attr2) => attr2.decl.$refText === "@@@validation");
6879
+ }
6736
6880
  validateArgs(funcDecl, args, accept) {
6737
6881
  let success = true;
6738
6882
  for (let i = 0; i < funcDecl.params.length; i++) {
@@ -6793,6 +6937,44 @@ var FunctionInvocationValidator = class {
6793
6937
  }
6794
6938
  return true;
6795
6939
  }
6940
+ _checkLength(expr, accept) {
6941
+ const msg = "argument must be a string or list field";
6942
+ const fieldArg = expr.args[0].value;
6943
+ if (!isDataFieldReference(fieldArg)) {
6944
+ accept("error", msg, {
6945
+ node: expr.args[0]
6946
+ });
6947
+ return;
6948
+ }
6949
+ if (isDataModel(fieldArg.$resolvedType?.decl)) {
6950
+ accept("error", msg, {
6951
+ node: expr.args[0]
6952
+ });
6953
+ return;
6954
+ }
6955
+ if (!fieldArg.$resolvedType?.array && fieldArg.$resolvedType?.decl !== "String") {
6956
+ accept("error", msg, {
6957
+ node: expr.args[0]
6958
+ });
6959
+ }
6960
+ }
6961
+ _checkRegex(expr, accept) {
6962
+ const regex = expr.args[1]?.value;
6963
+ if (!isStringLiteral(regex)) {
6964
+ accept("error", "second argument must be a string literal", {
6965
+ node: expr.args[1]
6966
+ });
6967
+ return;
6968
+ }
6969
+ try {
6970
+ new RegExp(regex.value);
6971
+ } catch (e) {
6972
+ accept("error", "invalid regular expression: " + e.message, {
6973
+ node: expr.args[1]
6974
+ });
6975
+ }
6976
+ }
6977
+ // TODO: move this to policy plugin
6796
6978
  _checkCheck(expr, accept) {
6797
6979
  let valid = true;
6798
6980
  const fieldArg = expr.args[0].value;
@@ -6864,6 +7046,24 @@ var FunctionInvocationValidator = class {
6864
7046
  }
6865
7047
  }
6866
7048
  };
7049
+ _ts_decorate2([
7050
+ func("length"),
7051
+ _ts_metadata2("design:type", Function),
7052
+ _ts_metadata2("design:paramtypes", [
7053
+ typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
7054
+ typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
7055
+ ]),
7056
+ _ts_metadata2("design:returntype", void 0)
7057
+ ], FunctionInvocationValidator.prototype, "_checkLength", null);
7058
+ _ts_decorate2([
7059
+ func("regex"),
7060
+ _ts_metadata2("design:type", Function),
7061
+ _ts_metadata2("design:paramtypes", [
7062
+ typeof InvocationExpr === "undefined" ? Object : InvocationExpr,
7063
+ typeof ValidationAcceptor === "undefined" ? Object : ValidationAcceptor
7064
+ ]),
7065
+ _ts_metadata2("design:returntype", void 0)
7066
+ ], FunctionInvocationValidator.prototype, "_checkRegex", null);
6867
7067
  _ts_decorate2([
6868
7068
  func("check"),
6869
7069
  _ts_metadata2("design:type", Function),
@@ -6973,51 +7173,68 @@ var ZModelValidator = class {
6973
7173
  constructor(services) {
6974
7174
  this.services = services;
6975
7175
  }
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
7176
  checkModel(node, accept) {
6989
- this.shouldCheck(node) && new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
7177
+ new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
6990
7178
  }
6991
7179
  checkDataSource(node, accept) {
6992
- this.shouldCheck(node) && new DataSourceValidator().validate(node, accept);
7180
+ new DataSourceValidator().validate(node, accept);
6993
7181
  }
6994
7182
  checkDataModel(node, accept) {
6995
- this.shouldCheck(node) && new DataModelValidator().validate(node, accept);
7183
+ new DataModelValidator().validate(node, accept);
6996
7184
  }
6997
7185
  checkTypeDef(node, accept) {
6998
- this.shouldCheck(node) && new TypeDefValidator().validate(node, accept);
7186
+ new TypeDefValidator().validate(node, accept);
6999
7187
  }
7000
7188
  checkEnum(node, accept) {
7001
- this.shouldCheck(node) && new EnumValidator().validate(node, accept);
7189
+ new EnumValidator().validate(node, accept);
7002
7190
  }
7003
7191
  checkAttribute(node, accept) {
7004
- this.shouldCheck(node) && new AttributeValidator().validate(node, accept);
7192
+ new AttributeValidator().validate(node, accept);
7005
7193
  }
7006
7194
  checkExpression(node, accept) {
7007
- this.shouldCheck(node) && new ExpressionValidator().validate(node, accept);
7195
+ new ExpressionValidator().validate(node, accept);
7008
7196
  }
7009
7197
  checkFunctionInvocation(node, accept) {
7010
- this.shouldCheck(node) && new FunctionInvocationValidator().validate(node, accept);
7198
+ new FunctionInvocationValidator().validate(node, accept);
7011
7199
  }
7012
7200
  checkFunctionDecl(node, accept) {
7013
- this.shouldCheck(node) && new FunctionDeclValidator().validate(node, accept);
7201
+ new FunctionDeclValidator().validate(node, accept);
7014
7202
  }
7015
7203
  };
7016
7204
 
7017
- // src/zmodel-linker.ts
7205
+ // src/zmodel-document-builder.ts
7018
7206
  var import_langium7 = require("langium");
7207
+ var ZModelDocumentBuilder = class extends import_langium7.DefaultDocumentBuilder {
7208
+ static {
7209
+ __name(this, "ZModelDocumentBuilder");
7210
+ }
7211
+ constructor(services) {
7212
+ super(services);
7213
+ let validationOptions = this.updateBuildOptions.validation;
7214
+ const stopFlags = {
7215
+ stopAfterLinkingErrors: true,
7216
+ stopAfterLexingErrors: true,
7217
+ stopAfterParsingErrors: true
7218
+ };
7219
+ if (validationOptions === true) {
7220
+ validationOptions = stopFlags;
7221
+ } else if (typeof validationOptions === "object") {
7222
+ validationOptions = {
7223
+ ...validationOptions,
7224
+ ...stopFlags
7225
+ };
7226
+ }
7227
+ this.updateBuildOptions = {
7228
+ ...this.updateBuildOptions,
7229
+ validation: validationOptions
7230
+ };
7231
+ }
7232
+ };
7233
+
7234
+ // src/zmodel-linker.ts
7235
+ var import_langium8 = require("langium");
7019
7236
  var import_ts_pattern2 = require("ts-pattern");
7020
- var ZModelLinker = class extends import_langium7.DefaultLinker {
7237
+ var ZModelLinker = class extends import_langium8.DefaultLinker {
7021
7238
  static {
7022
7239
  __name(this, "ZModelLinker");
7023
7240
  }
@@ -7027,31 +7244,29 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7027
7244
  this.descriptions = services.workspace.AstNodeDescriptionProvider;
7028
7245
  }
7029
7246
  //#region Reference linking
7030
- async link(document, cancelToken = import_langium7.Cancellation.CancellationToken.None) {
7247
+ async link(document, cancelToken = import_langium8.Cancellation.CancellationToken.None) {
7031
7248
  if (document.parseResult.lexerErrors?.length > 0 || document.parseResult.parserErrors?.length > 0) {
7032
7249
  return;
7033
7250
  }
7034
- for (const node of import_langium7.AstUtils.streamContents(document.parseResult.value)) {
7035
- await (0, import_langium7.interruptAndCheck)(cancelToken);
7251
+ for (const node of import_langium8.AstUtils.streamContents(document.parseResult.value)) {
7252
+ await (0, import_langium8.interruptAndCheck)(cancelToken);
7036
7253
  this.resolve(node, document);
7037
7254
  }
7038
- document.state = import_langium7.DocumentState.Linked;
7255
+ document.state = import_langium8.DocumentState.Linked;
7039
7256
  }
7040
- linkReference(container, property, document, extraScopes) {
7041
- if (this.resolveFromScopeProviders(container, property, document, extraScopes)) {
7257
+ linkReference(refInfo, document, extraScopes) {
7258
+ const defaultRef = refInfo.reference;
7259
+ if (defaultRef._ref) {
7260
+ return;
7261
+ }
7262
+ if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
7042
7263
  return;
7043
7264
  }
7044
- const reference = container[property];
7045
- this.doLink({
7046
- reference,
7047
- container,
7048
- property
7049
- }, document);
7265
+ this.doLink(refInfo, document);
7050
7266
  }
7051
7267
  //#endregion
7052
7268
  //#region Expression type resolving
7053
- resolveFromScopeProviders(node, property, document, providers) {
7054
- const reference = node[property];
7269
+ resolveFromScopeProviders(reference, document, providers) {
7055
7270
  for (const provider of providers) {
7056
7271
  const target = provider(reference.$refText);
7057
7272
  if (target) {
@@ -7180,12 +7395,16 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7180
7395
  }
7181
7396
  }
7182
7397
  resolveInvocation(node, document, extraScopes) {
7183
- this.linkReference(node, "function", document, extraScopes);
7398
+ this.linkReference({
7399
+ reference: node.function,
7400
+ container: node,
7401
+ property: "function"
7402
+ }, document, extraScopes);
7184
7403
  node.args.forEach((arg) => this.resolve(arg, document, extraScopes));
7185
7404
  if (node.function.ref) {
7186
7405
  const funcDecl = node.function.ref;
7187
7406
  if (isAuthInvocation(node)) {
7188
- const allDecls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.langiumDocuments(), import_langium7.AstUtils.getContainerOfType(node, isDataModel));
7407
+ const allDecls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.langiumDocuments(), import_langium8.AstUtils.getContainerOfType(node, isDataModel));
7189
7408
  const authDecl = getAuthDecl(allDecls);
7190
7409
  if (authDecl) {
7191
7410
  node.$resolvedType = {
@@ -7193,7 +7412,7 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7193
7412
  nullable: true
7194
7413
  };
7195
7414
  }
7196
- } else if (isFutureExpr(node)) {
7415
+ } else if (isBeforeInvocation(node)) {
7197
7416
  node.$resolvedType = {
7198
7417
  decl: getContainingDataModel(node)
7199
7418
  };
@@ -7257,7 +7476,7 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7257
7476
  if (isArrayExpr(node.value)) {
7258
7477
  node.value.items.forEach((item) => {
7259
7478
  if (isReferenceExpr(item)) {
7260
- const resolved2 = this.resolveFromScopeProviders(item, "target", document, [
7479
+ const resolved2 = this.resolveFromScopeProviders(item.target, document, [
7261
7480
  scopeProvider
7262
7481
  ]);
7263
7482
  if (resolved2) {
@@ -7271,7 +7490,7 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7271
7490
  this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true);
7272
7491
  }
7273
7492
  } else if (isReferenceExpr(node.value)) {
7274
- const resolved2 = this.resolveFromScopeProviders(node.value, "target", document, [
7493
+ const resolved2 = this.resolveFromScopeProviders(node.value.target, document, [
7275
7494
  scopeProvider
7276
7495
  ]);
7277
7496
  if (resolved2) {
@@ -7323,14 +7542,10 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7323
7542
  this.resolveDefault(node, document, scopes);
7324
7543
  }
7325
7544
  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)) {
7545
+ import_langium8.AstUtils.streamReferences(node).forEach((ref) => {
7546
+ this.linkReference(ref, document, extraScopes);
7547
+ });
7548
+ for (const child of import_langium8.AstUtils.streamContents(node)) {
7334
7549
  this.resolve(child, document, extraScopes);
7335
7550
  }
7336
7551
  }
@@ -7374,9 +7589,9 @@ var ZModelLinker = class extends import_langium7.DefaultLinker {
7374
7589
  };
7375
7590
 
7376
7591
  // src/zmodel-scope.ts
7377
- var import_langium8 = require("langium");
7592
+ var import_langium9 = require("langium");
7378
7593
  var import_ts_pattern3 = require("ts-pattern");
7379
- var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputation {
7594
+ var ZModelScopeComputation = class extends import_langium9.DefaultScopeComputation {
7380
7595
  static {
7381
7596
  __name(this, "ZModelScopeComputation");
7382
7597
  }
@@ -7386,9 +7601,9 @@ var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputati
7386
7601
  }
7387
7602
  async computeExports(document, cancelToken) {
7388
7603
  const result = await super.computeExports(document, cancelToken);
7389
- for (const node of import_langium8.AstUtils.streamAllContents(document.parseResult.value)) {
7604
+ for (const node of import_langium9.AstUtils.streamAllContents(document.parseResult.value)) {
7390
7605
  if (cancelToken) {
7391
- await (0, import_langium8.interruptAndCheck)(cancelToken);
7606
+ await (0, import_langium9.interruptAndCheck)(cancelToken);
7392
7607
  }
7393
7608
  if (isEnumField(node)) {
7394
7609
  const desc = this.services.workspace.AstNodeDescriptionProvider.createDescription(node, node.name, document);
@@ -7399,7 +7614,7 @@ var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputati
7399
7614
  }
7400
7615
  processNode(node, document, scopes) {
7401
7616
  super.processNode(node, document, scopes);
7402
- if (isDataModel(node)) {
7617
+ if (isDataModel(node) || isTypeDef(node)) {
7403
7618
  const bases = getRecursiveBases(node);
7404
7619
  for (const base of bases) {
7405
7620
  for (const field of base.fields) {
@@ -7409,7 +7624,7 @@ var ZModelScopeComputation = class extends import_langium8.DefaultScopeComputati
7409
7624
  }
7410
7625
  }
7411
7626
  };
7412
- var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7627
+ var ZModelScopeProvider = class extends import_langium9.DefaultScopeProvider {
7413
7628
  static {
7414
7629
  __name(this, "ZModelScopeProvider");
7415
7630
  }
@@ -7418,19 +7633,19 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7418
7633
  super(services), this.services = services;
7419
7634
  }
7420
7635
  getGlobalScope(referenceType, context) {
7421
- const model = import_langium8.AstUtils.getContainerOfType(context.container, isModel);
7636
+ const model = import_langium9.AstUtils.getContainerOfType(context.container, isModel);
7422
7637
  if (!model) {
7423
- return import_langium8.EMPTY_SCOPE;
7638
+ return import_langium9.EMPTY_SCOPE;
7424
7639
  }
7425
7640
  const importedUris = model.imports.map(resolveImportUri).filter((url) => !!url);
7426
7641
  const importedElements = this.indexManager.allElements(referenceType).filter((des) => (
7427
7642
  // allow current document
7428
- import_langium8.UriUtils.equals(des.documentUri, model.$document?.uri) || // allow stdlib
7643
+ import_langium9.UriUtils.equals(des.documentUri, model.$document?.uri) || // allow stdlib
7429
7644
  des.documentUri.path.endsWith(STD_LIB_MODULE_NAME) || // allow plugin models
7430
7645
  des.documentUri.path.endsWith(PLUGIN_MODULE_NAME) || // allow imported documents
7431
- importedUris.some((importedUri) => import_langium8.UriUtils.equals(des.documentUri, importedUri))
7646
+ importedUris.some((importedUri) => import_langium9.UriUtils.equals(des.documentUri, importedUri))
7432
7647
  ));
7433
- return new import_langium8.StreamScope(importedElements);
7648
+ return new import_langium9.StreamScope(importedElements);
7434
7649
  }
7435
7650
  getScope(context) {
7436
7651
  if (isMemberAccessExpr(context.container) && context.container.operand && context.property === "member") {
@@ -7450,31 +7665,31 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7450
7665
  const node = context.container;
7451
7666
  const allowTypeDefScope = (
7452
7667
  // isAuthOrAuthMemberAccess(node.operand) ||
7453
- !!import_langium8.AstUtils.getContainerOfType(node, isTypeDef)
7668
+ !!import_langium9.AstUtils.getContainerOfType(node, isTypeDef)
7454
7669
  );
7455
7670
  return (0, import_ts_pattern3.match)(node.operand).when(isReferenceExpr, (operand) => {
7456
7671
  const ref = operand.target.ref;
7457
7672
  if (isDataField(ref)) {
7458
7673
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7459
7674
  }
7460
- return import_langium8.EMPTY_SCOPE;
7675
+ return import_langium9.EMPTY_SCOPE;
7461
7676
  }).when(isMemberAccessExpr, (operand) => {
7462
7677
  const ref = operand.member.ref;
7463
7678
  if (isDataField(ref) && !ref.type.array) {
7464
7679
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7465
7680
  }
7466
- return import_langium8.EMPTY_SCOPE;
7681
+ return import_langium9.EMPTY_SCOPE;
7467
7682
  }).when(isThisExpr, () => {
7468
7683
  return this.createScopeForContainingModel(node, globalScope);
7469
7684
  }).when(isInvocationExpr, (operand) => {
7470
7685
  if (isAuthInvocation(operand)) {
7471
7686
  return this.createScopeForAuth(node, globalScope);
7472
7687
  }
7473
- if (isFutureInvocation(operand)) {
7688
+ if (isBeforeInvocation(operand)) {
7474
7689
  return this.createScopeForContainingModel(node, globalScope);
7475
7690
  }
7476
- return import_langium8.EMPTY_SCOPE;
7477
- }).otherwise(() => import_langium8.EMPTY_SCOPE);
7691
+ return import_langium9.EMPTY_SCOPE;
7692
+ }).otherwise(() => import_langium9.EMPTY_SCOPE);
7478
7693
  }
7479
7694
  getCollectionPredicateScope(context, collectionPredicate) {
7480
7695
  const referenceType = this.reflection.getReferenceType(context);
@@ -7486,30 +7701,30 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7486
7701
  if (isDataField(ref)) {
7487
7702
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7488
7703
  }
7489
- return import_langium8.EMPTY_SCOPE;
7704
+ return import_langium9.EMPTY_SCOPE;
7490
7705
  }).when(isMemberAccessExpr, (expr) => {
7491
7706
  const ref = expr.member.ref;
7492
7707
  if (isDataField(ref)) {
7493
7708
  return this.createScopeForContainer(ref.type.reference?.ref, globalScope, allowTypeDefScope);
7494
7709
  }
7495
- return import_langium8.EMPTY_SCOPE;
7710
+ return import_langium9.EMPTY_SCOPE;
7496
7711
  }).when(isInvocationExpr, (expr) => {
7497
7712
  const returnTypeDecl = expr.function.ref?.returnType.reference?.ref;
7498
7713
  if (isDataModel(returnTypeDecl)) {
7499
7714
  return this.createScopeForContainer(returnTypeDecl, globalScope, allowTypeDefScope);
7500
7715
  } else {
7501
- return import_langium8.EMPTY_SCOPE;
7716
+ return import_langium9.EMPTY_SCOPE;
7502
7717
  }
7503
7718
  }).when(isAuthInvocation, (expr) => {
7504
7719
  return this.createScopeForAuth(expr, globalScope);
7505
- }).otherwise(() => import_langium8.EMPTY_SCOPE);
7720
+ }).otherwise(() => import_langium9.EMPTY_SCOPE);
7506
7721
  }
7507
7722
  createScopeForContainingModel(node, globalScope) {
7508
- const model = import_langium8.AstUtils.getContainerOfType(node, isDataModel);
7723
+ const model = import_langium9.AstUtils.getContainerOfType(node, isDataModel);
7509
7724
  if (model) {
7510
7725
  return this.createScopeForContainer(model, globalScope);
7511
7726
  } else {
7512
- return import_langium8.EMPTY_SCOPE;
7727
+ return import_langium9.EMPTY_SCOPE;
7513
7728
  }
7514
7729
  }
7515
7730
  createScopeForContainer(node, globalScope, includeTypeDefScope = false) {
@@ -7518,16 +7733,16 @@ var ZModelScopeProvider = class extends import_langium8.DefaultScopeProvider {
7518
7733
  } else if (includeTypeDefScope && isTypeDef(node)) {
7519
7734
  return this.createScopeForNodes(node.fields, globalScope);
7520
7735
  } else {
7521
- return import_langium8.EMPTY_SCOPE;
7736
+ return import_langium9.EMPTY_SCOPE;
7522
7737
  }
7523
7738
  }
7524
7739
  createScopeForAuth(node, globalScope) {
7525
- const decls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.services.shared.workspace.LangiumDocuments, import_langium8.AstUtils.getContainerOfType(node, isDataModel));
7740
+ const decls = getAllLoadedAndReachableDataModelsAndTypeDefs(this.services.shared.workspace.LangiumDocuments, import_langium9.AstUtils.getContainerOfType(node, isDataModel));
7526
7741
  const authDecl = getAuthDecl(decls);
7527
7742
  if (authDecl) {
7528
7743
  return this.createScopeForContainer(authDecl, globalScope, true);
7529
7744
  } else {
7530
- return import_langium8.EMPTY_SCOPE;
7745
+ return import_langium9.EMPTY_SCOPE;
7531
7746
  }
7532
7747
  }
7533
7748
  };
@@ -7544,12 +7759,12 @@ function getCollectionPredicateContext(node) {
7544
7759
  __name(getCollectionPredicateContext, "getCollectionPredicateContext");
7545
7760
 
7546
7761
  // src/zmodel-workspace-manager.ts
7547
- var import_langium9 = require("langium");
7762
+ var import_langium10 = require("langium");
7548
7763
  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 {
7764
+ var import_node_path2 = __toESM(require("path"), 1);
7765
+ var import_node_url2 = require("url");
7766
+ var import_meta2 = {};
7767
+ var ZModelWorkspaceManager = class extends import_langium10.DefaultWorkspaceManager {
7553
7768
  static {
7554
7769
  __name(this, "ZModelWorkspaceManager");
7555
7770
  }
@@ -7570,8 +7785,8 @@ var ZModelWorkspaceManager = class extends import_langium9.DefaultWorkspaceManag
7570
7785
  folderPath
7571
7786
  ]
7572
7787
  });
7573
- const languagePackageDir = import_node_path.default.dirname(languagePackagePath);
7574
- const candidateStdlibPath = import_node_path.default.join(languagePackageDir, "res", STD_LIB_MODULE_NAME);
7788
+ const languagePackageDir = import_node_path2.default.dirname(languagePackagePath);
7789
+ const candidateStdlibPath = import_node_path2.default.join(languagePackageDir, "res", STD_LIB_MODULE_NAME);
7575
7790
  if (import_node_fs2.default.existsSync(candidateStdlibPath)) {
7576
7791
  installedStdlibPath = candidateStdlibPath;
7577
7792
  console.log(`Found installed zenstack package stdlib at: ${installedStdlibPath}`);
@@ -7584,73 +7799,12 @@ var ZModelWorkspaceManager = class extends import_langium9.DefaultWorkspaceManag
7584
7799
  if (installedStdlibPath) {
7585
7800
  stdLibPath = installedStdlibPath;
7586
7801
  } 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);
7802
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path2.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
7803
+ stdLibPath = import_node_path2.default.join(_dirname, "../res", STD_LIB_MODULE_NAME);
7589
7804
  console.log(`Using bundled stdlib in extension:`, stdLibPath);
7590
7805
  }
7591
- const stdlib = await this.documentFactory.fromUri(import_langium9.URI.file(stdLibPath));
7806
+ const stdlib = await this.documentFactory.fromUri(import_langium10.URI.file(stdLibPath));
7592
7807
  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
7808
  }
7655
7809
  };
7656
7810
 
@@ -7667,12 +7821,13 @@ var ZModelLanguageModule = {
7667
7821
  };
7668
7822
  var ZModelSharedModule = {
7669
7823
  workspace: {
7824
+ DocumentBuilder: /* @__PURE__ */ __name((services) => new ZModelDocumentBuilder(services), "DocumentBuilder"),
7670
7825
  WorkspaceManager: /* @__PURE__ */ __name((services) => new ZModelWorkspaceManager(services), "WorkspaceManager")
7671
7826
  }
7672
7827
  };
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)({
7828
+ function createZModelLanguageServices(context, logToConsole = false) {
7829
+ const shared = (0, import_langium11.inject)((0, import_lsp.createDefaultSharedModule)(context), ZModelGeneratedSharedModule, ZModelSharedModule);
7830
+ const ZModelLanguage = (0, import_langium11.inject)((0, import_lsp.createDefaultModule)({
7676
7831
  shared
7677
7832
  }), ZModelGeneratedModule, ZModelLanguageModule);
7678
7833
  shared.ServiceRegistry.register(ZModelLanguage);
@@ -7680,31 +7835,39 @@ function createZModelLanguageServices(context) {
7680
7835
  if (!context.connection) {
7681
7836
  shared.workspace.ConfigurationProvider.initialized({});
7682
7837
  }
7838
+ shared.workspace.DocumentBuilder.onBuildPhase(import_langium11.DocumentState.Parsed, async (documents) => {
7839
+ for (const doc of documents) {
7840
+ if (doc.parseResult.lexerErrors.length > 0 || doc.parseResult.parserErrors.length > 0) {
7841
+ continue;
7842
+ }
7843
+ const schemaPath = (0, import_node_url3.fileURLToPath)(doc.uri.toString());
7844
+ const pluginSchemas = getPluginDocuments(doc.parseResult.value, schemaPath);
7845
+ for (const plugin of pluginSchemas) {
7846
+ const pluginDoc = await shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium11.URI.file(import_node_path3.default.resolve(plugin)));
7847
+ shared.workspace.IndexManager.updateContent(pluginDoc);
7848
+ if (logToConsole) {
7849
+ console.log(`Loaded plugin model: ${plugin}`);
7850
+ }
7851
+ }
7852
+ }
7853
+ });
7683
7854
  return {
7684
7855
  shared,
7685
7856
  ZModelLanguage
7686
7857
  };
7687
7858
  }
7688
7859
  __name(createZModelLanguageServices, "createZModelLanguageServices");
7689
-
7690
- // src/index.ts
7691
- var import_meta2 = {};
7692
- function createZModelServices() {
7693
- return createZModelLanguageServices(import_node.NodeFileSystem);
7860
+ function createZModelServices(logToConsole = false) {
7861
+ return createZModelLanguageServices(import_node.NodeFileSystem, logToConsole);
7694
7862
  }
7695
7863
  __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();
7864
+
7865
+ // src/document.ts
7866
+ var import_meta3 = {};
7867
+ async function loadDocument(fileName, additionalModelFiles = []) {
7868
+ const { ZModelLanguage: services } = createZModelServices(false);
7706
7869
  const extensions = services.LanguageMetaData.fileExtensions;
7707
- if (!extensions.includes(import_node_path2.default.extname(fileName))) {
7870
+ if (!extensions.includes(import_node_path4.default.extname(fileName))) {
7708
7871
  return {
7709
7872
  success: false,
7710
7873
  errors: [
@@ -7722,23 +7885,27 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7722
7885
  warnings: []
7723
7886
  };
7724
7887
  }
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)))));
7888
+ const _dirname = typeof __dirname !== "undefined" ? __dirname : import_node_path4.default.dirname((0, import_node_url4.fileURLToPath)(import_meta3.url));
7889
+ 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
7890
  const langiumDocuments = services.shared.workspace.LangiumDocuments;
7729
- const document = await langiumDocuments.getOrCreateDocument(import_langium11.URI.file(import_node_path2.default.resolve(fileName)));
7891
+ const document = await langiumDocuments.getOrCreateDocument(import_langium12.URI.file(import_node_path4.default.resolve(fileName)));
7730
7892
  const importedURIs = await loadImports(document, langiumDocuments);
7731
7893
  const importedDocuments = [];
7732
7894
  for (const uri of importedURIs) {
7733
7895
  importedDocuments.push(await langiumDocuments.getOrCreateDocument(uri));
7734
7896
  }
7897
+ const additionalDocs = await Promise.all(additionalModelFiles.map((file) => services.shared.workspace.LangiumDocuments.getOrCreateDocument(import_langium12.URI.file(import_node_path4.default.resolve(file)))));
7735
7898
  await services.shared.workspace.DocumentBuilder.build([
7736
7899
  stdLib,
7737
- ...pluginDocs,
7900
+ ...additionalDocs,
7738
7901
  document,
7739
7902
  ...importedDocuments
7740
7903
  ], {
7741
- validation: true
7904
+ validation: {
7905
+ stopAfterLexingErrors: true,
7906
+ stopAfterParsingErrors: true,
7907
+ stopAfterLinkingErrors: true
7908
+ }
7742
7909
  });
7743
7910
  const diagnostics = langiumDocuments.all.flatMap((doc) => (doc.diagnostics ?? []).map((diag) => ({
7744
7911
  doc,
@@ -7748,7 +7915,7 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7748
7915
  const warnings = [];
7749
7916
  if (diagnostics.length > 0) {
7750
7917
  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}`;
7918
+ 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
7919
  if (diag.severity === 1) {
7753
7920
  errors.push(message);
7754
7921
  } else {
@@ -7797,7 +7964,7 @@ async function loadImports(document, documents, uris = /* @__PURE__ */ new Set()
7797
7964
  }
7798
7965
  }
7799
7966
  }
7800
- return Array.from(uris).filter((x) => uriString != x).map((e) => import_langium11.URI.parse(e));
7967
+ return Array.from(uris).filter((x) => uriString != x).map((e) => import_langium12.URI.parse(e));
7801
7968
  }
7802
7969
  __name(loadImports, "loadImports");
7803
7970
  function mergeImportsDeclarations(documents, model) {
@@ -7814,13 +7981,13 @@ function linkContentToContainer(node) {
7814
7981
  if (!name.startsWith("$")) {
7815
7982
  if (Array.isArray(value)) {
7816
7983
  value.forEach((item, index) => {
7817
- if ((0, import_langium11.isAstNode)(item)) {
7984
+ if ((0, import_langium12.isAstNode)(item)) {
7818
7985
  item.$container = node;
7819
7986
  item.$containerProperty = name;
7820
7987
  item.$containerIndex = index;
7821
7988
  }
7822
7989
  });
7823
- } else if ((0, import_langium11.isAstNode)(value)) {
7990
+ } else if ((0, import_langium12.isAstNode)(value)) {
7824
7991
  value.$container = node;
7825
7992
  value.$containerProperty = name;
7826
7993
  }
@@ -7848,7 +8015,6 @@ function validationAfterImportMerge(model) {
7848
8015
  __name(validationAfterImportMerge, "validationAfterImportMerge");
7849
8016
  // Annotate the CommonJS export names for ESM import in node:
7850
8017
  0 && (module.exports = {
7851
- DocumentLoadError,
7852
8018
  ZModelLanguageMetaData,
7853
8019
  ZModelLanguageModule,
7854
8020
  ZModelSharedModule,