@milaboratories/milaboratories.ui-examples.model 1.3.7 → 1.3.9

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.
@@ -1,14 +1,14 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/milaboratories.ui-examples.model@1.3.7 build /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
3
+ > @milaboratories/milaboratories.ui-examples.model@1.3.9 build /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
4
4
  > ts-builder build --target block-model && block-tools build-model
5
5
 
6
6
  Building block-model project...
7
7
  ↳ rollup -c /configs/rollup.block-model.config.js
8
8
  
9
9
  ./src/index.ts → dist, dist...
10
- created dist, dist in 11.8s
10
+ created dist, dist in 7.2s
11
11
  
12
12
  ./src/index.ts → dist...
13
- created dist in 10.4s
13
+ created dist in 4.8s
14
14
  Build completed successfully
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @milaboratories/milaboratories.ui-examples.model@1.3.7 type-check /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
3
+ > @milaboratories/milaboratories.ui-examples.model@1.3.9 type-check /home/runner/_work/platforma/platforma/etc/blocks/ui-examples/model
4
4
  > ts-builder types --target block-model
5
5
 
6
6
  ↳ tsc --noEmit --project ./tsconfig.json
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @milaboratories/milaboratories.ui-examples.model
2
2
 
3
+ ## 1.3.9
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [5deb79a]
8
+ - @platforma-sdk/model@1.47.5
9
+
10
+ ## 1.3.8
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [a81ce44]
15
+ - @platforma-sdk/model@1.46.0
16
+
3
17
  ## 1.3.7
4
18
 
5
19
  ### Patch Changes
package/dist/bundle.js CHANGED
@@ -4745,6 +4745,134 @@
4745
4745
  function isLinkerColumn(column) {
4746
4746
  return !!readAnnotationJson(column, Annotation.IsLinkerColumn);
4747
4747
  }
