@trebco/treb 27.7.6 → 27.9.0

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 (36) hide show
  1. package/dist/treb-spreadsheet.mjs +14 -14
  2. package/dist/treb.d.ts +21 -21
  3. package/notes/conditional-fomratring.md +29 -0
  4. package/package.json +1 -1
  5. package/treb-base-types/src/area.ts +181 -0
  6. package/treb-base-types/src/evaluate-options.ts +21 -0
  7. package/treb-base-types/src/gradient.ts +97 -0
  8. package/treb-base-types/src/import.ts +2 -1
  9. package/treb-base-types/src/index.ts +2 -0
  10. package/treb-calculator/src/calculator.ts +190 -28
  11. package/treb-calculator/src/dag/calculation_leaf_vertex.ts +97 -0
  12. package/treb-calculator/src/dag/graph.ts +10 -22
  13. package/treb-calculator/src/dag/{leaf_vertex.ts → state_leaf_vertex.ts} +3 -3
  14. package/treb-calculator/src/descriptors.ts +10 -3
  15. package/treb-calculator/src/expression-calculator.ts +1 -1
  16. package/treb-calculator/src/function-library.ts +25 -22
  17. package/treb-calculator/src/functions/base-functions.ts +166 -5
  18. package/treb-calculator/src/index.ts +6 -6
  19. package/treb-calculator/src/notifier-types.ts +1 -1
  20. package/treb-calculator/src/utilities.ts +2 -2
  21. package/treb-charts/src/util.ts +2 -2
  22. package/treb-embed/src/embedded-spreadsheet.ts +352 -41
  23. package/treb-export/src/export-worker/export-worker.ts +0 -13
  24. package/treb-export/src/export2.ts +187 -2
  25. package/treb-export/src/import2.ts +169 -4
  26. package/treb-export/src/workbook-style2.ts +56 -8
  27. package/treb-export/src/workbook2.ts +10 -1
  28. package/treb-grid/src/index.ts +2 -1
  29. package/treb-grid/src/layout/base_layout.ts +23 -15
  30. package/treb-grid/src/render/tile_renderer.ts +2 -1
  31. package/treb-grid/src/types/conditional_format.ts +168 -0
  32. package/treb-grid/src/types/grid.ts +5 -6
  33. package/treb-grid/src/types/grid_base.ts +186 -33
  34. package/treb-grid/src/types/sheet.ts +330 -26
  35. package/treb-grid/src/types/sheet_types.ts +4 -0
  36. /package/{README-shadow-DOM.md → notes/shadow-DOM.md} +0 -0
@@ -19,13 +19,13 @@
19
19
  *
20
20
  */
21
21
 
22
- import type { Cell, ICellAddress, ICellAddress2, UnionValue,
23
- ArrayUnion, IArea, CellDataWithAddress} from 'treb-base-types';
22
+ import type { Cell, ICellAddress, ICellAddress2, UnionValue, EvaluateOptions,
23
+ ArrayUnion, IArea, CellDataWithAddress, CellValue} from 'treb-base-types';
24
24
  import { Localization, Area, ValueType, IsCellAddress} from 'treb-base-types';
25
25
 
26
26
  import type { ExpressionUnit, DependencyList, UnitRange, UnitAddress, UnitIdentifier } from 'treb-parser';
27
27
  import { Parser,
28
- DecimalMarkType, ArgumentSeparatorType } from 'treb-parser';
28
+ DecimalMarkType, ArgumentSeparatorType, QuotedSheetNameRegex } from 'treb-parser';
29
29
 
30
30
  import { Graph } from './dag/graph';
31
31
  import type { SpreadsheetVertex } from './dag/spreadsheet_vertex';
@@ -49,10 +49,12 @@ import { Variance } from './functions/statistics-functions';
49
49
 
50
50
  import * as Primitives from './primitives';
51
51
 
