@vertz/compiler 0.2.19 → 0.2.20

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.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  type DiagnosticSeverity = "error" | "warning" | "info";
2
- type DiagnosticCode = "VERTZ_SCHEMA_NAMING" | "VERTZ_SCHEMA_PLACEMENT" | "VERTZ_SCHEMA_EXECUTION" | "VERTZ_SCHEMA_MISSING_ID" | "VERTZ_SCHEMA_DYNAMIC_NAME" | "VERTZ_MODULE_CIRCULAR" | "VERTZ_MODULE_EXPORT_INVALID" | "VERTZ_MODULE_IMPORT_MISSING" | "VERTZ_MODULE_DUPLICATE_NAME" | "VERTZ_MODULE_DYNAMIC_NAME" | "VERTZ_MODULE_OPTIONS_INVALID" | "VERTZ_MODULE_WRONG_OWNERSHIP" | "VERTZ_SERVICE_INJECT_MISSING" | "VERTZ_SERVICE_UNUSED" | "VERTZ_SERVICE_DYNAMIC_NAME" | "VERTZ_ENV_MISSING_DEFAULT" | "VERTZ_ENV_DUPLICATE" | "VERTZ_ENV_DYNAMIC_CONFIG" | "VERTZ_MW_MISSING_NAME" | "VERTZ_MW_MISSING_HANDLER" | "VERTZ_MW_DYNAMIC_NAME" | "VERTZ_MW_NON_OBJECT_CONFIG" | "VERTZ_MW_REQUIRES_UNSATISFIED" | "VERTZ_MW_PROVIDES_COLLISION" | "VERTZ_MW_ORDER_INVALID" | "VERTZ_RT_UNKNOWN_MODULE_DEF" | "VERTZ_RT_DYNAMIC_PATH" | "VERTZ_RT_MISSING_HANDLER" | "VERTZ_RT_MISSING_PREFIX" | "VERTZ_RT_DYNAMIC_CONFIG" | "VERTZ_RT_INVALID_PATH" | "VERTZ_ROUTE_DUPLICATE" | "VERTZ_ROUTE_PARAM_MISMATCH" | "VERTZ_ROUTE_MISSING_RESPONSE" | "VERTZ_APP_MISSING" | "VERTZ_APP_NOT_FOUND" | "VERTZ_APP_DUPLICATE" | "VERTZ_APP_BASEPATH_FORMAT" | "VERTZ_APP_INLINE_MODULE" | "VERTZ_DEP_CYCLE" | "VERTZ_DEP_CIRCULAR" | "VERTZ_DEP_UNRESOLVED_INJECT" | "VERTZ_DEP_INIT_ORDER" | "VERTZ_CTX_COLLISION" | "VERTZ_DEAD_CODE" | "ENTITY_MISSING_ARGS" | "ENTITY_NON_LITERAL_NAME" | "ENTITY_INVALID_NAME" | "ENTITY_DUPLICATE_NAME" | "ENTITY_CONFIG_NOT_OBJECT" | "ENTITY_MISSING_MODEL" | "ENTITY_MODEL_UNRESOLVABLE" | "ENTITY_ACTION_NAME_COLLISION" | "ENTITY_ACTION_MISSING_SCHEMA" | "ENTITY_ACTION_INVALID_METHOD" | "ENTITY_UNKNOWN_ACCESS_OP" | "ENTITY_UNRESOLVED_IMPORT" | "ENTITY_ROUTE_COLLISION" | "ENTITY_NO_ROUTES" | "ENTITY_MODEL_NOT_REGISTERED" | "ENTITY_EXPOSE_EMPTY_SELECT" | "ACCESS_MULTIPLE_DEFINITIONS" | "ACCESS_NON_LITERAL_KEY" | "ACCESS_NON_LITERAL_ROLE" | "ACCESS_DUPLICATE_ENTITLEMENT" | "ACCESS_WHERE_NOT_TRANSLATABLE";
2
+ type DiagnosticCode = "VERTZ_SCHEMA_NAMING" | "VERTZ_SCHEMA_PLACEMENT" | "VERTZ_SCHEMA_EXECUTION" | "VERTZ_SCHEMA_MISSING_ID" | "VERTZ_SCHEMA_DYNAMIC_NAME" | "VERTZ_MODULE_CIRCULAR" | "VERTZ_MODULE_EXPORT_INVALID" | "VERTZ_MODULE_IMPORT_MISSING" | "VERTZ_MODULE_DUPLICATE_NAME" | "VERTZ_MODULE_DYNAMIC_NAME" | "VERTZ_MODULE_OPTIONS_INVALID" | "VERTZ_MODULE_WRONG_OWNERSHIP" | "VERTZ_SERVICE_INJECT_MISSING" | "VERTZ_SERVICE_UNUSED" | "VERTZ_SERVICE_DYNAMIC_NAME" | "VERTZ_ENV_MISSING_DEFAULT" | "VERTZ_ENV_DUPLICATE" | "VERTZ_ENV_DYNAMIC_CONFIG" | "VERTZ_MW_MISSING_NAME" | "VERTZ_MW_MISSING_HANDLER" | "VERTZ_MW_DYNAMIC_NAME" | "VERTZ_MW_NON_OBJECT_CONFIG" | "VERTZ_MW_REQUIRES_UNSATISFIED" | "VERTZ_MW_PROVIDES_COLLISION" | "VERTZ_MW_ORDER_INVALID" | "VERTZ_RT_UNKNOWN_MODULE_DEF" | "VERTZ_RT_DYNAMIC_PATH" | "VERTZ_RT_MISSING_HANDLER" | "VERTZ_RT_MISSING_PREFIX" | "VERTZ_RT_DYNAMIC_CONFIG" | "VERTZ_RT_INVALID_PATH" | "VERTZ_ROUTE_DUPLICATE" | "VERTZ_ROUTE_PARAM_MISMATCH" | "VERTZ_ROUTE_MISSING_RESPONSE" | "VERTZ_APP_MISSING" | "VERTZ_APP_NOT_FOUND" | "VERTZ_APP_DUPLICATE" | "VERTZ_APP_BASEPATH_FORMAT" | "VERTZ_APP_INLINE_MODULE" | "VERTZ_DEP_CYCLE" | "VERTZ_DEP_CIRCULAR" | "VERTZ_DEP_UNRESOLVED_INJECT" | "VERTZ_DEP_INIT_ORDER" | "VERTZ_CTX_COLLISION" | "VERTZ_DEAD_CODE" | "ENTITY_MISSING_ARGS" | "ENTITY_NON_LITERAL_NAME" | "ENTITY_INVALID_NAME" | "ENTITY_DUPLICATE_NAME" | "ENTITY_CONFIG_NOT_OBJECT" | "ENTITY_MISSING_MODEL" | "ENTITY_MODEL_UNRESOLVABLE" | "ENTITY_ACTION_NAME_COLLISION" | "ENTITY_ACTION_MISSING_SCHEMA" | "ENTITY_ACTION_INVALID_METHOD" | "ENTITY_UNKNOWN_ACCESS_OP" | "ENTITY_UNRESOLVED_IMPORT" | "ENTITY_ROUTE_COLLISION" | "ENTITY_NO_ROUTES" | "ENTITY_MODEL_NOT_REGISTERED" | "ENTITY_EXPOSE_EMPTY_SELECT" | "ENTITY_EXPOSE_NON_LITERAL" | "ENTITY_EXPOSE_RELATION_UNRESOLVED" | "ACCESS_MULTIPLE_DEFINITIONS" | "ACCESS_NON_LITERAL_KEY" | "ACCESS_NON_LITERAL_ROLE" | "ACCESS_DUPLICATE_ENTITLEMENT" | "ACCESS_WHERE_NOT_TRANSLATABLE";
3
3
  interface SourceContext {
4
4
  lines: {
5
5
  number: number;
@@ -440,6 +440,7 @@ declare class EntityAnalyzer extends BaseAnalyzer<EntityAnalyzerResult> {
440
440
  private extractRelations;
441
441
  private extractExpose;
442
442
  private extractExposeFields;
443
+ private checkExposeNonLiteral;
443
444
  /**
444
445
  * Extract primaryKey and hiddenFields from the model's table type.
445
446
  * Navigates ModelDef.table._columns to inspect column metadata.
@@ -451,6 +452,13 @@ declare class EntityAnalyzer extends BaseAnalyzer<EntityAnalyzerResult> {
451
452
  */
452
453
  private resolveModelRelationTypes;
453
454
  /**
455
+ * Post-processing: validate expose.include relations after entity resolution.
456
+ * Emits ENTITY_EXPOSE_RELATION_UNRESOLVED for relations whose target entity
457
+ * could not be resolved. The IR preserves the entries; the ir-adapter handles
458
+ * omission from codegen output.
459
+ */
460
+ private validateExposeRelations;
461
+ /**
454
462
  * Post-processing: resolve relation `entity` fields by matching
455
463
  * each relation's _target return type to the table type of known entities.
456
464
  */
package/dist/index.js CHANGED
@@ -985,6 +985,7 @@ class EntityAnalyzer extends BaseAnalyzer {
985
985
  }
986
986
  }
987
987
  this.resolveRelationEntities(entities, modelExprs);
988
+ this.validateExposeRelations(entities);
988
989
  return { entities };
989
990
  }
990
991
  findEntityCalls(file) {
@@ -1454,6 +1455,7 @@ class EntityAnalyzer extends BaseAnalyzer {
1454
1455
  const selectExpr = getPropertyValue(exposeExpr, "select");
1455
1456
  if (!selectExpr || !selectExpr.isKind(SyntaxKind5.ObjectLiteralExpression))
1456
1457
  return;
1458
+ this.checkExposeNonLiteral(selectExpr, "expose.select", loc);
1457
1459
  const select = this.extractExposeFields(selectExpr);
1458
1460
  if (select.length === 0) {
1459
1461
  this.addDiagnostic({
@@ -1466,6 +1468,7 @@ class EntityAnalyzer extends BaseAnalyzer {
1466
1468
  const includeExpr = getPropertyValue(exposeExpr, "include");
1467
1469
  let include;
1468
1470
  if (includeExpr?.isKind(SyntaxKind5.ObjectLiteralExpression)) {
1471
+ this.checkExposeNonLiteral(includeExpr, "expose.include", loc);
1469
1472
  include = getProperties(includeExpr).filter(({ value }) => getBooleanValue(value) !== false).map(({ name, value }) => {
1470
1473
  const boolVal = getBooleanValue(value);
1471
1474
  if (boolVal === true || !value.isKind(SyntaxKind5.ObjectLiteralExpression)) {
@@ -1491,6 +1494,19 @@ class EntityAnalyzer extends BaseAnalyzer {
1491
1494
  conditional: getBooleanValue(value) !== true
1492
1495
  }));
1493
1496
  }
1497
+ checkExposeNonLiteral(obj, context, loc) {
1498
+ for (const prop of obj.getProperties()) {
1499
+ if (prop.isKind(SyntaxKind5.SpreadAssignment) || prop.isKind(SyntaxKind5.PropertyAssignment) && prop.getNameNode().isKind(SyntaxKind5.ComputedPropertyName)) {
1500
+ this.addDiagnostic({
1501
+ code: "ENTITY_EXPOSE_NON_LITERAL",
1502
+ severity: "warning",
1503
+ message: `${context} contains non-literal properties (spread or computed) that can't be statically analyzed`,
1504
+ ...loc
1505
+ });
1506
+ return;
1507
+ }
1508
+ }
1509
+ }
1494
1510
  extractModelTableMetadata(modelExpr, modelRef) {
1495
1511
  try {
1496
1512
  const modelType = modelExpr.getType();
@@ -1561,6 +1577,26 @@ class EntityAnalyzer extends BaseAnalyzer {
1561
1577
  } catch {}
1562
1578
  return result;
1563
1579
  }
1580
+ validateExposeRelations(entities) {
1581
+ for (const entity of entities) {
1582
+ if (!entity.expose?.include)
1583
+ continue;
1584
+ const relationMap = new Map(entity.relations.map((r) => [r.name, r]));
1585
+ for (const rel of entity.expose.include) {
1586
+ const matchedRelation = relationMap.get(rel.name);
1587
+ if (!matchedRelation || !matchedRelation.entity) {
1588
+ this.addDiagnostic({
1589
+ code: "ENTITY_EXPOSE_RELATION_UNRESOLVED",
1590
+ severity: "warning",
1591
+ message: `expose.include references relation "${rel.name}" whose target entity could not be resolved`,
1592
+ file: entity.sourceFile,
1593
+ line: entity.sourceLine,
1594
+ column: entity.sourceColumn
1595
+ });
1596
+ }
1597
+ }
1598
+ }
1599
+ }
1564
1600
  resolveRelationEntities(entities, modelExprs) {
1565
1601
  try {
1566
1602
  const tableToEntity = new Map;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertz/compiler",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Vertz compiler — internal, no stability guarantee",