4748
+ function makeAxisTree(axis) {
4749
+ return { axis, children: [] };
4750
+ }
4751
+ /** Build tree by axis parents annotations */
4752
+ function getAxesTree(rootAxis) {
4753
+ const root = makeAxisTree(rootAxis);
4754
+ let nodesQ = [root];
4755
+ while (nodesQ.length) {
4756
+ const nextNodes = [];
4757
+ for (const node of nodesQ) {
4758
+ node.children = node.axis.parentAxesSpec.map(makeAxisTree);
4759
+ nextNodes.push(...node.children);
4760
+ }
4761
+ nodesQ = nextNodes;
4762
+ }
4763
+ return root;
4764
+ }
4765
+ /** Get array of axisSpecs from axisTree */
4766
+ function getArrayFromAxisTree(tree) {
4767
+ const res = [tree.axis];
4768
+ let nodesQ = [tree];
4769
+ while (nodesQ.length) {
4770
+ const nextNodes = [];
4771
+ for (const node of nodesQ) {
4772
+ for (const parent of node.children) {
4773
+ res.push(parent.axis);
4774
+ nextNodes.push(parent);
4775
+ }
4776
+ }
4777
+ nodesQ = nextNodes;
4778
+ }
4779
+ return res;
4780
+ }
4781
+ function canonicalizeAxisWithParents(axis) {
4782
+ return canonicalizeJson(getArrayFromAxisTree(getAxesTree(axis)).map(getAxisId));
4783
+ }
4784
+ function normalizingAxesComparator(axis1, axis2) {
4785
+ if (axis1.name !== axis2.name) {
4786
+ return axis1.name < axis2.name ? 1 : -1;
4787
+ }
4788
+ if (axis1.type !== axis2.type) {
4789
+ return axis1.type < axis2.type ? 1 : -1;
4790
+ }
4791
+ const domain1 = canonicalizeJson(axis1.domain ?? {});
4792
+ const domain2 = canonicalizeJson(axis2.domain ?? {});
4793
+ if (domain1 !== domain2) {
4794
+ return domain1 < domain2 ? 1 : -1;
4795
+ }
4796
+ const parents1 = canonicalizeAxisWithParents(axis1);
4797
+ const parents2 = canonicalizeAxisWithParents(axis2);
4798
+ if (parents1 !== parents2) {
4799
+ return parents1 < parents2 ? 1 : -1;
4800
+ }
4801
+ const annotation1 = canonicalizeJson(axis1.annotations ?? {});
4802
+ const annotation2 = canonicalizeJson(axis2.annotations ?? {});
4803
+ if (annotation1 !== annotation2) {
4804
+ return annotation1 < annotation2 ? 1 : -1;
4805
+ }
4806
+ return 0;
4807
+ }
4808
+ function parseParentsFromAnnotations(axis) {
4809
+ const parentsList = readAnnotationJson(axis, Annotation.Parents);
4810
+ if (parentsList === undefined) {
4811
+ return [];
4812
+ }
4813
+ return parentsList;
4814
+ }
4815
+ function sortParentsDeep(axisSpec) {
4816
+ axisSpec.parentAxesSpec.forEach(sortParentsDeep);
4817
+ axisSpec.parentAxesSpec.sort(normalizingAxesComparator);
4818
+ }
4819
+ function hasCycleOfParents(axisSpec) {
4820
+ const root = makeAxisTree(axisSpec);
4821
+ let nodesQ = [root];
4822
+ const ancestors = new Set(canonicalizeJson(getAxisId(axisSpec)));
4823
+ while (nodesQ.length) {
4824
+ const nextNodes = [];
4825
+ const levelIds = new Set();
4826
+ for (const node of nodesQ) {
4827
+ node.children = node.axis.parentAxesSpec.map(makeAxisTree);
4828
+ for (const child of node.children) {
4829
+ const childId = canonicalizeJson(getAxisId(child.axis));
4830
+ if (!levelIds.has(childId)) {
4831
+ nextNodes.push(child);
4832
+ levelIds.add(childId);
4833
+ if (ancestors.has(childId)) {
4834
+ return true;
4835
+ }
4836
+ ancestors.add(childId);
4837
+ }
4838
+ }
4839
+ }
4840
+ nodesQ = nextNodes;
4841
+ }
4842
+ return false;
4843
+ }
4844
+ /** Create list of normalized axisSpec (parents are in array of specs, not indexes) */
4845
+ function getNormalizedAxesList(axes) {
4846
+ if (!axes.length) {
4847
+ return [];
4848
+ }
4849
+ const modifiedAxes = axes.map((axis) => {
4850
+ const { parentAxes: _, ...copiedRest } = axis;
4851
+ return { ...copiedRest, annotations: { ...copiedRest.annotations }, parentAxesSpec: [] };
4852
+ });
4853
+ axes.forEach((axis, idx) => {
4854
+ const modifiedAxis = modifiedAxes[idx];
4855
+ if (axis.parentAxes) { // if we have parents by indexes then take from the list
4856
+ modifiedAxis.parentAxesSpec = axis.parentAxes.map((idx) => modifiedAxes[idx]);
4857
+ }
4858
+ else { // else try to parse from annotation name
4859
+ const parents = parseParentsFromAnnotations(axis).map((name) => modifiedAxes.find((axis) => axis.name === name));
4860
+ modifiedAxis.parentAxesSpec = parents.some((p) => p === undefined) ? [] : parents;
4861
+ delete modifiedAxis.annotations?.[Annotation.Parents];
4862
+ }
4863
+ });
4864
+ if (modifiedAxes.some(hasCycleOfParents)) { // Axes list is broken
4865
+ modifiedAxes.forEach((axis) => {
4866
+ axis.parentAxesSpec = [];
4867
+ });
4868
+ }
4869
+ else {
4870
+ modifiedAxes.forEach((axis) => {
4871
+ sortParentsDeep(axis);
4872
+ });
4873
+ }
4874
+ return modifiedAxes;
4875
+ }
4748
4876
  /// Well-known column names