52
- import type { DataModel, Annotation, FunctionDescriptor, Sheet } from 'treb-grid';
53
- import { LeafVertex } from './dag/leaf_vertex';
52
+ import type { DataModel, Annotation, FunctionDescriptor, Sheet, ConditionalFormat } from 'treb-grid';
53
+ import type { LeafVertex } from './dag/graph';
54
54
 
55
55
  import { ArgumentError, ReferenceError, UnknownError, ValueError, ExpressionError, NAError, DivideByZeroError } from './function-error';
56
+ import { StateLeafVertex } from './dag/state_leaf_vertex';
57
+ import { CalculationLeafVertex } from './dag/calculation_leaf_vertex';
56
58
 
57
59
  /**
58
60
  * breaking this out so we can use it for export (TODO)
@@ -120,27 +122,6 @@ const TranslateSubtotalType = (type: string|number): number => {
120
122
 
121
123
  };
122
124
 
123
- /**
124
- * options for the evaluate function
125
- */
126
- export interface EvaluateOptions {
127
-
128
- /**
129
- * argument separator to use when parsing input. set this option to
130
- * use a consistent argument separator independent of current locale.
131
- */
132
- argument_separator?: ','|';';
133
-
134
- /**
135
- * allow R1C1-style references. the Evaluate function cannot use
136
- * relative references (e.g. R[-1]C[0]), so those will always fail.
137
- * however it may be useful to use direct R1C1 references (e.g. R3C4),
138
- * so we optionally support that behind this flag.
139
- */
140
- r1c1?: boolean;
141
-
142
- }
143
-
144
125
  /**
145
126
  * we're providing a runtime option for how to handle complex numbers.
146
127
  * we will need to pass that into the calculator when it's created to
@@ -1309,6 +1290,7 @@ export class Calculator extends Graph {
1309
1290
  if (this.full_rebuild_required) {
1310
1291
  subset = undefined;
1311
1292
  this.UpdateAnnotations();
1293
+ this.UpdateConditionals();
1312
1294
  // this.UpdateNotifiers();
1313
1295
  this.full_rebuild_required = false; // unset
1314
1296
  }
@@ -1391,9 +1373,11 @@ export class Calculator extends Graph {
1391
1373
  return map;
1392
1374
  }
1393
1375
 
1376
+ public Evaluate(expression: string, active_sheet?: Sheet, options?: EvaluateOptions, raw_result?: false): CellValue|CellValue[][];
1377
+ public Evaluate(expression: string, active_sheet?: Sheet, options?: EvaluateOptions, raw_result?: true): UnionValue;
1394
1378
 
1395
1379
  /** moved from embedded sheet */
