@finos/legend-graph 32.5.0 → 32.5.2

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.
Files changed (49) hide show
  1. package/lib/graph/metamodel/pure/dataProduct/DataProduct.d.ts +4 -3
  2. package/lib/graph/metamodel/pure/dataProduct/DataProduct.d.ts.map +1 -1
  3. package/lib/graph/metamodel/pure/dataProduct/DataProduct.js +7 -5
  4. package/lib/graph/metamodel/pure/dataProduct/DataProduct.js.map +1 -1
  5. package/lib/graph/metamodel/pure/packageableElements/relation/Accessor.d.ts +1 -0
  6. package/lib/graph/metamodel/pure/packageableElements/relation/Accessor.d.ts.map +1 -1
  7. package/lib/graph/metamodel/pure/packageableElements/relation/Accessor.js +5 -1
  8. package/lib/graph/metamodel/pure/packageableElements/relation/Accessor.js.map +1 -1
  9. package/lib/graph-manager/action/query/Query.d.ts +7 -0
  10. package/lib/graph-manager/action/query/Query.d.ts.map +1 -1
  11. package/lib/graph-manager/action/query/Query.js +7 -0
  12. package/lib/graph-manager/action/query/Query.js.map +1 -1
  13. package/lib/graph-manager/helpers/DataProductHelper.d.ts +7 -2
  14. package/lib/graph-manager/helpers/DataProductHelper.d.ts.map +1 -1
  15. package/lib/graph-manager/helpers/DataProductHelper.js +27 -2
  16. package/lib/graph-manager/helpers/DataProductHelper.js.map +1 -1
  17. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts +13 -1
  18. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts.map +1 -1
  19. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js +214 -92
  20. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js.map +1 -1
  21. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.d.ts.map +1 -1
  22. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.js +20 -2
  23. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.js.map +1 -1
  24. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.d.ts.map +1 -1
  25. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.js +7 -0
  26. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.js.map +1 -1
  27. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.d.ts +6 -1
  28. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.d.ts.map +1 -1
  29. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.js +16 -0
  30. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.js.map +1 -1
  31. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.d.ts +1 -1
  32. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.d.ts.map +1 -1
  33. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.js +6 -6
  34. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.js.map +1 -1
  35. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.d.ts.map +1 -1
  36. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js +14 -10
  37. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js.map +1 -1
  38. package/lib/package.json +1 -1
  39. package/package.json +3 -3
  40. package/src/graph/metamodel/pure/dataProduct/DataProduct.ts +13 -5
  41. package/src/graph/metamodel/pure/packageableElements/relation/Accessor.ts +6 -1
  42. package/src/graph-manager/action/query/Query.ts +9 -0
  43. package/src/graph-manager/helpers/DataProductHelper.ts +47 -4
  44. package/src/graph-manager/protocol/pure/v1/V1_PureGraphManager.ts +488 -484
  45. package/src/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.ts +22 -0
  46. package/src/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.ts +7 -0
  47. package/src/graph-manager/protocol/pure/v1/engine/query/V1_Query.ts +28 -0
  48. package/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.ts +6 -3
  49. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.ts +21 -23
@@ -51,8 +51,9 @@ import {
51
51
  type ExecutionOptions,
52
52
  type ServiceRegistrationOptions,
53
53
  } from '../../../../graph-manager/AbstractPureGraphManager.js';
54
- import type { Mapping } from '../../../../graph/metamodel/pure/packageableElements/mapping/Mapping.js';
54
+ import { Mapping } from '../../../../graph/metamodel/pure/packageableElements/mapping/Mapping.js';
55
55
  import type { Runtime } from '../../../../graph/metamodel/pure/packageableElements/runtime/Runtime.js';
56
+ import { PackageableRuntime } from '../../../../graph/metamodel/pure/packageableElements/runtime/PackageableRuntime.js';
56
57
  import type { PackageableElement } from '../../../../graph/metamodel/pure/packageableElements/PackageableElement.js';