4749
4877
  const PColumnName = {
4750
4878
  Label: 'pl7.app/label'};
@@ -5244,6 +5372,232 @@
5244
5372
  return canonicalize(result);
5245
5373
  }
5246
5374
 
5375
+ class LinkerMap {
5376
+ /** Graph of linkers connected by axes (single or grouped by parents) */
5377
+ data;
5378
+ constructor(linkerMap) {
5379
+ this.data = linkerMap;
5380
+ }
5381
+ get keys() {
5382
+ return this.data.keys();
5383
+ }
5384
+ get keyAxesIds() {
5385
+ return [...this.data.keys()].map(parseJson);
5386
+ }
5387
+ static fromColumns(columns) {
5388
+ const result = new Map();
5389
+ for (const linker of columns.filter((l) => !!readAnnotationJson(l.spec, Annotation.IsLinkerColumn))) {
5390
+ const groups = LinkerMap.getAxesGroups(getNormalizedAxesList(linker.spec.axesSpec)); // split input axes into groups by parent links from annotation
5391
+ if (groups.length !== 2) {
5392
+ continue; // not a valid linker column
5393
+ }
5394
+ const [left, right] = groups;
5395
+ // In case of group:
5396
+ // A - C
5397
+ // \_ B _ D
5398
+ // E/
5399
+ // put 2 variants as keys:
5400
+ // A - C
5401
+ // \_ B _ D
5402
+ // and
5403
+ // E - B - D
5404
+ const leftKeyVariants = LinkerMap.getAxesRoots(left).map((axis) => {
5405
+ const axes = getArrayFromAxisTree(getAxesTree(axis));
5406
+ const key = canonicalizeJson(axes.map(getAxisId));
5407
+ return [key, axes];
5408
+ });
5409
+ const rightKeyVariants = LinkerMap.getAxesRoots(right).map((axis) => {
5410
+ const axes = getArrayFromAxisTree(getAxesTree(axis));
5411
+ const key = canonicalizeJson(axes.map(getAxisId));
5412
+ return [key, axes];
5413
+ });
5414
+ for (const [keyLeft, spec] of leftKeyVariants) {
5415
+ if (!result.has(keyLeft)) {
5416
+ result.set(keyLeft, { keyAxesSpec: spec, linkWith: new Map() });
5417
+ }
5418
+ }
5419
+ for (const [keyRight, spec] of rightKeyVariants) {
5420
+ if (!result.has(keyRight)) {
5421
+ result.set(keyRight, { keyAxesSpec: spec, linkWith: new Map() });
5422
+ }
5423
+ }
5424
+ for (const [keyLeft] of leftKeyVariants) {
5425
+ for (const [keyRight] of rightKeyVariants) {
5426
+ result.get(keyLeft)?.linkWith.set(keyRight, linker);
5427
+ result.get(keyRight)?.linkWith.set(keyLeft, linker);
5428
+ }
5429
+ }
5430
+ }
5431
+ return new this(result);
5432
+ }
5433
+ /** Get all available nodes of linker graphs if start from sourceAxesKeys */
5434
+ searchAvailableAxesKeys(sourceAxesKeys) {
5435
+ const startKeys = new Set(sourceAxesKeys);
5436
+ const allAvailableKeys = new Set();
5437
+ let nextKeys = sourceAxesKeys;
5438
+ while (nextKeys.length) {
5439
+ const next = [];
5440
+ for (const key of nextKeys) {
5441
+ const node = this.data.get(key);
5442
+ if (!node)
5443
+ continue;
5444
+ for (const availableKey of node.linkWith.keys()) {
5445
+ if (!allAvailableKeys.has(availableKey) && !startKeys.has(availableKey)) {
5446
+ next.push(availableKey);
5447
+ allAvailableKeys.add(availableKey);
5448
+ }
5449
+ }
5450
+ }
5451
+ nextKeys = next;
5452
+ }
5453
+ return allAvailableKeys;
5454
+ }
5455
+ /** Get all linker columns that are necessary to reach endKey from startKey */
5456
+ searchLinkerPath(startKey, endKey) {
5457
+ const previous = {};
5458
+ let nextIds = new Set([startKey]);
5459
+ const visited = new Set([startKey]);
5460
+ while (nextIds.size) {
5461
+ const next = new Set();
5462
+ for (const nextId of nextIds) {
5463
+ const node = this.data.get(nextId);
5464
+ if (!node)
5465
+ continue;
5466
+ for (const availableId of node.linkWith.keys()) {
5467
+ previous[availableId] = nextId;
5468
+ if (availableId === endKey) {
5469
+ const ids = [];
5470
+ let current = endKey;
5471
+ while (previous[current] !== startKey) {
5472
+ ids.push(current);
5473
+ current = previous[current];
5474
+ }
5475
+ ids.push(current);
5476
+ return ids.map((id) => this.data.get(id).linkWith.get(previous[id]));
5477
+ }
5478
+ else if (!visited.has(availableId)) {
5479
+ next.add(availableId);
5480
+ visited.add(availableId);
5481
+ }
5482
+ }
5483
+ }
5484
+ nextIds = next;
5485
+ }
5486
+ return [];
5487
+ }
5488
+ getLinkerColumnsForAxes({ from: sourceAxes, to: targetAxes, throwWhenNoLinkExists = true, }) {
5489
+ // start keys - all possible keys in linker map using sourceAxes (for example, all axes of block's columns or all axes of columns in data-inputs)
5490
+ const startKeys = sourceAxes.map(LinkerMap.getLinkerKeyFromAxisSpec);
5491
+ return Array.from(new Map(LinkerMap.getAxesRoots(targetAxes)
5492
+ .map(LinkerMap.getLinkerKeyFromAxisSpec) // target keys contain all axes to be linked; if some of target axes has parents they must be in the key
5493
+ .flatMap((targetKey) => {
5494
+ const linkers = startKeys
5495
+ .map((startKey) => this.searchLinkerPath(startKey, targetKey))
5496
+ .reduce((shortestPath, path) => (shortestPath.length && shortestPath.length < path.length) || !path.length ? shortestPath : path, [])
5497
+ .map((linker) => [linker.columnId, linker]);
5498
+ if (!linkers.length && throwWhenNoLinkExists) {
5499
+ throw Error(`Unable to find linker column for ${targetKey}`);
5500
+ }
5501
+ return linkers;
5502
+ })).values());
5503
+ }
5504
+ /** Get list of axisSpecs from keys of linker columns map */
5505
+ getAxesListFromKeysList(keys) {
5506
+ return Array.from(new Map(keys.flatMap((key) => this.data.get(key)?.keyAxesSpec ?? [])
5507
+ .map((axis) => [canonicalizeJson(getAxisId(axis)), axis])).values());
5508
+ }
5509
+ /** Get axes of target axes that are impossible to be linked to source axes with current linker map */
5510
+ getNonLinkableAxes(sourceAxes, targetAxes) {
5511
+ const startKeys = sourceAxes.map(LinkerMap.getLinkerKeyFromAxisSpec);
5512
+ // target keys contain all axes to be linked; if some of target axes has parents they must be in the key
5513
+ const targetKeys = targetAxes.map(LinkerMap.getLinkerKeyFromAxisSpec);
5514
+ const axes = Array.from(new Map(targetAxes
5515
+ .filter((_targetAxis, idx) => {
5516
+ const targetKey = targetKeys[idx];
5517
+ return !startKeys.some((startKey) => this.searchLinkerPath(startKey, targetKey).length);
5518
+ })
5519
+ .flatMap((axis) => getArrayFromAxisTree(getAxesTree(axis)).map((axis) => [canonicalizeJson(getAxisId(axis)), axis]))).values());
5520
+ return axes;
5521
+ }
5522
+ /** Get all axes that can be connected to sourceAxes by linkers */
5523
+ getReachableByLinkersAxesFromAxesNormalized(sourceAxes, matchAxisIdFn) {
5524
+ let startKeys = [];
5525
+ if (matchAxisIdFn) {
5526
+ const sourceAxisIdsGrouped = sourceAxes.map((axis) => getArrayFromAxisTree(getAxesTree(axis)).map(getAxisId));
5527
+ for (const sourceAxisIdsGroup of sourceAxisIdsGrouped) {
5528
+ const matched = this.keyAxesIds.find((keyIds) => keyIds.every((linkerKeyAxisId) => sourceAxisIdsGroup.find((sourceAxisId) => matchAxisIdFn(linkerKeyAxisId, sourceAxisId))));
5529
+ if (matched) {
5530
+ startKeys.push(canonicalizeJson(matched));
5531
+ }
5532
+ }
5533
+ }
5534
+ else {
5535
+ startKeys = sourceAxes.map(LinkerMap.getLinkerKeyFromAxisSpec);
5536
+ }
5537
+ const availableKeys = this.searchAvailableAxesKeys(startKeys);
5538
+ return this.getAxesListFromKeysList([...availableKeys]);
5539
+ }
5540
+ getReachableByLinkersAxesFromAxes(sourceAxes, matchAxisIdFn) {
5541
+ return this.getReachableByLinkersAxesFromAxesNormalized(getNormalizedAxesList(sourceAxes), matchAxisIdFn);
5542
+ }
5543
+ static getLinkerKeyFromAxisSpec(axis) {
5544
+ return canonicalizeJson(getArrayFromAxisTree(getAxesTree(axis)).map(getAxisId));
5545
+ }
5546
+ /** Split array of axes into several arrays by parents: axes of one group are parents for each other.
5547
+ There are no order inside every group. */
5548
+ static getAxesGroups(axesSpec) {
5549
+ switch (axesSpec.length) {
5550
+ case 0: return [];
5551
+ case 1: return [[axesSpec[0]]];
5552
+ }
5553
+ const axisKeys = axesSpec.map((spec) => canonicalizeJson(getAxisId(spec)));
5554
+ const axisParentsIdxs = axesSpec.map((spec) => new Set(spec.parentAxesSpec
5555
+ .map((spec) => canonicalizeJson(getAxisId(spec)))
5556
+ .map((el) => {
5557
+ const idx = axisKeys.indexOf(el);
5558
+ if (idx === -1) {
5559
+ throw new Error(`malformed axesSpec: ${JSON.stringify(axesSpec)}, unable to locate parent ${el}`);
5560
+ }
5561
+ return idx;
5562
+ })));
5563
+ const allIdxs = [...axesSpec.keys()];
5564
+ const groups = []; // groups of axis indexes
5565
+ const usedIdxs = new Set();
5566
+ let nextFreeEl = allIdxs.find((idx) => !usedIdxs.has(idx));
5567
+ while (nextFreeEl !== undefined) {
5568
+ const currentGroup = [nextFreeEl];
5569
+ usedIdxs.add(nextFreeEl);
5570
+ let nextElsOfCurrentGroup = [nextFreeEl];
5571
+ while (nextElsOfCurrentGroup.length) {
5572
+ const next = new Set();
5573
+ for (const groupIdx of nextElsOfCurrentGroup) {
5574
+ const groupElementParents = axisParentsIdxs[groupIdx];
5575
+ allIdxs.forEach((idx) => {
5576
+ if (idx === groupIdx || usedIdxs.has(idx)) {
5577
+ return;
5578
+ }
5579
+ const parents = axisParentsIdxs[idx];
5580
+ if (parents.has(groupIdx) || groupElementParents.has(idx)) {
5581
+ currentGroup.push(idx);
5582
+ next.add(idx);
5583
+ usedIdxs.add(idx);
5584
+ }
5585
+ });
5586
+ }
5587
+ nextElsOfCurrentGroup = [...next];
5588
+ }
5589
+ groups.push([...currentGroup]);
5590
+ nextFreeEl = allIdxs.find((idx) => !usedIdxs.has(idx));
5591
+ }
5592
+ return groups.map((group) => group.map((idx) => axesSpec[idx]));
5593
+ }
5594
+ /** Get all axes that are not parents of any other axis */
5595
+ static getAxesRoots(axes) {
5596
+ const parentsSet = new Set(axes.flatMap((axis) => axis.parentAxesSpec).map((spec) => canonicalizeJson(getAxisId(spec))));
5597
+ return axes.filter((axis) => !parentsSet.has(canonicalizeJson(getAxisId(axis))));
5598
+ }
5599
+ }
5600
+
5247
5601
  /** Characters in string representation */
