@zenstackhq/language 3.0.0-beta.6 → 3.0.0-beta.8

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.d.cts CHANGED
@@ -21,7 +21,6 @@ declare const ZModelLanguageMetaData: {
21
21
  declare class ZModelValidator {
22
22
  protected readonly services: ZModelServices;
23
23
  constructor(services: ZModelServices);
24
- private shouldCheck;
25
24
  checkModel(node: Model, accept: ValidationAcceptor): void;
26
25
  checkDataSource(node: DataSource, accept: ValidationAcceptor): void;
27
26
  checkDataModel(node: DataModel, accept: ValidationAcceptor): void;
package/dist/index.d.ts CHANGED
@@ -21,7 +21,6 @@ declare const ZModelLanguageMetaData: {
21
21
  declare class ZModelValidator {
22
22
  protected readonly services: ZModelServices;
23
23
  constructor(services: ZModelServices);
24
- private shouldCheck;
25
24
  checkModel(node: Model, accept: ValidationAcceptor): void;
26
25
  checkDataSource(node: DataSource, accept: ValidationAcceptor): void;
27
26
  checkDataModel(node: DataModel, accept: ValidationAcceptor): void;
package/dist/index.js CHANGED
@@ -5109,7 +5109,6 @@ import { AstUtils as AstUtils2 } from "langium";
5109
5109
  import pluralize from "pluralize";
5110
5110
 
5111
5111
  // src/utils.ts
5112
- import { invariant } from "@zenstackhq/common-helpers";
5113
5112
  import { AstUtils, URI } from "langium";
5114
5113
  import fs from "fs";
5115
5114
  import path from "path";
@@ -5192,10 +5191,6 @@ function isRelationshipField(field) {
5192
5191
  return isDataModel(field.type.reference?.ref);
5193
5192
  }
5194
5193
  __name(isRelationshipField, "isRelationshipField");
5195
- function isFutureExpr(node) {
5196
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5197
- }
5198
- __name(isFutureExpr, "isFutureExpr");
5199
5194
  function isDelegateModel(node) {
5200
5195
  return isDataModel(node) && hasAttribute(node, "@@delegate");
5201
5196
  }
@@ -5214,7 +5209,7 @@ function getRecursiveBases(decl, includeDelegate = true, seen = /* @__PURE__ */
5214
5209
  }
5215
5210
  seen.add(decl);
5216
5211
  decl.mixins.forEach((mixin) => {
5217
- const baseDecl = mixin.ref;
5212
+ const baseDecl = decl.$container.declarations.find((d) => isTypeDef(d) && d.name === mixin.$refText);
5218
5213
  if (baseDecl) {
5219
5214
  if (!includeDelegate && isDelegateModel(baseDecl)) {
5220
5215
  return;
@@ -5431,10 +5426,10 @@ function getAuthDecl(decls) {
5431
5426
  return authModel;
5432
5427
  }
5433
5428
  __name(getAuthDecl, "getAuthDecl");
5434
- function isFutureInvocation(node) {
5435
- return isInvocationExpr(node) && node.function.ref?.name === "future" && isFromStdlib(node.function.ref);
5429
+ function isBeforeInvocation(node) {
5430
+ return isInvocationExpr(node) && node.function.ref?.name === "before" && isFromStdlib(node.function.ref);
5436
5431
  }
5437
- __name(isFutureInvocation, "isFutureInvocation");
5432
+ __name(isBeforeInvocation, "isBeforeInvocation");
5438
5433
  function isCollectionPredicate(node) {
5439
5434
  return isBinaryExpr(node) && [
5440
5435
  "?",
@@ -5489,12 +5484,14 @@ function getAllFields(decl, includeIgnored = false, seen = /* @__PURE__ */ new S
5489
5484
  seen.add(decl);
5490
5485
  const fields = [];
5491
5486
  for (const mixin of decl.mixins) {
5492
- invariant(mixin.ref, `Mixin ${mixin.$refText} is not resolved`);
5493
- fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5487
+ if (mixin.ref) {
5488
+ fields.push(...getAllFields(mixin.ref, includeIgnored, seen));
5489
+ }
5494
5490
  }
5495
5491
  if (isDataModel(decl) && decl.baseModel) {
5496
- invariant(decl.baseModel.ref, `Base model ${decl.baseModel.$refText} is not resolved`);
5497
- fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
5492
+ if (decl.baseModel.ref) {
5493
+ fields.push(...getAllFields(decl.baseModel.ref, includeIgnored, seen));
5494
+ }
5498
5495
  }
5499
5496
  fields.push(...decl.fields.filter((f) => includeIgnored || !hasAttribute(f, "@ignore")));
5500
5497
  return fields;
@@ -5507,12 +5504,14 @@ function getAllAttributes(decl, seen = /* @__PURE__ */ new Set()) {
5507
5504
  seen.add(decl);
5508
5505
  const attributes = [];
5509
5506
  for (const mixin of decl.mixins) {
5510
- invariant(mixin.ref, `Mixin ${mixin.$refText} is not resolved`);
5511
- attributes.push(...getAllAttributes(mixin.ref, seen));
5507
+ if (mixin.ref) {
5508
+ attributes.push(...getAllAttributes(mixin.ref, seen));
5509
+ }
5512
5510
  }
5513
5511
  if (isDataModel(decl) && decl.baseModel) {
5514
- invariant(decl.baseModel.ref, `Base model ${decl.baseModel.$refText} is not resolved`);
5515
- attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
5512
+ if (decl.baseModel.ref) {
5513
+ attributes.push(...getAllAttributes(decl.baseModel.ref, seen));
5514
+ }
5516
5515
  }
5517
5516
  attributes.push(...decl.attributes);
5518
5517
  return attributes;
@@ -5662,12 +5661,21 @@ var AttributeApplicationValidator = class {
5662
5661
  "create",
5663
5662
  "read",
5664
5663
  "update",
5664
+ "post-update",
5665
5665
  "delete",
5666
5666
  "all"
5667
5667
  ], attr, accept);
5668
5668
  if ((kind === "create" || kind === "all") && attr.args[1]?.value) {
5669
5669
  this.rejectNonOwnedRelationInExpression(attr.args[1].value, accept);
5670
5670
  }
5671
+ if (kind !== "post-update" && attr.args[1]?.value) {
5672
+ const beforeCall = AstUtils2.streamAst(attr.args[1]?.value).find(isBeforeInvocation);
5673
+ if (beforeCall) {
5674
+ accept("error", `"before()" is only allowed in "post-update" policy rules`, {
5675
+ node: beforeCall
5676
+ });
5677
+ }
5678
+ }
5671
5679
  }
5672
5680
  rejectNonOwnedRelationInExpression(expr, accept) {
5673
5681
  const contextModel = AstUtils2.getContainerOfType(expr, isDataModel);
@@ -5722,8 +5730,8 @@ var AttributeApplicationValidator = class {
5722
5730
  "all"
5723
5731
  ], attr, accept);
5724
5732
  const expr = attr.args[1]?.value;
5725
- if (expr && AstUtils2.streamAst(expr).some((node) => isFutureExpr(node))) {
5726
- accept("error", `"future()" is not allowed in field-level policy rules`, {
5733
+ if (expr && AstUtils2.streamAst(expr).some((node) => isBeforeInvocation(node))) {
5734
+ accept("error", `"before()" is not allowed in field-level policy rules`, {
5727
5735
  node: expr
5728
5736
  });
5729
5737
  }
@@ -5961,7 +5969,7 @@ var AttributeValidator = class {
5961
5969
  };
5962
5970
 
5963
5971
  // src/validators/datamodel-validator.ts
5964
- import { invariant as invariant2 } from "@zenstackhq/common-helpers";
5972
+ import { invariant } from "@zenstackhq/common-helpers";
5965
5973
  import { AstUtils as AstUtils3 } from "langium";
5966
5974
 
5967
5975
  // src/validators/common.ts
@@ -6332,7 +6340,7 @@ var DataModelValidator = class {
6332
6340
  if (!model.baseModel) {
6333
6341
  return;
6334
6342
  }
6335
- invariant2(model.baseModel.ref, "baseModel must be resolved");
6343
+ invariant(model.baseModel.ref, "baseModel must be resolved");
6336
6344
  if (!isDelegateModel(model.baseModel.ref)) {
6337
6345
  accept("error", `Model ${model.baseModel.$refText} cannot be extended because it's not a delegate model`, {
6338
6346
  node: model,
@@ -6354,7 +6362,7 @@ var DataModelValidator = class {
6354
6362
  }
6355
6363
  seen.push(current);
6356
6364
  if (current.baseModel) {
6357
- invariant2(current.baseModel.ref, "baseModel must be resolved");
6365
+ invariant(current.baseModel.ref, "baseModel must be resolved");
6358
6366
  todo.push(current.baseModel.ref);
6359
6367
  }
6360
6368
  }
@@ -6484,11 +6492,21 @@ var ExpressionValidator = class {
6484
6492
  }
6485
6493
  }
6486
6494
  switch (expr.$type) {
6495
+ case "MemberAccessExpr":
6496
+ this.validateMemberAccessExpr(expr, accept);
6497
+ break;
6487
6498
  case "BinaryExpr":
6488
6499
  this.validateBinaryExpr(expr, accept);
6489
6500
  break;
6490
6501
  }
6491
6502
  }
6503
+ validateMemberAccessExpr(expr, accept) {
6504
+ if (isBeforeInvocation(expr.operand) && isDataModel(expr.$resolvedType?.decl)) {
6505
+ accept("error", "relation fields cannot be accessed from `before()`", {
6506
+ node: expr
6507
+ });
6508
+ }
6509
+ }
6492
6510
  validateBinaryExpr(expr, accept) {
6493
6511
  switch (expr.operator) {
6494
6512
  case "in": {
@@ -6976,49 +6994,66 @@ var ZModelValidator = class {
6976
6994
  constructor(services) {
6977
6995
  this.services = services;
6978
6996
  }
6979
- shouldCheck(node) {
6980
- let doc;
6981
- let currNode = node;
6982
- while (currNode) {
6983
- if (currNode.$document) {
6984
- doc = currNode.$document;
6985
- break;
6986
- }
6987
- currNode = currNode.$container;
6988
- }
6989
- return doc?.parseResult.lexerErrors.length === 0 && doc?.parseResult.parserErrors.length === 0;
6990
- }
6991
6997
  checkModel(node, accept) {
6992
- this.shouldCheck(node) && new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
6998
+ new SchemaValidator(this.services.shared.workspace.LangiumDocuments).validate(node, accept);
6993
6999
  }
6994
7000
  checkDataSource(node, accept) {
6995
- this.shouldCheck(node) && new DataSourceValidator().validate(node, accept);
7001
+ new DataSourceValidator().validate(node, accept);
6996
7002
  }
6997
7003
  checkDataModel(node, accept) {
6998
- this.shouldCheck(node) && new DataModelValidator().validate(node, accept);
7004
+ new DataModelValidator().validate(node, accept);
6999
7005
  }
7000
7006
  checkTypeDef(node, accept) {
7001
- this.shouldCheck(node) && new TypeDefValidator().validate(node, accept);
7007
+ new TypeDefValidator().validate(node, accept);
7002
7008
  }
7003
7009
  checkEnum(node, accept) {
7004
- this.shouldCheck(node) && new EnumValidator().validate(node, accept);
7010
+ new EnumValidator().validate(node, accept);
7005
7011
  }
7006
7012
  checkAttribute(node, accept) {
7007
- this.shouldCheck(node) && new AttributeValidator().validate(node, accept);
7013
+ new AttributeValidator().validate(node, accept);
7008
7014
  }
7009
7015
  checkExpression(node, accept) {
7010
- this.shouldCheck(node) && new ExpressionValidator().validate(node, accept);
7016
+ new ExpressionValidator().validate(node, accept);
7011
7017
  }
7012
7018
  checkFunctionInvocation(node, accept) {
7013
- this.shouldCheck(node) && new FunctionInvocationValidator().validate(node, accept);
7019
+ new FunctionInvocationValidator().validate(node, accept);
7014
7020
  }
7015
7021
  checkFunctionDecl(node, accept) {
7016
- this.shouldCheck(node) && new FunctionDeclValidator().validate(node, accept);
7022
+ new FunctionDeclValidator().validate(node, accept);
7023
+ }
7024
+ };
7025
+
7026
+ // src/zmodel-document-builder.ts
7027
+ import { DefaultDocumentBuilder } from "langium";
7028
+ var ZModelDocumentBuilder = class extends DefaultDocumentBuilder {
7029
+ static {
7030
+ __name(this, "ZModelDocumentBuilder");
7031
+ }
7032
+ constructor(services) {
7033
+ super(services);
7034
+ let validationOptions = this.updateBuildOptions.validation;
7035
+ const stopFlags = {
7036
+ stopAfterLinkingErrors: true,
7037
+ stopAfterLexingErrors: true,
7038
+ stopAfterParsingErrors: true
7039
+ };
7040
+ if (validationOptions === true) {
7041
+ validationOptions = stopFlags;
7042
+ } else if (typeof validationOptions === "object") {
7043
+ validationOptions = {
7044
+ ...validationOptions,
7045
+ ...stopFlags
7046
+ };
7047
+ }
7048
+ this.updateBuildOptions = {
7049
+ ...this.updateBuildOptions,
7050
+ validation: validationOptions
7051
+ };
7017
7052
  }
7018
7053
  };
7019
7054
 
7020
7055
  // src/zmodel-linker.ts
7021
- import { AstUtils as AstUtils6, Cancellation, DefaultLinker, DocumentState, interruptAndCheck, isReference } from "langium";
7056
+ import { AstUtils as AstUtils6, Cancellation, DefaultLinker, DocumentState, interruptAndCheck } from "langium";
7022
7057
  import { match as match2 } from "ts-pattern";
7023
7058
  var ZModelLinker = class extends DefaultLinker {
7024
7059
  static {
@@ -7040,21 +7075,19 @@ var ZModelLinker = class extends DefaultLinker {
7040
7075
  }
7041
7076
  document.state = DocumentState.Linked;
7042
7077
  }
7043
- linkReference(container, property, document, extraScopes) {
7044
- if (this.resolveFromScopeProviders(container, property, document, extraScopes)) {
7078
+ linkReference(refInfo, document, extraScopes) {
7079
+ const defaultRef = refInfo.reference;
7080
+ if (defaultRef._ref) {
7045
7081
  return;
7046
7082
  }
7047
- const reference = container[property];
7048
- this.doLink({
7049
- reference,
7050
- container,
7051
- property
7052
- }, document);
7083
+ if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
7084
+ return;
7085
+ }
7086
+ this.doLink(refInfo, document);
7053
7087
  }
7054
7088
  //#endregion
7055
7089
  //#region Expression type resolving
7056
- resolveFromScopeProviders(node, property, document, providers) {
7057
- const reference = node[property];
7090
+ resolveFromScopeProviders(reference, document, providers) {
7058
7091
  for (const provider of providers) {
7059
7092
  const target = provider(reference.$refText);
7060
7093
  if (target) {
@@ -7183,7 +7216,11 @@ var ZModelLinker = class extends DefaultLinker {
7183
7216
  }
7184
7217
  }
7185
7218
  resolveInvocation(node, document, extraScopes) {
7186
- this.linkReference(node, "function", document, extraScopes);
7219
+ this.linkReference({
7220
+ reference: node.function,
7221
+ container: node,
7222
+ property: "function"
7223
+ }, document, extraScopes);
7187
7224
  node.args.forEach((arg) => this.resolve(arg, document, extraScopes));
7188
7225
  if (node.function.ref) {
7189
7226
  const funcDecl = node.function.ref;
@@ -7196,7 +7233,7 @@ var ZModelLinker = class extends DefaultLinker {
7196
7233
  nullable: true
7197
7234
  };
7198
7235
  }
7199
- } else if (isFutureExpr(node)) {
7236
+ } else if (isBeforeInvocation(node)) {
7200
7237
  node.$resolvedType = {
7201
7238
  decl: getContainingDataModel(node)
7202
7239
  };
@@ -7260,7 +7297,7 @@ var ZModelLinker = class extends DefaultLinker {
7260
7297
  if (isArrayExpr(node.value)) {
7261
7298
  node.value.items.forEach((item) => {
7262
7299
  if (isReferenceExpr(item)) {
7263
- const resolved2 = this.resolveFromScopeProviders(item, "target", document, [
7300
+ const resolved2 = this.resolveFromScopeProviders(item.target, document, [
7264
7301
  scopeProvider
7265
7302
  ]);
7266
7303
  if (resolved2) {
@@ -7274,7 +7311,7 @@ var ZModelLinker = class extends DefaultLinker {
7274
7311
  this.resolveToBuiltinTypeOrDecl(node.value, node.value.items[0].$resolvedType.decl, true);
7275
7312
  }
7276
7313
  } else if (isReferenceExpr(node.value)) {
7277
- const resolved2 = this.resolveFromScopeProviders(node.value, "target", document, [
7314
+ const resolved2 = this.resolveFromScopeProviders(node.value.target, document, [
7278
7315
  scopeProvider
7279
7316
  ]);
7280
7317
  if (resolved2) {
@@ -7326,13 +7363,9 @@ var ZModelLinker = class extends DefaultLinker {
7326
7363
  this.resolveDefault(node, document, scopes);
7327
7364
  }
7328
7365
  resolveDefault(node, document, extraScopes) {
7329
- for (const [property, value] of Object.entries(node)) {
7330
- if (!property.startsWith("$")) {
7331
- if (isReference(value)) {
7332
- this.linkReference(node, property, document, extraScopes);
7333
- }
7334
- }
7335
- }
7366
+ AstUtils6.streamReferences(node).forEach((ref) => {
7367
+ this.linkReference(ref, document, extraScopes);
7368
+ });
7336
7369
  for (const child of AstUtils6.streamContents(node)) {
7337
7370
  this.resolve(child, document, extraScopes);
7338
7371
  }
@@ -7473,7 +7506,7 @@ var ZModelScopeProvider = class extends DefaultScopeProvider {
7473
7506
  if (isAuthInvocation(operand)) {
7474
7507
  return this.createScopeForAuth(node, globalScope);
7475
7508
  }
7476
- if (isFutureInvocation(operand)) {
7509
+ if (isBeforeInvocation(operand)) {
7477
7510
  return this.createScopeForContainingModel(node, globalScope);
7478
7511
  }
7479
7512
  return EMPTY_SCOPE;
@@ -7669,6 +7702,7 @@ var ZModelLanguageModule = {
7669
7702
  };
7670
7703
  var ZModelSharedModule = {
7671
7704
  workspace: {
7705
+ DocumentBuilder: /* @__PURE__ */ __name((services) => new ZModelDocumentBuilder(services), "DocumentBuilder"),
7672
7706
  WorkspaceManager: /* @__PURE__ */ __name((services) => new ZModelWorkspaceManager(services), "WorkspaceManager")
7673
7707
  }
7674
7708
  };
@@ -7739,7 +7773,11 @@ async function loadDocument(fileName, pluginModelFiles = []) {
7739
7773
  document,
7740
7774
  ...importedDocuments
7741
7775
  ], {
7742
- validation: true
7776
+ validation: {
7777
+ stopAfterLexingErrors: true,
7778
+ stopAfterParsingErrors: true,
7779
+ stopAfterLinkingErrors: true
7780
+ }
7743
7781
  });
7744
7782
  const diagnostics = langiumDocuments.all.flatMap((doc) => (doc.diagnostics ?? []).map((diag) => ({
7745
7783
  doc,