57
58
  import {
58
59
  type SystemModel,
@@ -348,6 +349,7 @@ import { V1_UserListOwnership } from './model/packageableElements/service/V1_Ser
348
349
  import { V1_PureSingleExecution } from './model/packageableElements/service/V1_ServiceExecution.js';
349
350
  import {
350
351
  type V1_Runtime,
352
+ V1_EngineRuntime,
351
353
  V1_RuntimePointer,
352
354
  } from './model/packageableElements/runtime/V1_Runtime.js';
353
355
  import type { TestDebug } from '../../../../graph/metamodel/pure/test/result/DebugTestsResult.js';
@@ -380,9 +382,11 @@ import {
380
382
  } from '../../../action/analytics/data-product/DataProductAnalysis.js';
381
383
  import {
382
384
  DataProductAccessType,
385
+ DataProductElementScope,
383
386
  ModelAccessPointGroup,
384
387
  NativeModelAccess,
385
388
  NativeModelExecutionContext,
389
+ type DataProductElement,
386
390
  } from '../../../../graph/metamodel/pure/dataProduct/DataProduct.js';
387
391
  import { V1_MemSQLFunction } from './model/packageableElements/function/V1_MemSQLFunction.js';
388
392
  import { LineageModel } from '../../../../graph/metamodel/pure/lineage/LineageModel.js';
@@ -403,6 +407,12 @@ import { IngestDefinition } from '../../../../graph/metamodel/pure/packageableEl
403
407
  import { Database } from '../../../../graph/metamodel/pure/packageableElements/store/relational/model/Database.js';
404
408
  import { V1_createAccessorFromPackageableElement } from './helpers/V1_AccessorHelper.js';
405
409
 
410
+ /**
411
+ * Number of elements to process synchronously before yielding to the event loop.
412
+ * This avoids per-element setTimeout overhead while keeping the UI responsive.
413
+ */
414
+ const GRAPH_BUILDER_BATCH_SIZE = 100;
415
+
406
416
  class V1_PureModelContextDataIndex {
407
417
  elements: V1_PackageableElement[] = [];
408
418
  nativeElements: V1_PackageableElement[] = [];
@@ -1297,46 +1307,57 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1297
1307
  graph.allElements.map((el) => el.path),
1298
1308
  );
1299
1309
 
1300
- await Promise.all(
1301
- inputs.flatMap(async (input) => {
1302
- // create the package cache
1303
- const packageCache = new Map<string, Package>();
1304
- await Promise.all(
1305
- input.data.nativeElements.map((element) => {
1306
- return this.visitWithGraphBuilderErrorHandling(
1307
- element,
1308
- new V1_ElementFirstPassBuilder(
1309
- this.getBuilderContext(graph, input.model, element, options),
1310
- packageCache,
1311
- elementPathCache,
1312
- ),
1313
- );
1314
- }),
1315
- );
1316
- await Promise.all(
1317
- this.graphBuilderExtensions.sortedExtraElementBuilders.flatMap(
1318
- (builder) =>
1319
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1320
- (element) => {
1321
- return this.visitWithGraphBuilderErrorHandling(
1322
- element,
1323
- new V1_ElementFirstPassBuilder(
1324
- this.getBuilderContext(
1325
- graph,
1326
- input.model,
1327
- element,
1328
- options,
1329
- ),
1330
- packageCache,
1331
- elementPathCache,
1332
- ),
1333
- );
1334
- },
1335
- ),
1336
- ),
1310
+ // NOTE: We must index ALL native elements across ALL inputs before indexing
1311
+ // plugin-contributed ("other") elements. Plugin elements
1312
+ // may resolve references to native elements (e.g. Mapping, Runtime) from
1313
+ // other inputs during their first pass. If we process each input fully
1314
+ // (native + other) before moving to the next, a plugin element in input[0]
1315
+ // could fail to find a native element that only exists in input[1].
1316
+ const packageCaches = new Map<
1317
+ V1_PureGraphBuilderInput,
1318
+ Map<string, Package>
1319
+ >();
1320
+
1321
+ const createFirstPassBuilder = (
1322
+ input: V1_PureGraphBuilderInput,
1323
+ packageCache: Map<string, Package>,
1324
+ element: V1_PackageableElement,
1325
+ ): V1_ElementFirstPassBuilder =>
1326
+ new V1_ElementFirstPassBuilder(
1327
+ this.getBuilderContext(graph, input.model, element, options),
1328
+ packageCache,
1329
+ elementPathCache,
1330
+ );
1331
+
1332
+ for (const input of inputs) {
1333
+ const packageCache = new Map<string, Package>();
1334
+ packageCaches.set(input, packageCache);
1335
+
1336
+ // Phase 1: index native elements for this input
1337
+ await this.runBatchedLoop(input.data.nativeElements, (element) =>
1338
+ this.visitWithGraphBuilderErrorHandling(
1339
+ element,
1340
+ createFirstPassBuilder(input, packageCache, element),
1341
+ ),
1342
+ );
1343
+ }
1344
+
1345
+ // Phase 2: index other (plugin-contributed) elements across all inputs,
1346
+ // now that all native elements have been indexed
1347
+ for (const input of inputs) {
1348
+ const packageCache = guaranteeNonNullable(packageCaches.get(input));
1349
+
1350
+ const otherElements =
1351
+ this.graphBuilderExtensions.sortedExtraElementBuilders.flatMap(
1352
+ (builder) => input.data.otherElementsByBuilder.get(builder) ?? [],
1337
1353
  );
1338
- }),
1339
- );
1354
+ await this.runBatchedLoop(otherElements, (element) =>
1355
+ this.visitWithGraphBuilderErrorHandling(
1356
+ element,
1357
+ createFirstPassBuilder(input, packageCache, element),
1358
+ ),
1359
+ );
1360
+ }
1340
1361
  }
1341
1362
 