5248
5602
  const PlIdLength = 24; // = 15 bytes * 8 bits / 5 bits per char in base32
5249
5603
  z
@@ -6253,7 +6607,7 @@
6253
6607
  return undefined;
6254
6608
  }
6255
6609
  getUniversalEntries(predicateOrSelectors, opts) {
6256
- const { anchorCtx, labelOps: rawLabelOps, dontWaitAllData = false, overrideLabelAnnotation = false, exclude } = opts ?? {};
6610
+ const { anchorCtx, labelOps: rawLabelOps, dontWaitAllData = false, overrideLabelAnnotation = false, exclude, enrichByLinkers = false } = opts ?? {};
6257
6611
  const labelOps = {
6258
6612
  ...(overrideLabelAnnotation && rawLabelOps?.includeNativeLabel !== false ? { includeNativeLabel: true } : {}),
6259
6613
  ...(rawLabelOps ?? {}),
@@ -6426,6 +6780,29 @@
6426
6780
  label: label,
6427
6781
  });
6428
6782
  }
6783
+ const ids = new Set(result.map((entry) => entry.id));
6784
+ if (enrichByLinkers && anchorCtx) {
6785
+ const linkers = result.filter((entry) => isLinkerColumn(entry.spec));
6786
+ if (linkers.length === 0) {
6787
+ return result;
6788
+ }
6789
+ const anchorAxes = Object.values(anchorCtx.anchors).flatMap((anchor) => anchor.axesSpec);
6790
+ const linkerMap = LinkerMap.fromColumns(linkers.map(getColumnIdAndSpec));
6791
+ // loose way of matching
6792
+ function matchAxisIdFn(linkerKeyId, sourceAxisId) {
6793
+ return matchAxisId(linkerKeyId, sourceAxisId) || matchAxisId(sourceAxisId, linkerKeyId);
6794
+ }
6795
+ // search all axes that can be reached by linkers from anchor axes; anchor axes are not in this list;
6796
+ const availableByLinkersAxes = linkerMap.getReachableByLinkersAxesFromAxes(anchorAxes, matchAxisIdFn);
6797
+ // search all columns that includes at least one of additional axes;
6798
+ const availableByLinkersColumns = this.getUniversalEntries((spec) => !isLinkerColumn(spec) && spec.axesSpec.some((columnAxisSpec) => {
6799
+ const columnAxisId = getAxisId(columnAxisSpec);
6800
+ return availableByLinkersAxes.some((axis) => matchAxisIdFn(getAxisId(axis), columnAxisId));
6801
+ }), { anchorCtx, labelOps, dontWaitAllData, overrideLabelAnnotation, exclude });
6802
+ if (availableByLinkersColumns) {
6803
+ result.push(...availableByLinkersColumns.filter((entry) => !ids.has(entry.id)));
6804
+ }
6805
+ }
6429
6806
  return result;
6430
6807
  }
6431
6808
  getColumns(predicateOrSelectors, opts) {
@@ -7001,7 +7378,7 @@
7001
7378
  }
7002
7379
  }
7003
7380
 
7004
- var version = "1.45.45";
7381
+ var version = "1.47.5";
7005
7382
 
7006
7383
  const PlatformaSDKVersion = version;
7007
7384