@loaders.gl/graphs 4.5.3 → 5.0.0-alpha.11

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 (77) hide show
  1. package/LICENSE +14 -3
  2. package/README.md +122 -10
  3. package/dist/dot-loader-types.d.ts +40 -3
  4. package/dist/dot-loader-types.d.ts.map +1 -1
  5. package/dist/dot-loader-types.js +8 -2
  6. package/dist/dot-loader-types.js.map +1 -1
  7. package/dist/dot-loader.cjs +1449 -108
  8. package/dist/dot-loader.cjs.map +3 -4
  9. package/dist/dot-loader.d.ts +11 -6
  10. package/dist/dot-loader.d.ts.map +1 -1
  11. package/dist/dot-loader.js +3 -3
  12. package/dist/dot-loader.js.map +1 -1
  13. package/dist/dot-types.d.ts +6 -1
  14. package/dist/dot-types.d.ts.map +1 -1
  15. package/dist/gexf-loader-types.d.ts +53 -0
  16. package/dist/gexf-loader-types.d.ts.map +1 -0
  17. package/dist/gexf-loader-types.js +26 -0
  18. package/dist/gexf-loader-types.js.map +1 -0
  19. package/dist/gexf-loader.cjs +1304 -0
  20. package/dist/gexf-loader.cjs.map +6 -0
  21. package/dist/gexf-loader.d.ts +24 -0
  22. package/dist/gexf-loader.d.ts.map +1 -0
  23. package/dist/gexf-loader.js +13 -0
  24. package/dist/gexf-loader.js.map +1 -0
  25. package/dist/gexf-types.d.ts +16 -0
  26. package/dist/gexf-types.d.ts.map +1 -0
  27. package/dist/gexf-types.js +5 -0
  28. package/dist/gexf-types.js.map +1 -0
  29. package/dist/graph-types.d.ts +28 -0
  30. package/dist/graph-types.d.ts.map +1 -1
  31. package/dist/graphml-loader-types.d.ts +39 -3
  32. package/dist/graphml-loader-types.d.ts.map +1 -1
  33. package/dist/graphml-loader-types.js +8 -2
  34. package/dist/graphml-loader-types.js.map +1 -1
  35. package/dist/graphml-loader.cjs +1006 -61
  36. package/dist/graphml-loader.cjs.map +3 -4
  37. package/dist/graphml-loader.d.ts +11 -6
  38. package/dist/graphml-loader.d.ts.map +1 -1
  39. package/dist/graphml-loader.js +3 -3
  40. package/dist/graphml-loader.js.map +1 -1
  41. package/dist/index.cjs +1452 -470
  42. package/dist/index.cjs.map +3 -4
  43. package/dist/index.d.ts +9 -2
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -2
  46. package/dist/index.js.map +1 -1
  47. package/dist/lib/build-graph-tables.d.ts +4 -0
  48. package/dist/lib/build-graph-tables.d.ts.map +1 -0
  49. package/dist/lib/build-graph-tables.js +143 -0
  50. package/dist/lib/build-graph-tables.js.map +1 -0
  51. package/dist/lib/parse-dot.d.ts +3 -1
  52. package/dist/lib/parse-dot.d.ts.map +1 -1
  53. package/dist/lib/parse-dot.js +41 -24
  54. package/dist/lib/parse-dot.js.map +1 -1
  55. package/dist/lib/parse-gexf.d.ts +5 -0
  56. package/dist/lib/parse-gexf.d.ts.map +1 -0
  57. package/dist/lib/parse-gexf.js +380 -0
  58. package/dist/lib/parse-gexf.js.map +1 -0
  59. package/dist/lib/parse-graphml.d.ts +2 -1
  60. package/dist/lib/parse-graphml.d.ts.map +1 -1
  61. package/dist/lib/parse-graphml.js +50 -27
  62. package/dist/lib/parse-graphml.js.map +1 -1
  63. package/package.json +15 -6
  64. package/src/dot-loader-types.ts +21 -4
  65. package/src/dot-loader.ts +7 -4
  66. package/src/dot-types.ts +7 -1
  67. package/src/gexf-loader-types.ts +41 -0
  68. package/src/gexf-loader.ts +17 -0
  69. package/src/gexf-types.ts +21 -0
  70. package/src/graph-types.ts +35 -0
  71. package/src/graphml-loader-types.ts +20 -4
  72. package/src/graphml-loader.ts +7 -4
  73. package/src/index.ts +11 -2
  74. package/src/lib/build-graph-tables.ts +208 -0
  75. package/src/lib/parse-dot.ts +47 -24
  76. package/src/lib/parse-gexf.ts +388 -0
  77. package/src/lib/parse-graphml.ts +86 -34