1396
- public Evaluate(expression: string, active_sheet?: Sheet, options: EvaluateOptions = {}) {
1380
+ public Evaluate(expression: string, active_sheet?: Sheet, options: EvaluateOptions = {}, raw_result = false) {
1397
1381
 
1398
1382
  const current = this.parser.argument_separator;
1399
1383
  const r1c1_state = this.parser.flags.r1c1;
@@ -1447,6 +1431,9 @@ export class Calculator extends Graph {
1447
1431
 
1448
1432
  // console.info({expression: parse_result.expression})
1449
1433
  const result = this.CalculateExpression(parse_result.expression);
1434
+ if (raw_result) {
1435
+ return result;
1436
+ }
1450
1437
 
1451
1438
  if (result.type === ValueType.array) {
1452
1439
  return result.value.map(row => row.map(value => value.value));
@@ -1500,6 +1487,7 @@ export class Calculator extends Graph {
1500
1487
  // add leaf vertices for annotations
1501
1488
 
1502
1489
  this.UpdateAnnotations(); // all
1490
+ this.UpdateConditionals();
1503
1491
 
1504
1492
  // and notifiers
1505
1493
 
@@ -1722,6 +1710,180 @@ export class Calculator extends Graph {
1722
1710
  }
1723
1711
  */
1724
1712
 
1713
+ public Unresolve(ref: IArea|ICellAddress, context: Sheet, qualified = true, named = true) {
1714
+
1715
+ let range = '';
1716
+ const area = IsCellAddress(ref) ? new Area(ref) : new Area(ref.start, ref.end);
1717
+
1718
+ if (named) {
1719
+ const named_range = this.model.named_ranges.MatchSelection(area);
1720
+ if (named_range) {
1721
+ return named_range;
1722
+ }
1723
+ }
1724
+
1725
+ if (area.count > 1) {
1726
+ range = Area.CellAddressToLabel(area.start) + ':' + Area.CellAddressToLabel(area.end);
1727
+ }
1728
+ else {
1729
+ range = Area.CellAddressToLabel(area.start);
1730
+ }
1731
+
1732
+ if (!qualified) {
1733
+ return range;
1734
+ }
1735
+
1736
+ // is there a function to resolve sheet? actually, don't we know that
1737
+ // the active selection must be on the active sheet? (...)
1738
+
1739
+ const sheet_id = area.start.sheet_id || context?.id;
1740
+ const sheet_name = this.ResolveSheetName(sheet_id, true);
1741
+
1742
+ return sheet_name ? sheet_name + '!' + range : range;
1743
+
1744
+ }
1745
+
1746
+ /**
1747
+ *
1748
+ */
1749
+ public ResolveSheetName(id: number, quote = false): string | undefined {
1750
+ const sheet = this.model.sheets.Find(id);
1751
+ if (sheet) {
1752
+ if (quote && QuotedSheetNameRegex.test(sheet.name)) {
1753
+ return `'${sheet.name}'`;
1754
+ }
1755
+ return sheet.name;
1756
+ }
1757
+ return undefined;
1758
+ }
1759
+
1760
+ public RemoveConditional(conditional: ConditionalFormat): void {
1761
+ if (conditional.type === 'expression') {
1762
+ const vertex = conditional.internal?.vertex as LeafVertex;
1763
+ if (vertex) {
1764
+ vertex.Reset();
1765
+ this.RemoveLeafVertex(vertex);
1766
+ }
1767
+ }
1768
+ }
1769
+
1770
+ public UpdateConditionals(list?: ConditionalFormat|ConditionalFormat[], context?: Sheet): void {
1771
+
1772
+ if (!list) {
1773
+ for (const sheet of this.model.sheets.list) {
1774
+ if (sheet.conditional_formats?.length) {
1775
+ this.UpdateConditionals(sheet.conditional_formats, sheet);
1776
+ }
1777
+ }
1778
+ return;
1779
+ }
1780
+
1781
+ if (!context) {
1782
+ throw new Error('invalid call to update conditionals without context');
1783
+ }
1784
+
1785
+ if (list && !Array.isArray(list)) {
1786
+ list = [list];
1787
+ }
1788
+
1789
+ for (const entry of list) {
1790
+
1791
+ let expression = '';
1792
+
1793
+ switch (entry.type) {
1794
+ case 'cell-match':
1795
+ expression = this.Unresolve(entry.area, context, true, false) + ' ' + entry.expression;
1796
+ break;
1797
+
1798
+ case 'expression':
1799
+ expression = entry.expression;
1800
+ break;
1801
+
1802
+ case 'duplicate-values':
1803
+ expression = `UniqueValues(${
1804
+ this.Unresolve(entry.area, context, true, false)
1805
+ })`;
1806
+ if (!entry.unique) {
1807
+ expression = `NOT(${expression})`;
1808
+ }
1809
+ break;
1810
+
1811
+ case 'gradient':
1812
+ expression = `=Gradient(${
1813
+ [
1814
+ this.Unresolve(entry.area, context, true, false),
1815
+ entry.min ?? '',
1816
+ entry.max ?? '',
1817
+
1818
+ ].join(this.parser.argument_separator)
1819
+ })`;
1820
+ break;
1821
+
1822
+ default:
1823
+ continue;
1824
+ }
1825
+
1826
+ if (!expression) {
1827
+ continue; // FIXME: warn?
1828
+ }
1829
+
1830
+ // console.info({type: entry.type, expression});
1831
+
1832
+ if (!entry.internal) {
1833
+ entry.internal = {};
1834
+ }
1835
+ if (!entry.internal.vertex) {
1836
+ entry.internal.vertex = new CalculationLeafVertex();
1837
+
1838
+ let options: EvaluateOptions|undefined;
1839
+ if (entry.type !== 'gradient' && entry.type !== 'duplicate-values') {
1840
+ options = entry.options;
1841
+ }
1842
+
1843
+ // first pass, run the calculation
1844
+ const check = this.Evaluate(expression, context, options, true);
1845
+ entry.internal.vertex.result = check;
1846
+ entry.internal.vertex.updated = true;
1847
+
1848
+ }
1849
+
1850
+ const vertex = entry.internal.vertex as LeafVertex;
1851
+ this.AddLeafVertex(vertex);
1852
+ this.UpdateLeafVertex(vertex, expression, context);
1853
+
1854
+ /*
1855
+ if (entry.type === 'cell-match') {
1856
+ if (!entry.internal) {
1857
+ entry.internal = {};
1858
+ }
1859
+ if (!entry.internal.vertex) {
1860
+ entry.internal.vertex = new CalculationLeafVertex();
1861
+ }
1862
+ const vertex = entry.internal.vertex as LeafVertex;
1863
+ this.AddLeafVertex(vertex);
1864
+ this.UpdateLeafVertex(vertex, entry.expression, context);
1865
+ }
1866
+ else if (entry.type === 'expression') {
1867
+ if (!entry.internal) {
1868
+ entry.internal = {};
1869
+ }
1870
+ if (!entry.internal.vertex) {
1871
+ entry.internal.vertex = new CalculationLeafVertex();
1872
+
1873
+ // set initial state based on current state
1874
+ entry.internal.vertex.result = { type: ValueType.boolean, value: !!entry.applied };
1875
+
1876
+ }
1877
+ const vertex = entry.internal.vertex as LeafVertex;
1878
+ this.AddLeafVertex(vertex);
1879
+ this.UpdateLeafVertex(vertex, entry.expression, context);
1880
+ }
1881
+ */
1882
+
1883
+ }
1884
+
1885
+ }
1886
+
1725
1887
  public RemoveAnnotation(annotation: Annotation): void {
1726
1888
  const vertex = (annotation.temp.vertex as LeafVertex);
1727
1889
  if (!vertex) { return; }
@@ -1756,7 +1918,7 @@ export class Calculator extends Graph {
1756
1918
  for (const entry of list) {
1757
1919
  if (entry.data.formula) {
1758
1920
  if (!entry.temp.vertex) {
1759
- entry.temp.vertex = new LeafVertex();
1921
+ entry.temp.vertex = new StateLeafVertex();
1760
1922
  }
1761
1923
  const vertex = entry.temp.vertex as LeafVertex;
1762
1924
  this.AddLeafVertex(vertex);
@@ -0,0 +1,97 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ import type { GraphCallbacks } from './spreadsheet_vertex_base';
23
+ import { SpreadsheetVertex } from './spreadsheet_vertex';
24
+ import type { Vertex} from './vertex';
25
+ import { Color } from './vertex';
26
+
27
+ /**
28
+ * adding a new leaf vertex type that actually does a calculation;
29
+ * but it has no spreadsheet context (address) and by definition it
30
+ * has no dependendents.
31
+ *
32
+ * this is intended for managing conditional formats, if they have
33
+ * an expression. we only want to calculate these when necessary
34
+ * (i.e. dependencies have updated, or they are volatile).
35
+ *
36
+ */
37
+ export class CalculationLeafVertex extends SpreadsheetVertex {
38
+
39
+ public static type = 'calculation-leaf-vertex';
40
+
41
+ public type = CalculationLeafVertex.type; // for type guard
42
+
43
+ public address = { row: -1, column: -1 }; // fake address
44
+
45
+ /**
46
+ * flag, to reduce unecessary application. work in progress. this
47
+ * indicates that we reached the calculation step. that means either
48
+ * (1) dependencies changed, or (2) we were marked dirty in some global
49
+ * operation, probably a full-recalc.
50
+ *
51
+ * (2) is a waste but we're still going to save some cycles here. if you
52
+ * want you could add a state check like the other leaf vertex.
53
+ */
54
+ public updated = false;
55
+
56
+ /**
57
+ * leaf vertex defaults to black (i.e. tested) because leaf nodes cannot have
58
+ * outbound edges. it is still possible to change this, because it's a property
59
+ * and we can't override the set accessor, but making it an accessor in the
60
+ * superclass just for this purpose is not worthwhile since regular vertices
61
+ * should vastly outnumber leaves.
62
+ */
63
+ public color = Color.black;
64
+
65
+ /** overrides calculate function */
66
+ public Calculate(graph: GraphCallbacks): void {
67
+
68
+ // if we are not dirty, nothing to do
69
+ if (!this.dirty) return;
70
+
71
+ // check deps
72
+ for (const edge of this.edges_in) {
73
+ if ((edge as SpreadsheetVertex).dirty) {
74
+ return;
75
+ }
76
+ }
77
+
78
+ // ...
79
+
80
+ const result = graph.CalculationCallback.call(graph, this);
81
+
82
+ this.result = result.value;
83
+ this.dirty = false;
84
+
85
+ // set flag
86
+
87
+ this.updated = true;
88
+
89
+ // we are not allowed to have edges out, so nothing to do
90
+
91
+ }
92
+
93
+ public AddDependent(edge: Vertex): void {
94
+ throw(new Error('leaf vertex cannot have dependents'));
95
+ }
96
+
97
+ }
@@ -24,10 +24,13 @@ import { Color } from './vertex';
24
24
  import { SpreadsheetVertex } from './spreadsheet_vertex';
25
25
  import { ArrayVertex } from './array-vertex';
26
26
  import type { SpreadsheetVertexBase, CalculationResult, GraphCallbacks } from './spreadsheet_vertex_base';
27
- import type { LeafVertex } from './leaf_vertex';
27
+ import type { StateLeafVertex } from './state_leaf_vertex';
28
28
  import type { ICellAddress, ICellAddress2, IArea, UnionValue } from 'treb-base-types';
29
29
  import { Area } from 'treb-base-types';
30
30
  import type { DataModel } from 'treb-grid';
31
+ import { CalculationLeafVertex } from './calculation_leaf_vertex';
32
+
33
+ export type LeafVertex = StateLeafVertex|CalculationLeafVertex;
31
34
 
32
35
  // FIXME: this is a bad habit if you're testing on falsy for OK.
33
36
 
@@ -61,7 +64,8 @@ export abstract class Graph implements GraphCallbacks {
61
64
  public loop_hint?: string;
62
65
 
63
66
  // special
64
- public leaf_vertices: LeafVertex[] = [];
67
+ // public leaf_vertices: LeafVertex[] = [];
68
+ public leaf_vertices: Set<LeafVertex> = new Set();
65
69
 
66
70
  /** lock down access */
67
71
  private dirty_list: SpreadsheetVertexBase[] = [];
@@ -102,7 +106,7 @@ export abstract class Graph implements GraphCallbacks {
102
106
  this.dirty_list = [];
103
107
  this.volatile_list = [];
104
108
  this.vertices = [[]];
105
- this.leaf_vertices = [];
109
+ this.leaf_vertices.clear();
106
110
  // this.cells_map = {};
107
111
 
108
112
  /** array vertex maintains its own list */
@@ -812,28 +816,12 @@ export abstract class Graph implements GraphCallbacks {
812
816
  * managing and maintaining these vertices: we only need references.
813
817
  */
814
818
  public AddLeafVertex(vertex: LeafVertex): void {
815
-
816
- // ... don't add more than once. this is expensive but
817
- // the list should (generally speaking) be short, so not
818
- // a serious problem atm
819
-
820
- /*
821
- if (this.leaf_vertices.some((test) => test === vertex)) {
822
- return;
823
- }
824
- */
825
- for (const test of this.leaf_vertices) {
826
- if (test === vertex) {
827
- return;
828
- }
829
- }
830
-
831
- this.leaf_vertices.push(vertex);
819
+ this.leaf_vertices.add(vertex);
832
820
  }
833
821
 
834
- /** removes vertex, by match */
822
+ /** removes vertex */
835
823
  public RemoveLeafVertex(vertex: LeafVertex): void {
836
- this.leaf_vertices = this.leaf_vertices.filter((test) => test !== vertex);
824
+ this.leaf_vertices.delete(vertex);
837
825
  }
838
826
 
839
827
  /**
@@ -40,12 +40,12 @@ import { Color } from './vertex';
40
40
  * have both leaf- and spreadsheet-vertex extend that.
41
41
  *
42
42
  */
43
- export class LeafVertex extends SpreadsheetVertex {
43
+ export class StateLeafVertex extends SpreadsheetVertex {
44
44
 
45
- public static type = 'leaf-vertex';
45
+ public static type = 'state-leaf-vertex';
46
46
 
47
47
  public state_id = 0;
48
- public type = LeafVertex.type; // for type guard
48
+ public type = StateLeafVertex.type; // for type guard
49
49
 
50
50
  /**
51
51
  * leaf vertex defaults to black (i.e. tested) because leaf nodes cannot have
@@ -112,10 +112,17 @@ export interface CompositeFunctionDescriptor {
112
112
  fn: (...args: any[]) => UnionValue; // UnionOrArray; // |UnitAddress|UnitRange;
113
113
 
114
114
  /**
115
- * for the future. some functions should not be available in
116
- * spreadsheet cells (charts, basically)
115
+ * limited visibility
116
+ *
117
+ * internal functions do not show up in the spreadsheet. we have an
118
+ * annotation value which should be usef in the future but it's not
119
+ * implemented yet.
120
+ *
121
+ * should we allow these functions to be used, and just not tooltip them;
122
+ * or block them entirely? for now we'll do the former as it's helpful to
123
+ * defug.
117
124
  */
118
- visibility?: string;
125
+ visibility?: 'internal'|'annotation';
119
126
 
120
127
  /**
121
128
  * for the future
@@ -821,7 +821,7 @@ export class ExpressionCalculator {
821
821
  const value: UnionValue[][] = [];
822
822
 
823
823
  for (let c = 0; c < columns; c++) {
824
- const col = [];
824
+ const col: UnionValue[] = [];
825
825
  for (let r = 0; r < rows; r++ ) {
826
826
  col[r] = fn(left_values[c][r], right_values[c][r]);
827
827
  }
@@ -1,24 +1,24 @@
1
- /*
2
- * This file is part of TREB.
3
- *
4
- * TREB is free software: you can redistribute it and/or modify it under the
5
- * terms of the GNU General Public License as published by the Free Software
6
- * Foundation, either version 3 of the License, or (at your option) any
7
- * later version.
8
- *
9
- * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
- * details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
- *
17
- * Copyright 2022-2023 trebco, llc.
18
- * info@treb.app
19
- *
20
- */
21
-
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
22
  import type {
23
23
  ExtendedFunctionDescriptor, CompositeFunctionDescriptor,
24
24
  FunctionMap, ExtendedFunctionMap } from './descriptors';
@@ -80,9 +80,12 @@ export class FunctionLibrary {
80
80
  }
81
81
 
82
82
  /** get a list, for AC services */
83
- public List() {
83
+ public List(filter_internal = true) {
84
84
  const list: ExtendedFunctionMap = {};
85
85
  for (const key of Object.keys(this.functions)) {
86
+ if (filter_internal && this.functions[key].visibility === 'internal') {
87
+ continue;
88
+ }
86
89
  list[key] = this.functions[key];
87
90
  }
88
91
  return list;