1342
1363
  private async buildTypes(
@@ -1345,128 +1366,78 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1345
1366
  options?: GraphBuilderOptions,
1346
1367
  ): Promise<void> {
1347
1368
  // Second pass
1348
- await Promise.all(
1349
- inputs.flatMap((input) =>
1350
- input.data.profiles.map((element) =>
1351
- this.visitWithGraphBuilderErrorHandling(
1352
- element,
1353
- new V1_ElementSecondPassBuilder(
1354
- this.getBuilderContext(graph, input.model, element, options),
1355
- ),
1356
- ),
1357
- ),
1358
- ),
1369
+ await this.processElementsInBatches(
1370
+ graph,
1371
+ inputs,
1372
+ (data) => data.profiles,
1373
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1374
+ options,
1359
1375
  );
1360
- await Promise.all(
1361
- inputs.flatMap((input) =>
1362
- input.data.classes.map((element) =>
1363
- this.visitWithGraphBuilderErrorHandling(
1364
- element,
1365
- new V1_ElementSecondPassBuilder(
1366
- this.getBuilderContext(graph, input.model, element, options),
1367
- ),
1368
- ),
1369
- ),
1370
- ),
1376
+ await this.processElementsInBatches(
1377
+ graph,
1378
+ inputs,
1379
+ (data) => data.classes,
1380
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1381
+ options,
1371
1382
  );
1372
- await Promise.all(
1373
- inputs.flatMap((input) =>
1374
- input.data.enumerations.map((element) =>
1375
- this.visitWithGraphBuilderErrorHandling(
1376
- element,
1377
- new V1_ElementSecondPassBuilder(
1378
- this.getBuilderContext(graph, input.model, element, options),
1379
- ),
1380
- ),
1381
- ),
1382
- ),
1383
+ await this.processElementsInBatches(
1384
+ graph,
1385
+ inputs,
1386
+ (data) => data.enumerations,
1387
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1388
+ options,
1383
1389
  );
1384
- await Promise.all(
1385
- inputs.flatMap((input) =>
1386
- input.data.measures.map((element) =>
1387
- this.visitWithGraphBuilderErrorHandling(
1388
- element,
1389
- new V1_ElementSecondPassBuilder(
1390
- this.getBuilderContext(graph, input.model, element, options),
1391
- ),
1392
- ),
1393
- ),
1394
- ),
1390
+ await this.processElementsInBatches(
1391
+ graph,
1392
+ inputs,
1393
+ (data) => data.measures,
1394
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1395
+ options,
1395
1396
  );
1396
- await Promise.all(
1397
- inputs.flatMap((input) =>
1398
- input.data.functions.map((element) =>
1399
- this.visitWithGraphBuilderErrorHandling(
1400
- element,
1401
- new V1_ElementSecondPassBuilder(
1402
- this.getBuilderContext(graph, input.model, element, options),
1403
- ),
1404
- ),
1405
- ),
1406
- ),
1397
+ await this.processElementsInBatches(
1398
+ graph,
1399
+ inputs,
1400
+ (data) => data.functions,
1401
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1402
+ options,
1407
1403
  );
1408
1404
  // Third pass
1409
- await Promise.all(
1410
- inputs.flatMap((input) =>
1411
- input.data.classes.map((element) =>
1412
- this.visitWithGraphBuilderErrorHandling(
1413
- element,
1414
- new V1_ElementThirdPassBuilder(
1415
- this.getBuilderContext(graph, input.model, element, options),
1416
- ),
1417
- ),
1418
- ),
1419
- ),
1405
+ await this.processElementsInBatches(
1406
+ graph,
1407
+ inputs,
1408
+ (data) => data.classes,
1409
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1410
+ options,
1420
1411
  );
1421
- await Promise.all(
1422
- inputs.flatMap((input) =>
1423
- input.data.associations.map((element) =>
1424
- this.visitWithGraphBuilderErrorHandling(
1425
- element,
1426
- new V1_ElementThirdPassBuilder(
1427
- this.getBuilderContext(graph, input.model, element, options),
1428
- ),
1429
- ),
1430
- ),
1431
- ),
1412
+ await this.processElementsInBatches(
1413
+ graph,
1414
+ inputs,
1415
+ (data) => data.associations,
1416
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1417
+ options,
1432
1418
  );
1433
1419
  // Fourth Pass
1434
- await Promise.all(
1435
- inputs.flatMap((input) =>
1436
- input.data.classes.map((element) =>
1437
- this.visitWithGraphBuilderErrorHandling(
1438
- element,
1439
- new V1_ElementFourthPassBuilder(
1440
- this.getBuilderContext(graph, input.model, element, options),
1441
- ),
1442
- ),
1443
- ),
1444
- ),
1420
+ await this.processElementsInBatches(
1421
+ graph,
1422
+ inputs,
1423
+ (data) => data.classes,
1424
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1425
+ options,
1445
1426
  );
1446
- await Promise.all(
1447
- inputs.flatMap((input) =>
1448
- input.data.associations.map((element) =>
1449
- this.visitWithGraphBuilderErrorHandling(
1450
- element,
1451
- new V1_ElementFourthPassBuilder(
1452
- this.getBuilderContext(graph, input.model, element, options),
1453
- ),
1454
- ),
1455
- ),
1456
- ),
1427
+ await this.processElementsInBatches(
1428
+ graph,
1429
+ inputs,
1430
+ (data) => data.associations,
1431
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1432
+ options,
1457
1433
  );
1458
1434
  // Fifth pass
1459
- await Promise.all(
1460
- inputs.flatMap((input) =>
1461
- input.data.classes.map((element) =>
1462
- this.visitWithGraphBuilderErrorHandling(
1463
- element,
1464
- new V1_ElementFifthPassBuilder(
1465
- this.getBuilderContext(graph, input.model, element, options),
1466
- ),
1467
- ),
1468
- ),
1469
- ),
1435
+ await this.processElementsInBatches(
1436
+ graph,
1437
+ inputs,
1438
+ (data) => data.classes,
1439
+ (ctx) => new V1_ElementFifthPassBuilder(ctx),
1440
+ options,
1470
1441
  );
1471
1442
  }
1472
1443
 
@@ -1475,17 +1446,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1475
1446
  inputs: V1_PureGraphBuilderInput[],
1476
1447
  options?: GraphBuilderOptions,
1477
1448
  ): Promise<void> {
1478
- await Promise.all(
1479
- inputs.flatMap((input) =>
1480
- input.data.functionActivators.map((element) =>
1481
- this.visitWithGraphBuilderErrorHandling(
1482
- element,
1483
- new V1_ElementSecondPassBuilder(
1484
- this.getBuilderContext(graph, input.model, element, options),
1485
- ),
1486
- ),
1487
- ),
1488
- ),
1449
+ await this.processElementsInBatches(
1450
+ graph,
1451
+ inputs,
1452
+ (data) => data.functionActivators,
1453
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1454
+ options,
1489
1455
  );
1490
1456
  }
1491
1457
 
@@ -1494,53 +1460,33 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1494
1460
  inputs: V1_PureGraphBuilderInput[],
1495
1461
  options?: GraphBuilderOptions,
1496
1462
  ): Promise<void> {
1497
- await Promise.all(
1498
- inputs.flatMap((input) =>
1499
- input.data.stores.map((element) =>
1500
- this.visitWithGraphBuilderErrorHandling(
1501
- element,
1502
- new V1_ElementSecondPassBuilder(
1503
- this.getBuilderContext(graph, input.model, element, options),
1504
- ),
1505
- ),
1506
- ),
1507
- ),
1463
+ await this.processElementsInBatches(
1464
+ graph,
1465
+ inputs,
1466
+ (data) => data.stores,
1467
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1468
+ options,
1508
1469
  );
1509
- await Promise.all(
1510
- inputs.flatMap((input) =>
1511
- input.data.stores.map((element) =>
1512
- this.visitWithGraphBuilderErrorHandling(
1513
- element,
1514
- new V1_ElementThirdPassBuilder(
1515
- this.getBuilderContext(graph, input.model, element, options),
1516
- ),
1517
- ),
1518
- ),
1519
- ),
1470
+ await this.processElementsInBatches(
1471
+ graph,
1472
+ inputs,
1473
+ (data) => data.stores,
1474
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1475
+ options,
1520
1476
  );
1521
- await Promise.all(
1522
- inputs.flatMap((input) =>
1523
- input.data.stores.map((element) =>
1524
- this.visitWithGraphBuilderErrorHandling(
1525
- element,
1526
- new V1_ElementFourthPassBuilder(
1527
- this.getBuilderContext(graph, input.model, element, options),
1528
- ),
1529
- ),
1530
- ),
1531
- ),
1477
+ await this.processElementsInBatches(
1478
+ graph,
1479
+ inputs,
1480
+ (data) => data.stores,
1481
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1482
+ options,
1532
1483
  );
1533
- await Promise.all(
1534
- inputs.flatMap((input) =>
1535
- input.data.stores.map((element) =>
1536
- this.visitWithGraphBuilderErrorHandling(
1537
- element,
1538
- new V1_ElementFifthPassBuilder(
1539
- this.getBuilderContext(graph, input.model, element, options),
1540
- ),
1541
- ),
1542
- ),
1543
- ),
1484
+ await this.processElementsInBatches(
1485
+ graph,
1486
+ inputs,
1487
+ (data) => data.stores,
1488
+ (ctx) => new V1_ElementFifthPassBuilder(ctx),
1489
+ options,
1544
1490
  );
1545
1491
  }
1546
1492
 
@@ -1549,41 +1495,26 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1549
1495
  inputs: V1_PureGraphBuilderInput[],
1550
1496
  options?: GraphBuilderOptions,
1551
1497
  ): Promise<void> {
1552
- await Promise.all(
1553
- inputs.flatMap((input) =>
1554
- input.data.mappings.map((element) =>
1555
- this.visitWithGraphBuilderErrorHandling(
1556
- element,
1557
- new V1_ElementSecondPassBuilder(
1558
- this.getBuilderContext(graph, input.model, element, options),
1559
- ),
1560
- ),
1561
- ),
1562
- ),
1498
+ await this.processElementsInBatches(
1499
+ graph,
1500
+ inputs,
1501
+ (data) => data.mappings,
1502
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1503
+ options,
1563
1504
  );
1564
- await Promise.all(
1565
- inputs.flatMap((input) =>
1566
- input.data.mappings.map((element) =>
1567
- this.visitWithGraphBuilderErrorHandling(
1568
- element,
1569
- new V1_ElementThirdPassBuilder(
1570
- this.getBuilderContext(graph, input.model, element, options),
1571
- ),
1572
- ),
1573
- ),
1574
- ),
1505
+ await this.processElementsInBatches(
1506
+ graph,
1507
+ inputs,
1508
+ (data) => data.mappings,
1509
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1510
+ options,
1575
1511
  );
1576
- await Promise.all(
1577
- inputs.flatMap((input) =>
1578
- input.data.mappings.map((element) =>
1579
- this.visitWithGraphBuilderErrorHandling(
1580
- element,
1581
- new V1_ElementFourthPassBuilder(
1582
- this.getBuilderContext(graph, input.model, element, options),
1583
- ),
1584
- ),
1585
- ),
1586
- ),
1512
+ await this.processElementsInBatches(
1513
+ graph,
1514
+ inputs,
1515
+ (data) => data.mappings,
1516
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1517
+ options,
1587
1518
  );
1588
1519
  }
1589
1520
 
@@ -1593,29 +1524,19 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1593
1524
  options?: GraphBuilderOptions,
1594
1525
  ): Promise<void> {
1595
1526
  // NOTE: connections must be built before runtimes
1596
- await Promise.all(
1597
- inputs.flatMap((input) =>
1598
- input.data.connections.map((element) =>
1599
- this.visitWithGraphBuilderErrorHandling(
1600
- element,
1601
- new V1_ElementSecondPassBuilder(
1602
- this.getBuilderContext(graph, input.model, element, options),
1603
- ),
1604
- ),
1605
- ),
1606
- ),
1527
+ await this.processElementsInBatches(
1528
+ graph,
1529
+ inputs,
1530
+ (data) => data.connections,
1531
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1532
+ options,
1607
1533
  );
1608
- await Promise.all(
1609
- inputs.flatMap((input) =>
1610
- input.data.runtimes.map((element) =>
1611
- this.visitWithGraphBuilderErrorHandling(
1612
- element,
1613
- new V1_ElementSecondPassBuilder(
1614
- this.getBuilderContext(graph, input.model, element, options),
1615
- ),
1616
- ),
1617
- ),
1618
- ),
1534
+ await this.processElementsInBatches(
1535
+ graph,
1536
+ inputs,
1537
+ (data) => data.runtimes,
1538
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1539
+ options,
1619
1540
  );
1620
1541
  }
1621
1542
 
@@ -1624,29 +1545,19 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1624
1545
  inputs: V1_PureGraphBuilderInput[],
1625
1546
  options?: GraphBuilderOptions,
1626
1547
  ): Promise<void> {
1627
- await Promise.all(
1628
- inputs.flatMap((input) =>
1629
- input.data.services.map((element) =>
1630
- this.visitWithGraphBuilderErrorHandling(
1631
- element,
1632
- new V1_ElementSecondPassBuilder(
1633
- this.getBuilderContext(graph, input.model, element, options),
1634
- ),
1635
- ),
1636
- ),
1637
- ),
1548
+ await this.processElementsInBatches(
1549
+ graph,
1550
+ inputs,
1551
+ (data) => data.services,
1552
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1553
+ options,
1638
1554
  );
1639
- await Promise.all(
1640
- inputs.flatMap((input) =>
1641
- input.data.executionEnvironments.map((element) =>
1642
- this.visitWithGraphBuilderErrorHandling(
1643
- element,
1644
- new V1_ElementSecondPassBuilder(
1645
- this.getBuilderContext(graph, input.model, element, options),
1646
- ),
1647
- ),
1648
- ),
1649
- ),
1555
+ await this.processElementsInBatches(
1556
+ graph,
1557
+ inputs,
1558
+ (data) => data.executionEnvironments,
1559
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1560
+ options,
1650
1561
  );
1651
1562
  }
1652
1563
 
@@ -1655,17 +1566,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1655
1566
  inputs: V1_PureGraphBuilderInput[],
1656
1567
  options?: GraphBuilderOptions,
1657
1568
  ): Promise<void> {
1658
- await Promise.all(
1659
- inputs.flatMap((input) =>
1660
- input.data.dataElements.map((element) =>
1661
- this.visitWithGraphBuilderErrorHandling(
1662
- element,
1663
- new V1_ElementSecondPassBuilder(
1664
- this.getBuilderContext(graph, input.model, element, options),
1665
- ),
1666
- ),
1667
- ),
1668
- ),
1569
+ await this.processElementsInBatches(
1570
+ graph,
1571
+ inputs,
1572
+ (data) => data.dataElements,
1573
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1574
+ options,
1669
1575
  );
1670
1576
  }
1671
1577
 
@@ -1674,17 +1580,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1674
1580
  inputs: V1_PureGraphBuilderInput[],
1675
1581
  options?: GraphBuilderOptions,
1676
1582
  ): Promise<void> {
1677
- await Promise.all(
1678
- inputs.flatMap((input) =>
1679
- input.data.products.map((element) =>
1680
- this.visitWithGraphBuilderErrorHandling(
1681
- element,
1682
- new V1_ElementSecondPassBuilder(
1683
- this.getBuilderContext(graph, input.model, element, options),
1684
- ),
1685
- ),
1686
- ),
1687
- ),
1583
+ await this.processElementsInBatches(
1584
+ graph,
1585
+ inputs,
1586
+ (data) => data.products,
1587
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1588
+ options,
1688
1589
  );
1689
1590
  }
1690
1591
 
@@ -1693,17 +1594,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1693
1594
  inputs: V1_PureGraphBuilderInput[],
1694
1595
  options?: GraphBuilderOptions,
1695
1596
  ): Promise<void> {
1696
- await Promise.all(
1697
- inputs.flatMap((input) =>
1698
- input.data.fileGenerations.map((element) =>
1699
- this.visitWithGraphBuilderErrorHandling(
1700
- element,
1701
- new V1_ElementSecondPassBuilder(
1702
- this.getBuilderContext(graph, input.model, element, options),
1703
- ),
1704
- ),
1705
- ),
1706
- ),
1597
+ await this.processElementsInBatches(
1598
+ graph,
1599
+ inputs,
1600
+ (data) => data.fileGenerations,
1601
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1602
+ options,
1707
1603
  );
1708
1604
  }
1709
1605
 
@@ -1712,17 +1608,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1712
1608
  inputs: V1_PureGraphBuilderInput[],
1713
1609
  options?: GraphBuilderOptions,
1714
1610
  ): Promise<void> {
1715
- await Promise.all(
1716
- inputs.flatMap((input) =>
1717
- input.data.generationSpecifications.map((element) =>
1718
- this.visitWithGraphBuilderErrorHandling(
1719
- element,
1720
- new V1_ElementSecondPassBuilder(
1721
- this.getBuilderContext(graph, input.model, element, options),
1722
- ),
1723
- ),
1724
- ),
1725
- ),
1611
+ await this.processElementsInBatches(
1612
+ graph,
1613
+ inputs,
1614
+ (data) => data.generationSpecifications,
1615
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1616
+ options,
1726
1617
  );
1727
1618
  }
1728
1619
 
@@ -1731,17 +1622,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1731
1622
  inputs: V1_PureGraphBuilderInput[],
1732
1623
  options?: GraphBuilderOptions,
1733
1624
  ): Promise<void> {
1734
- await Promise.all(
1735
- inputs.flatMap((input) =>
1736
- input.data.sectionIndices.map((element) =>
1737
- this.visitWithGraphBuilderErrorHandling(
1738
- element,
1739
- new V1_ElementSecondPassBuilder(
1740
- this.getBuilderContext(graph, input.model, element, options),
1741
- ),
1742
- ),
1743
- ),
1744
- ),
1625
+ await this.processElementsInBatches(
1626
+ graph,
1627
+ inputs,
1628
+ (data) => data.sectionIndices,
1629
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1630
+ options,
1745
1631
  );
1746
1632
  }
1747
1633
 
@@ -1750,82 +1636,90 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1750
1636
  inputs: V1_PureGraphBuilderInput[],
1751
1637
  options?: GraphBuilderOptions,
1752
1638
  ): Promise<void> {
1753
- await Promise.all(
1754
- this.graphBuilderExtensions.sortedExtraElementBuilders.map(
1755
- async (builder) => {
1756
- await Promise.all(
1757
- inputs.flatMap((input) =>
1758
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1759
- (element) =>
1760
- this.visitWithGraphBuilderErrorHandling(
1761
- element,
1762
- new V1_ElementSecondPassBuilder(
1763
- this.getBuilderContext(
1764
- graph,
1765
- input.model,
1766
- element,
1767
- options,
1768
- ),
1769
- ),
1770
- ),
1771
- ),
1772
- ),
1773
- );
1774
- await Promise.all(
1775
- inputs.flatMap((input) =>
1776
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1777
- (element) =>
1778
- this.visitWithGraphBuilderErrorHandling(
1779
- element,
1780
- new V1_ElementThirdPassBuilder(
1781
- this.getBuilderContext(
1782
- graph,
1783
- input.model,
1784
- element,
1785
- options,
1786
- ),
1787
- ),
1788
- ),
1789
- ),
1790
- ),
1791
- );
1792
- await Promise.all(
1793
- inputs.flatMap((input) =>
1794
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1795
- (element) =>
1796
- this.visitWithGraphBuilderErrorHandling(
1797
- element,
1798
- new V1_ElementFourthPassBuilder(
1799
- this.getBuilderContext(
1800
- graph,
1801
- input.model,
1802
- element,
1803
- options,
1804
- ),
1805
- ),
1806
- ),
1807
- ),
1808
- ),
1809
- );
1810
- await Promise.all(
1811
- inputs.flatMap((input) =>
1812
- (input.data.otherElementsByBuilder.get(builder) ?? []).map(
1813
- (element) =>
1814
- this.visitWithGraphBuilderErrorHandling(
1815
- element,
1816
- new V1_ElementFifthPassBuilder(
1817
- this.getBuilderContext(
1818
- graph,
1819
- input.model,
1820
- element,
1821
- options,
1822
- ),
1823
- ),
1824
- ),
1825
- ),
1826
- ),
1827
- );
1828
- },
1639
+ for (const builder of this.graphBuilderExtensions
1640
+ .sortedExtraElementBuilders) {
1641
+ const getElements = (
1642
+ data: V1_PureModelContextDataIndex,
1643
+ ): V1_PackageableElement[] =>
1644
+ data.otherElementsByBuilder.get(builder) ?? [];
1645
+ await this.processElementsInBatches(
1646
+ graph,
1647
+ inputs,
1648
+ getElements,
1649
+ (ctx) => new V1_ElementSecondPassBuilder(ctx),
1650
+ options,
1651
+ );
1652
+ await this.processElementsInBatches(
1653
+ graph,
1654
+ inputs,
1655
+ getElements,
1656
+ (ctx) => new V1_ElementThirdPassBuilder(ctx),
1657
+ options,
1658
+ );
1659
+ await this.processElementsInBatches(
1660
+ graph,
1661
+ inputs,
1662
+ getElements,
1663
+ (ctx) => new V1_ElementFourthPassBuilder(ctx),
1664
+ options,
1665
+ );
1666
+ await this.processElementsInBatches(
1667
+ graph,
1668
+ inputs,
1669
+ getElements,
1670
+ (ctx) => new V1_ElementFifthPassBuilder(ctx),
1671
+ options,
1672
+ );
1673
+ }
1674
+ }
1675
+
1676
+ /**
1677
+ * Run a callback for each item in the array, processing items in batches
1678
+ * of {@link GRAPH_BUILDER_BATCH_SIZE} and yielding to the event loop between
1679
+ * batches to keep the UI responsive.
1680
+ */
1681
+ private async runBatchedLoop<T>(
1682
+ items: T[],
1683
+ process: (item: T) => void,
1684
+ ): Promise<void> {
1685
+ for (let i = 0; i < items.length; i += GRAPH_BUILDER_BATCH_SIZE) {
1686
+ if (i > 0) {
1687
+ await new Promise<void>((resolve) => setTimeout(resolve, 0));
1688
+ }
1689
+ const end = Math.min(i + GRAPH_BUILDER_BATCH_SIZE, items.length);
1690
+ for (let j = i; j < end; j++) {
1691
+ process(guaranteeNonNullable(items[j]));
1692
+ }
1693
+ }
1694
+ }
1695
+
1696
+ /**
1697
+ * Process elements from inputs in batches, yielding to the event loop
1698
+ * between batches to keep the UI responsive.
1699
+ */
1700
+ private async processElementsInBatches(
1701
+ graph: PureModel,
1702
+ inputs: V1_PureGraphBuilderInput[],
1703
+ getElements: (
1704
+ data: V1_PureModelContextDataIndex,
1705
+ ) => V1_PackageableElement[],
1706
+ createVisitor: (
1707
+ ctx: V1_GraphBuilderContext,
1708
+ ) => V1_PackageableElementVisitor<unknown>,
1709
+ options?: GraphBuilderOptions,
1710
+ ): Promise<void> {
1711
+ const allItems = inputs.flatMap((input) =>
1712
+ getElements(input.data).map((element) => ({
1713
+ element,
1714
+ model: input.model,
1715
+ })),
1716
+ );
1717
+ await this.runBatchedLoop(allItems, (item) =>
1718
+ this.visitWithGraphBuilderErrorHandling(
1719
+ item.element,
1720
+ createVisitor(
1721
+ this.getBuilderContext(graph, item.model, item.element, options),
1722
+ ),
1829
1723
  ),
1830
1724
  );
1831
1725
  }
@@ -1833,9 +1727,9 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1833
1727
  private visitWithGraphBuilderErrorHandling<T>(
1834
1728
  element: V1_PackageableElement,
1835
1729
  visitor: V1_PackageableElementVisitor<T>,
1836
- ): Promise<T> {
1730
+ ): T {
1837
1731
  try {
1838
- return promisify(() => element.accept_PackageableElementVisitor(visitor));
1732
+ return element.accept_PackageableElementVisitor(visitor);
1839
1733
  } catch (err) {
1840
1734
  assertErrorThrown(err);
1841
1735
  const error =
@@ -3840,6 +3734,24 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
3840
3734
  );
3841
3735
  }
3842
3736
 
3737
+ private resolveArtifactElements(
3738
+ elementPaths: string[],
3739
+ pureGraph: PureModel,
3740
+ ): DataProductElementScope[] {
3741
+ const scopes: DataProductElementScope[] = [];
3742
+ for (const path of elementPaths) {
3743
+ const el = pureGraph.getNullableElement(path, true);
3744
+ if (el) {
3745
+ const scope = new DataProductElementScope();
3746
+ scope.element = PackageableElementExplicitReference.create(
3747
+ el as DataProductElement,
3748
+ );
3749
+ scopes.push(scope);
3750
+ }
3751
+ }
3752
+ return scopes;
3753
+ }
3754
+
3843
3755
  async buildDataProductAnalysis(
3844
3756
  artifact: V1_DataProductArtifact,
3845
3757
  dataProductPath: string,
@@ -3849,30 +3761,12 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
3849
3761
  projectInfo: ProjectGAVCoordinates,
3850
3762
  graphReport?: GraphManagerOperationReport,
3851
3763
  ): Promise<DataProductAnalysisQueryResult> {
3852
- // Collect all mapping generation infos from model access point groups and native model access
3853
- const allMappingGenInfos = new Map<string, V1_MappingGenerationInfo>();
3854
-
3855
3764
  const modelAccessPointGroups = artifact.accessPointGroups.filter(
3856
3765
  (group): group is V1_ModelAccessPointGroupInfo =>
3857
3766
  group instanceof V1_ModelAccessPointGroupInfo,
3858
3767
  );
3859
- for (const group of modelAccessPointGroups) {
3860
- allMappingGenInfos.set(
3861
- group.mappingGeneration.path,
3862
- group.mappingGeneration,
3863
- );
3864
- }
3865
-
3866
- if (artifact.nativeModelAccess?.mappingGenerations) {
3867
- for (const [path, genInfo] of artifact.nativeModelAccess
3868
- .mappingGenerations) {
3869
- if (!allMappingGenInfos.has(path)) {
3870
- allMappingGenInfos.set(path, genInfo);
3871
- }
3872
- }
3873
- }
3874
3768
 
3875
- // Resolve mapping path from accessPointId and dataProductAccessType
3769
+ // Resolve the target access group and mapping path
3876
3770
  let mappingPath: string | undefined;
3877
3771
  let accessGroup:
3878
3772
  | V1_ModelAccessPointGroupInfo
@@ -3894,32 +3788,67 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
3894
3788
  accessGroup = nativeCtx;
3895
3789
  }
3896
3790
  }
3897
-
3898
- if (!mappingPath) {
3791
+ if (!accessGroup) {
3899
3792
  throw new Error(
3900
- `Can't resolve mapping path for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`,
3793
+ `Can't resolve access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`,
3901
3794
  );
3902
3795
  }
3903
- if (!accessGroup) {
3796
+ if (!mappingPath) {
3904
3797
  throw new Error(
3905
- `Can't resolve access group for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`,
3798
+ `Can't resolve mapping path '${mappingPath}' for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`,
3906
3799
  );
3907
3800
  }
3908
- // Build the minimal graph using ONLY the elements from the resolved mapping
3909
- const resolvedMappingGenInfo = mappingPath
3910
- ? allMappingGenInfos.get(mappingPath)
3911
- : undefined;
3912
3801
 
3913
- if (!resolvedMappingGenInfo) {
3914
- throw new Error(
3915
- `Can't find mapping generation info for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`,
3916
- );
3802
+ // prevent refetching artifact
3803
+ const includedGenInfos = new Map<string, V1_MappingGenerationInfo>();
3804
+
3805
+ if (artifact.nativeModelAccess?.mappingGenerations) {
3806
+ for (const [path, genInfo] of artifact.nativeModelAccess
3807
+ .mappingGenerations) {
3808
+ includedGenInfos.set(path, genInfo);
3809
+ }
3810
+ }
3811
+ for (const group of modelAccessPointGroups) {
3812
+ if (!includedGenInfos.has(group.mappingGeneration.path)) {
3813
+ includedGenInfos.set(
3814
+ group.mappingGeneration.path,
3815
+ group.mappingGeneration,
3816
+ );
3817
+ }
3818
+ }
3819
+
3820
+ const nativeRuntimePaths = new Map<string, string>();
3821
+ if (artifact.nativeModelAccess?.nativeModelExecutionContexts) {
3822
+ for (const ctx of artifact.nativeModelAccess
3823
+ .nativeModelExecutionContexts) {
3824
+ const rtPath = ctx.runtimeGeneration?.path;
3825
+ if (rtPath) {
3826
+ nativeRuntimePaths.set(ctx.key, rtPath);
3827
+ }
3828
+ }
3917
3829
  }
3918
3830
 
3919
- // Create a dummy mapping for the resolved mapping path
3920
- const dummyMapping = new V1_Mapping();
3921
- dummyMapping.package = extractPackagePathFromPath(mappingPath) ?? '';
3922
- dummyMapping.name = extractElementNameFromPath(mappingPath);
3831
+ // Only add a stub for the resolved mapping to the graph
3832
+ const resolvedMappingStub = new V1_Mapping();
3833
+ resolvedMappingStub.package = extractPackagePathFromPath(mappingPath) ?? '';
3834
+ resolvedMappingStub.name = extractElementNameFromPath(mappingPath);
3835
+
3836
+ // Only add a runtime stub for the resolved native context (if applicable)
3837
+ const resolvedRuntimePath =
3838
+ dataProductAccessType === DataProductAccessType.NATIVE
3839
+ ? nativeRuntimePaths.get(accessPointId)
3840
+ : undefined;
3841
+ let resolvedRuntimeStub: V1_PackageableRuntime | undefined;
3842
+ if (resolvedRuntimePath) {
3843
+ resolvedRuntimeStub = new V1_PackageableRuntime();
3844
+ resolvedRuntimeStub.package =
3845
+ extractPackagePathFromPath(resolvedRuntimePath) ?? '';
3846
+ resolvedRuntimeStub.name =
3847
+ extractElementNameFromPath(resolvedRuntimePath);
3848
+ resolvedRuntimeStub.runtimeValue = new V1_EngineRuntime();
3849
+ }
3850
+
3851
+ // Create a dummy data product element
3923
3852
 
3924
3853
  // Create a dummy data product element
3925
3854
  const dummyDataProduct = new V1_DataProduct();
@@ -3928,9 +3857,14 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
3928
3857
  dummyDataProduct.name = extractElementNameFromPath(dataProductPath);
3929
3858
  dummyDataProduct.title = artifact.dataProduct.title;
3930
3859
  dummyDataProduct.description = artifact.dataProduct.description;
3931
- // Build the minimal graph from the resolved mapping's model elements + dummy mapping + dummy data product
3932
- const graphEntities = resolvedMappingGenInfo.model.elements
3933
- .concat([dummyMapping])
3860
+
3861
+ // Only load model elements for the resolved mapping
3862
+ const allModelElements: V1_PackageableElement[] =
3863
+ includedGenInfos.get(mappingPath)?.model.elements ?? [];
3864
+
3865
+ const graphEntities = allModelElements
3866
+ .concat(resolvedMappingStub)
3867
+ .concat(resolvedRuntimeStub ? [resolvedRuntimeStub] : [])
3934
3868
  .concat(dummyDataProduct)
3935
3869
  .filter((el) => !pureGraph.getNullableElement(el.path, false))
3936
3870
  .map((el) => this.elementProtocolToEntity(el));
@@ -3949,45 +3883,115 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
3949
3883
  );
3950
3884
 
3951
3885
  const data = pureGraph.getDataProduct(dataProductPath);
3952
- // build access point group
3953
- let exec: ModelAccessPointGroup | NativeModelExecutionContext;
3954
- if (accessGroup instanceof V1_ModelAccessPointGroupInfo) {
3955
- const group = new ModelAccessPointGroup();
3956
- group.id = accessGroup.id;
3957
- data.accessPointGroups = [group];
3958
- group.mapping = PackageableElementExplicitReference.create(
3959
- pureGraph.getMapping(mappingPath),
3886
+
3887
+ let exec: ModelAccessPointGroup | NativeModelExecutionContext | undefined;
3888
+
3889
+ if (
3890
+ artifact.nativeModelAccess?.defaultExecutionContext &&
3891
+ artifact.nativeModelAccess.nativeModelExecutionContexts.length
3892
+ ) {
3893
+ const na = new NativeModelAccess();
3894
+ na.nativeModelExecutionContexts =
3895
+ artifact.nativeModelAccess.nativeModelExecutionContexts.map(
3896
+ (ctxInfo) => {
3897
+ const ctx = new NativeModelExecutionContext();
3898
+ ctx.key = ctxInfo.key;
3899
+ const ctxMappingPath = ctxInfo.mapping;
3900
+ const ctxMapping =
3901
+ ctxMappingPath === mappingPath
3902
+ ? pureGraph.getMapping(ctxMappingPath)
3903
+ : new Mapping(ctxMappingPath);
3904
+ ctx.mapping =
3905
+ PackageableElementExplicitReference.create(ctxMapping);
3906
+ const rtPath = nativeRuntimePaths.get(ctxInfo.key);
3907
+ if (rtPath) {
3908
+ const ctxRuntime =
3909
+ rtPath === resolvedRuntimePath
3910
+ ? pureGraph.getRuntime(rtPath)
3911
+ : new PackageableRuntime(rtPath);
3912
+ ctx.runtime =
3913
+ PackageableElementExplicitReference.create(ctxRuntime);
3914
+ }
3915
+ ctx.__owner = na;
3916
+ return ctx;
3917
+ },
3918
+ );
3919
+ const defaultExecutionContext = na.nativeModelExecutionContexts.find(
3920
+ (ctx) =>
3921
+ ctx.key === artifact.nativeModelAccess?.defaultExecutionContext,
3960
3922
  );
3961
- exec = group;
3962
- } else {
3963
- const nativeAccess = new NativeModelExecutionContext();
3964
- nativeAccess.key = accessGroup.key;
3965
- nativeAccess.mapping = PackageableElementExplicitReference.create(
3966
- pureGraph.getMapping(mappingPath),
3923
+ if (!defaultExecutionContext) {
3924
+ throw new Error(
3925
+ `Can't find execution context matching default context in '${dataProductPath}'`,
3926
+ );
3927
+ }
3928
+ na.defaultExecutionContext = defaultExecutionContext;
3929
+ na.featuredElements = this.resolveArtifactElements(
3930
+ artifact.nativeModelAccess.elements,
3931
+ pureGraph,
3967
3932
  );
3968
- const na = new NativeModelAccess();
3969
- na.nativeModelExecutionContexts = [nativeAccess];
3970
3933
  data.nativeModelAccess = na;
3971
- exec = nativeAccess;
3972
3934
  }
3973
3935
 
3974
- // Build MappingModelCoverageAnalysisResult for the resolved mapping only
3936
+ if (modelAccessPointGroups.length > 0) {
3937
+ data.accessPointGroups = modelAccessPointGroups.map((groupInfo) => {
3938
+ const group = new ModelAccessPointGroup();
3939
+ group.id = groupInfo.id;
3940
+ const groupMappingPath = groupInfo.mappingGeneration.path;
3941
+ const groupMapping =
3942
+ groupMappingPath === mappingPath
3943
+ ? pureGraph.getMapping(groupMappingPath)
3944
+ : new Mapping(groupMappingPath);
3945
+ group.mapping =
3946
+ PackageableElementExplicitReference.create(groupMapping);
3947
+ group.featuredElements = this.resolveArtifactElements(
3948
+ groupInfo.elements,
3949
+ pureGraph,
3950
+ );
3951
+ return group;
3952
+ });
3953
+ }
3954
+
3955
+ // Resolve the target exec state
3956
+ if (accessGroup instanceof V1_ModelAccessPointGroupInfo) {
3957
+ exec = data.accessPointGroups.find(
3958
+ (g) => g instanceof ModelAccessPointGroup && g.id === accessGroup.id,
3959
+ ) as ModelAccessPointGroup;
3960
+ } else {
3961
+ exec = data.nativeModelAccess?.nativeModelExecutionContexts.find(
3962
+ (ctx) => ctx.key === accessGroup.key,
3963
+ );
3964
+ }
3965
+
3966
+ if (!exec) {
3967
+ throw new Error(
3968
+ `Can't find execution matching access id in '${dataProductPath}'`,
3969
+ );
3970
+ }
3971
+
3972
+ // Build MappingModelCoverageAnalysisResult for all included mappings
3975
3973
  const mappingToMappingCoverageResult = new Map<
3976
3974
  string,
3977
3975
  MappingModelCoverageAnalysisResult
3978
3976
  >();
3979
- const v1Result = new V1_MappingModelCoverageAnalysisResult();
3980
- v1Result.mappedEntities = resolvedMappingGenInfo.mappedEntities;
3981
- v1Result.model = resolvedMappingGenInfo.model;
3982
- mappingToMappingCoverageResult.set(
3983
- mappingPath,
3984
- V1_buildModelCoverageAnalysisResult(
3985
- v1Result,
3986
- this,
3987
- pureGraph.getMapping(mappingPath),
3988
- resolvedMappingGenInfo.model,
3989
- ),
3990
- );
3977
+ for (const [mPath, genInfo] of includedGenInfos) {
3978
+ const v1Result = new V1_MappingModelCoverageAnalysisResult();
3979
+ v1Result.mappedEntities = genInfo.mappedEntities;
3980
+ v1Result.model = genInfo.model;
3981
+ const coverageMapping =
3982
+ mPath === mappingPath
3983
+ ? pureGraph.getMapping(mPath)
3984
+ : new Mapping(mPath);
3985
+ mappingToMappingCoverageResult.set(
3986
+ mPath,
3987
+ V1_buildModelCoverageAnalysisResult(
3988
+ v1Result,
3989
+ this,
3990
+ coverageMapping,
3991
+ genInfo.model,
3992
+ ),
3993
+ );
3994
+ }
3991
3995
 
3992
3996
  // Build the analysis result
3993
3997
  const result = new DataProductAnalysis();