package/LICENSE CHANGED
@@ -24,8 +24,20 @@ THE SOFTWARE.
24
24
 
25
25
  Copyright (c) 2015 Uber Technologies, Inc.
26
26
 
27
- loaders.gl includes certain files from Cesium (https://github.com/AnalyticalGraphicsInc/cesium)
28
- under the Apache 2 License (found in the submodule: modules/3d-tiles):)
27
+ Portions of modules/images/src/lib/category-api/binary-image-api.ts are based on
28
+ binary-gltf-utils (https://github.com/Qantas94Heavy/binary-gltf-utils) under the
29
+ MIT License reproduced above.
30
+
31
+ Copyright (c) 2016-17 Karl Cheng
32
+
33
+ Portions of modules/schema-utils/src/lib/utils/async-queue.ts are adapted from
34
+ async-iter-demo (https://github.com/rauschma/async-iter-demo) under the MIT
35
+ License reproduced above.
36
+
37
+ Copyright (c) 2016 Axel Rauschmayer
38
+
39
+ loaders.gl includes certain files from Cesium (https://github.com/CesiumGS/cesium)
40
+ under the Apache 2.0 License, including files in modules/3d-tiles.
29
41
 
30
42
  Copyright 2011-2018 CesiumJS Contributors
31
43
 
@@ -38,4 +50,3 @@ Unless required by applicable law or agreed to in writing, software
38
50
  distributed under the License is distributed on an "AS IS" BASIS,
39
51
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
40
52
  See the License for the specific language governing permissions and limitations under the License.
41
-
package/README.md CHANGED
@@ -1,6 +1,65 @@
1
1
  # @loaders.gl/graphs
2
2
 
3
- Framework-independent loaders for GraphML and Graphviz DOT documents.
3
+ Framework-independent loaders for GraphML, Graphviz DOT, and GEXF documents.
4
+
5
+ ## Graph output shapes
6
+
7
+ Graph loaders default to `graphml.shape: 'arrow-table'`, `dot.shape: 'arrow-table'`,
8
+ or `gexf.shape: 'arrow-table'`.
9
+ The result uses the standard table collection shape:
10
+
11
+ ```typescript
12
+ {
13
+ shape: 'tables',
14
+ tables: [
15
+ {name: 'nodes', table: {shape: 'arrow-table', schema, data: nodes}},
16
+ {name: 'edges', table: {shape: 'arrow-table', schema, data: edges}}
17
+ ]
18
+ }
19
+ ```
20
+
21
+ Each `data` is an Apache Arrow `Table`; each `schema` is a loaders.gl schema.
22
+ The node table has `id`, nullable `label`, and nullable `attributes` columns.
23
+ The edge table additionally has `sourceId`, `targetId`, and `directed`.
24
+ Structural identifiers are strings, including numeric DOT edge IDs. Row order follows
25
+ document order after DOT strict-edge coalescing. Edges may reference undeclared nodes;
26
+ the loaders preserve their endpoints without inventing GraphML nodes.
27
+
28
+ Application attributes live in a typed `attributes` struct, so keys such as `id` cannot
29
+ replace structural columns. GraphML declarations determine Boolean, Int32, Int64,
30
+ Float32, Float64, and Utf8 fields, including unused declarations on empty graphs.
31
+ GraphML `long` values are parsed as exact integers and read as `bigint`.
32
+ Invalid or out-of-range integer values make the affected attribute column Utf8,
33
+ preserving values as strings. DOT scalar types are inferred across the whole column;
34
+ numbers use Float64, booleans use Bool, and mixed scalar types use Utf8. Nested DOT
35
+ subgraph membership uses List and Struct columns. Missing values become Arrow nulls.
36
+ Empty undeclared attributes have a Struct with no child fields.
37
+
38
+ ```typescript
39
+ const graph = await load('network.graphml', GraphMLLoader);
40
+ if (graph.shape === 'tables' && graph.tables[0].table.shape === 'arrow-table') {
41
+ const nodes = graph.tables[0].table.data;
42
+ console.log(nodes.getChild('id')?.get(0));
43
+ }
44
+ ```
45
+
46
+ Select `'object-row-table'` for the same named table collection with object arrays in
47
+ `table.data`. This mode also preserves GraphML long values as `bigint`; it retains original
48
+ application attribute values rather than applying Arrow column normalization.
49
+
50
+ For compatibility with existing graph-layer consumers, request plain graph records:
51
+
52
+ ```typescript
53
+ const graph = await load('network.graphml', GraphMLLoader, {
54
+ graphml: {shape: 'plain-graph-data'}
55
+ });
56
+ // DOT: {dot: {shape: 'plain-graph-data'}}
57
+ ```
58
+
59
+ Plain output retains `shape: 'plain-graph-data'`, `nodes`, and `edges`, with original
60
+ DOT edge ID types. GraphML long values in this compatibility mode remain JavaScript
61
+ numbers and can lose precision outside the safe integer range.
62
+ DOT graph metadata is available as `graph.metadata` in every output shape.
4
63
 
5
64
  ## GraphML loader
6
65
 
@@ -13,11 +72,11 @@ import {GraphMLLoader} from '@loaders.gl/graphs';
13
72
  const graph = await load('network.graphml', GraphMLLoader);
14
73
  ```
15
74
 
16
- Pass `GraphMLLoader` to `parseSync` from `@loaders.gl/core` for synchronous parsing.
17
- The direct parser subpath also exports `GraphMLLoaderWithParser` from
18
- `@loaders.gl/graphs/graphml-loader`.
75
+ For synchronous parsing, import `GraphMLLoaderWithParser` from
76
+ `@loaders.gl/graphs/graphml-loader` and pass it to `parseSync` from `@loaders.gl/core`.
77
+ The package root exports metadata only; asynchronous core APIs preload the implementation.
19
78
 
20
- The result is `GraphData` with `shape: 'plain-graph-data'`, `nodes`, and `edges`.
79
+ The explicit plain compatibility result is `GraphData` with `shape: 'plain-graph-data'`, `nodes`, and `edges`.
21
80
  Nodes have `id`, optional `label`, and optional `attributes`. Edges additionally have
22
81
  `sourceId`, `targetId`, and `directed`. This shape is compatible with
23
82
  `createGraphFromData` in `@deck.gl-community/graph-layers`.
@@ -25,13 +84,14 @@ Nodes have `id`, optional `label`, and optional `attributes`. Edges additionally
25
84
  Supported constructs include node and edge identifiers, generated IDs for unnamed edges,
26
85
  `edgedefault` and per-edge direction overrides, node/edge/all keys, typed data and defaults,
27
86
  unknown data keys, and namespace-prefixed elements. Numeric and boolean keys become JavaScript
28
- values; other values remain strings. Nested XML data becomes a JSON string.
87
+ values; string values preserve their whitespace. Nested XML data becomes a JSON string.
29
88
 
30
89
  Only the first graph is returned. Nested graphs, hyperedges, ports, and graph-level data are
31
90
  ignored. Nodes without IDs and edges without endpoints are skipped. This is a permissive
32
91
  parser, not a GraphML schema validator. Long integers use JavaScript numbers and may lose
33
92
  precision outside the safe integer range.
34
93
 
94
+
35
95
  ## DOT loader
36
96
 
37
97
  ```typescript
@@ -41,12 +101,13 @@ import {DOTLoader} from '@loaders.gl/graphs';
41
101
  const graph = await load('network.dot', DOTLoader);
42
102
  ```
43
103
 
44
- Pass `DOTLoader` to `parseSync` for synchronous text or UTF-8 `ArrayBuffer` parsing.
45
- The direct parser subpath also exports `DOTLoaderWithParser` from
46
- `@loaders.gl/graphs/dot-loader`. `DOTLoader` recognizes `.dot` and `.gv` files.
104
+ Use `DOTLoaderWithParser` from `@loaders.gl/graphs/dot-loader` with `parseSync`
105
+ for synchronous text or UTF-8 `ArrayBuffer` parsing. `DOTLoader` recognizes `.dot` and `.gv` files.
47
106
 
48
- The loader returns the same plain `GraphData` node/edge shape as GraphML, plus typed
107
+ The loader returns the same named node/edge table collection as GraphML, plus typed
49
108
  DOT metadata: graph ID, direction, strictness, graph attributes, and subgraph descriptors.
109
+ Unknown backslash sequences are preserved for downstream attribute interpretation.
110
+ Backslashes followed by physical line endings join quoted identifiers and labels across lines.
50
111
  Identifiers remain strings, including numeric-looking IDs. Unquoted numeric attributes
51
112
  become numbers; quoted attributes remain strings. Node and edge `label` attributes are
52
113
  also exposed as record labels.
@@ -64,3 +125,54 @@ This is a parser for the supported DOT subset, not a Graphviz renderer. Node por
64
125
  subgraph endpoints in edge statements, and concatenated quoted strings are unsupported.
65
126
  Port syntax is rejected; identifiers containing colons must be quoted. Truncated input,
66
127
  trailing content, and edge operators inconsistent with the graph declaration are rejected.
128
+
129
+ ## GEXF loader
130
+
131
+ `GEXFLoader` reads static GEXF 1.2 (including `1.2draft`) and 1.3 documents.
132
+
133
+ ```typescript
134
+ import {load} from '@loaders.gl/core';
135
+ import {GEXFLoader} from '@loaders.gl/graphs';
136
+
137
+ const graph = await load('network.gexf', GEXFLoader);
138
+ // Optional: {gexf: {shape: 'object-row-table'}} or {gexf: {shape: 'plain-graph-data'}}
139
+ ```
140
+
141
+ For synchronous parsing, use `GEXFLoaderWithParser` from
142
+ `@loaders.gl/graphs/gexf-loader` with `parseSync`. The package root exports metadata
143
+ only; asynchronous core APIs preload the parser. Text and UTF-8 binary inputs are supported.
144
+ The loader recognizes `.gexf` and `application/gexf+xml`.
145
+
146
+ The default result contains named Arrow node and edge tables in the standard `tables`
147
+ collection. Application attributes use declaration titles inside the `attributes` struct;
148
+ node and edge declarations are scoped separately. Boolean, integer, long, float, double,
149
+ and string declarations retain their Arrow types, even for empty graphs. Byte and short
150
+ attributes use Int32. `anyURI`, date, char, bigdecimal, and biginteger values retain their text
151
+ as Utf8. Long integers remain exact `bigint` values in every output shape, including
152
+ plain records. Invalid or out-of-range scalar values promote the affected Arrow field
153
+ to Utf8, preserving the original text.
154
+
155
+ List attributes become typed Arrow Lists, including unused declarations. Both bracketed
156
+ comma-separated lists and legacy pipe/comma/semicolon-separated values are accepted.
157
+ Single and double quotes preserve embedded delimiters and whitespace; malformed
158
+ list quoting is rejected. An empty value becomes an empty list. Defaults apply before explicit values; absent
159
+ attributes without defaults become Arrow nulls. String values and labels preserve whitespace.
160
+
161
+ Native edge weight and kind properties are retained under `attributes.gexf.weight` and
162
+ `attributes.gexf.kind`. Namespaced color, position, size, shape, and thickness elements
163
+ are retained as nested structs under `attributes.gexf.viz`, with numeric coordinates,
164
+ color components, sizes, and thicknesses. Shape names, image URIs, and hex colors remain
165
+ strings. The application attribute title `gexf` is reserved to prevent collisions.
166
+
167
+ `graph.metadata` contains the document version, default direction, and an `attributes`
168
+ object with creator, description, keywords, and lastmodifieddate when supplied.
169
+ Directed and undirected edges, per-edge direction overrides, self-loops, and parallel
170
+ edges are preserved in document order. IDs remain strings; missing edge IDs receive
171
+ stable `edge-<index>` identifiers that avoid collisions with supplied IDs.
172
+
173
+ This is a static graph parser, not a complete GEXF schema validator. Dynamic graphs,
174
+ slice graphs, temporal values/spells, hierarchical/parent structures, mutual edges,
175
+ unsupported attribute types, and document type declarations are rejected explicitly.
176
+ Duplicate IDs or attribute declarations, undeclared application attributes, missing
177
+ required record attributes, and endpoints referencing undeclared nodes are rejected.
178
+ Foreign namespace extensions are ignored. See the [GEXF specification](https://gexf.net/schema.html).
@@ -1,4 +1,35 @@
1
- import type { DOTGraphData } from "./dot-types.js";
1
+ import type { DOTOutput } from "./dot-types.js";
2
+ import type { GraphShape } from "./graph-types.js";
3
+ /** Options for selecting the DOT graph output representation. */
4
+ export type DOTLoaderOptions = {
5
+ /** Format-specific graph options. */
6
+ dot?: {
7
+ /** Representation of each named table; defaults to Arrow. */
8
+ shape?: GraphShape;
9
+ };
10
+ };
11
+ /** Preloads the DOT parser implementation. */
12
+ declare function preload(): Promise<{
13
+ parse: (data: ArrayBuffer, options?: DOTLoaderOptions) => Promise<DOTOutput>;
14
+ parseSync: (data: ArrayBuffer, options?: DOTLoaderOptions) => DOTOutput;
15
+ parseTextSync: (data: string, options?: DOTLoaderOptions) => DOTOutput;
16
+ name: "DOT";
17
+ id: "dot";
18
+ module: "graphs";
19
+ version: any;
20
+ extensions: ["dot", "gv"];
21
+ mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"];
22
+ text: true;
23
+ worker: false;
24
+ dataType: DOTOutput;
25
+ batchType: never;
26
+ options: {
27
+ readonly dot: {
28
+ readonly shape: "arrow-table";
29
+ };
30
+ };
31
+ preload: typeof preload;
32
+ }>;
2
33
  /** Metadata-only loader for Graphviz DOT documents. */
3
34
  export declare const DOTLoader: {
4
35
  readonly name: "DOT";
@@ -9,8 +40,14 @@ export declare const DOTLoader: {
9
40
  readonly mimeTypes: ["text/vnd.graphviz", "text/x-graphviz", "application/vnd.graphviz"];
10
41
  readonly text: true;
11
42
  readonly worker: false;
12
- readonly dataType: DOTGraphData;
43
+ readonly dataType: DOTOutput;
13
44
  readonly batchType: never;
14
- readonly options: {};
45
+ readonly options: {
46
+ readonly dot: {
47
+ readonly shape: "arrow-table";
48
+ };
49
+ };
50
+ readonly preload: typeof preload;
15
51
  };
52
+ export {};
16
53
  //# sourceMappingURL=dot-loader-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dot-loader-types.d.ts","sourceRoot":"","sources":["../src/dot-loader-types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,YAAY,EAAC,uBAAoB;AAK9C,uDAAuD;AACvD,eAAO,MAAM,SAAS;;;;;;;;;uBASS,YAAY;wBACtB,KAAK;;CAEsB,CAAC"}
1
+ {"version":3,"file":"dot-loader-types.d.ts","sourceRoot":"","sources":["../src/dot-loader-types.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,SAAS,EAAC,uBAAoB;AAC3C,OAAO,KAAK,EAAC,UAAU,EAAC,yBAAsB;AAE9C,iEAAiE;AACjE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qCAAqC;IACrC,GAAG,CAAC,EAAE;QACJ,6DAA6D;QAC7D,KAAK,CAAC,EAAE,UAAU,CAAC;KACpB,CAAC;CACH,CAAC;AAKF,8CAA8C;AAC9C,iBAAe,OAAO;;;;;;;;;;;;cAeS,SAAS;eACnB,KAAK;;;;;;;GAbzB;AAED,uDAAuD;AACvD,eAAO,MAAM,SAAS;;;;;;;;;uBASS,SAAS;wBACnB,KAAK;;;;;;;CAGqC,CAAC"}
@@ -2,7 +2,12 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
  // @ts-ignore __VERSION__ is injected by the build.
5
- const VERSION = typeof "4.5.3" !== 'undefined' ? "4.5.3" : 'latest';
5
+ const VERSION = typeof "5.0.0-alpha.11" !== 'undefined' ? "5.0.0-alpha.11" : 'latest';
6
+ /** Preloads the DOT parser implementation. */
7
+ async function preload() {
8
+ const { DOTLoaderWithParser } = await import('@loaders.gl/graphs/dot-loader');
9
+ return DOTLoaderWithParser;
10
+ }
6
11
  /** Metadata-only loader for Graphviz DOT documents. */
7
12
  export const DOTLoader = {
8
13
  name: 'DOT',
@@ -15,6 +20,7 @@ export const DOTLoader = {
15
20
  worker: false,
16
21
  dataType: null,
17
22
  batchType: null,
18
- options: {}
23
+ options: { dot: { shape: 'arrow-table' } },
24
+ preload
19
25
  };
20
26
  //# sourceMappingURL=dot-loader-types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dot-loader-types.js","sourceRoot":"","sources":["../src/dot-loader-types.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,+BAA+B;AAC/B,oCAAoC;AAKpC,mDAAmD;AACnD,MAAM,OAAO,GAAG,cAAkB,KAAK,WAAW,CAAC,CAAC,SAAa,CAAC,CAAC,QAAQ,CAAC;AAE5E,uDAAuD;AACvD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,IAAI,EAAE,KAAK;IACX,EAAE,EAAE,KAAK;IACT,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IACzB,SAAS,EAAE,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,0BAA0B,CAAC;IAC/E,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,IAA+B;IACzC,SAAS,EAAE,IAAa;IACxB,OAAO,EAAE,EAAE;CACmC,CAAC"}
1
+ {"version":3,"file":"dot-loader-types.js","sourceRoot":"","sources":["../src/dot-loader-types.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,+BAA+B;AAC/B,oCAAoC;AAepC,mDAAmD;AACnD,MAAM,OAAO,GAAG,uBAAkB,KAAK,WAAW,CAAC,CAAC,kBAAa,CAAC,CAAC,QAAQ,CAAC;AAE5E,8CAA8C;AAC9C,KAAK,UAAU,OAAO;IACpB,MAAM,EAAC,mBAAmB,EAAC,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;IAC5E,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,IAAI,EAAE,KAAK;IACX,EAAE,EAAE,KAAK;IACT,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC;IACzB,SAAS,EAAE,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,0BAA0B,CAAC;IAC/E,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,IAA4B;IACtC,SAAS,EAAE,IAAa;IACxB,OAAO,EAAE,EAAC,GAAG,EAAE,EAAC,KAAK,EAAE,aAAa,EAAC,EAAC;IACtC,OAAO;CACsD,CAAC"}