@graphty/graph-io 0.3.25 → 0.3.26

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 (581) hide show
  1. package/README.md +49 -414
  2. package/dist/chunks/children-CL3Cy0ez.js.map +1 -1
  3. package/dist/chunks/choose-BbJI55dx.js +56 -0
  4. package/dist/chunks/choose-BbJI55dx.js.map +1 -0
  5. package/dist/chunks/constants-BCsFsMj4.js +231 -0
  6. package/dist/chunks/constants-BCsFsMj4.js.map +1 -0
  7. package/dist/chunks/{escape-B-tkk_Cl.js → escape-D0g6NNUy.js} +382 -92
  8. package/dist/chunks/escape-D0g6NNUy.js.map +1 -0
  9. package/dist/chunks/export-BTI4yQgy.js +4333 -0
  10. package/dist/chunks/export-BTI4yQgy.js.map +1 -0
  11. package/dist/chunks/exporter-BMqk5oxW.js +3465 -0
  12. package/dist/chunks/exporter-BMqk5oxW.js.map +1 -0
  13. package/dist/chunks/{importer-eUREhBGj.js → exporter-Cra2GYcN.js} +4969 -3201
  14. package/dist/chunks/exporter-Cra2GYcN.js.map +1 -0
  15. package/dist/chunks/{exporter-BGrsWamJ.js → exporter-Dxh231ZF.js} +38 -229
  16. package/dist/chunks/exporter-Dxh231ZF.js.map +1 -0
  17. package/dist/chunks/{exporter-DIeGJXAZ.js → exporter-tne475KK.js} +22 -20
  18. package/dist/chunks/exporter-tne475KK.js.map +1 -0
  19. package/dist/chunks/importer-90YWhJoF.js +2811 -0
  20. package/dist/chunks/importer-90YWhJoF.js.map +1 -0
  21. package/dist/chunks/{importer-D_e7e7LX.js → importer-Bcl1d4xH.js} +398 -145
  22. package/dist/chunks/importer-Bcl1d4xH.js.map +1 -0
  23. package/dist/chunks/{importer-BWY2FFc5.js → importer-BfIsp1f9.js} +255 -77
  24. package/dist/chunks/importer-BfIsp1f9.js.map +1 -0
  25. package/dist/chunks/{importer-zGLo8Dg_.js → importer-C_TEA1zJ.js} +484 -157
  26. package/dist/chunks/importer-C_TEA1zJ.js.map +1 -0
  27. package/dist/chunks/{importer-DET1tg6s.js → importer-DCjOvO7U.js} +1687 -310
  28. package/dist/chunks/importer-DCjOvO7U.js.map +1 -0
  29. package/dist/chunks/{importer-vi3bSdtw.js → importer-DfVu6j59.js} +509 -76
  30. package/dist/chunks/importer-DfVu6j59.js.map +1 -0
  31. package/dist/chunks/{importer-DIrbbnAf.js → importer-Dku_VAIY.js} +585 -226
  32. package/dist/chunks/importer-Dku_VAIY.js.map +1 -0
  33. package/dist/chunks/json-elements-3tnyt5uZ.js +1225 -0
  34. package/dist/chunks/json-elements-3tnyt5uZ.js.map +1 -0
  35. package/dist/chunks/ontology-export-B9Tcf37D.js +357 -0
  36. package/dist/chunks/ontology-export-B9Tcf37D.js.map +1 -0
  37. package/dist/chunks/{records-dbRkxwaq.js → records-CQXT__mY.js} +298 -114
  38. package/dist/chunks/records-CQXT__mY.js.map +1 -0
  39. package/dist/chunks/{text-Dr0Ifpag.js → text-DmcUs5_Q.js} +29 -11
  40. package/dist/chunks/text-DmcUs5_Q.js.map +1 -0
  41. package/dist/chunks/{writer-C7flM-Ih.js → writer-DxjgHwSe.js} +19 -1
  42. package/dist/chunks/writer-DxjgHwSe.js.map +1 -0
  43. package/dist/csv.js +951 -261
  44. package/dist/csv.js.map +1 -1
  45. package/dist/cx.js +6 -3
  46. package/dist/cx2.js +2 -2
  47. package/dist/cys.js +6 -3
  48. package/dist/dot.js +1 -1
  49. package/dist/gexf.js +554 -122
  50. package/dist/gexf.js.map +1 -1
  51. package/dist/gml.js +342 -85
  52. package/dist/gml.js.map +1 -1
  53. package/dist/graph-io.js +1105 -213
  54. package/dist/graph-io.js.map +1 -1
  55. package/dist/graphml.js +3 -2
  56. package/dist/graphml.js.map +1 -1
  57. package/dist/json.js +3 -2
  58. package/dist/neo4j.js +564 -157
  59. package/dist/neo4j.js.map +1 -1
  60. package/dist/obo.js +6 -3
  61. package/dist/pajek.js +1 -1
  62. package/dist/src/children.d.ts +18 -6
  63. package/dist/src/children.d.ts.map +1 -1
  64. package/dist/src/children.js +6 -3
  65. package/dist/src/children.js.map +1 -1
  66. package/dist/src/common/attributes.d.ts +29 -11
  67. package/dist/src/common/attributes.d.ts.map +1 -1
  68. package/dist/src/common/attributes.js +25 -7
  69. package/dist/src/common/attributes.js.map +1 -1
  70. package/dist/src/common/cell-budget.d.ts +9 -2
  71. package/dist/src/common/cell-budget.d.ts.map +1 -1
  72. package/dist/src/common/cell-budget.js +11 -3
  73. package/dist/src/common/cell-budget.js.map +1 -1
  74. package/dist/src/common/choose.d.ts +19 -0
  75. package/dist/src/common/choose.d.ts.map +1 -0
  76. package/dist/src/common/choose.js +72 -0
  77. package/dist/src/common/choose.js.map +1 -0
  78. package/dist/src/common/codes.d.ts +456 -66
  79. package/dist/src/common/codes.d.ts.map +1 -1
  80. package/dist/src/common/codes.js +458 -66
  81. package/dist/src/common/codes.js.map +1 -1
  82. package/dist/src/common/compare.d.ts +81 -0
  83. package/dist/src/common/compare.d.ts.map +1 -0
  84. package/dist/src/common/compare.js +394 -0
  85. package/dist/src/common/compare.js.map +1 -0
  86. package/dist/src/common/cx-export.d.ts +123 -0
  87. package/dist/src/common/cx-export.d.ts.map +1 -0
  88. package/dist/src/common/cx-export.js +334 -0
  89. package/dist/src/common/cx-export.js.map +1 -0
  90. package/dist/src/common/declared-types.d.ts +22 -2
  91. package/dist/src/common/declared-types.d.ts.map +1 -1
  92. package/dist/src/common/declared-types.js +19 -1
  93. package/dist/src/common/declared-types.js.map +1 -1
  94. package/dist/src/common/direction.d.ts +74 -50
  95. package/dist/src/common/direction.d.ts.map +1 -1
  96. package/dist/src/common/direction.js +47 -27
  97. package/dist/src/common/direction.js.map +1 -1
  98. package/dist/src/common/escape.d.ts +21 -9
  99. package/dist/src/common/escape.d.ts.map +1 -1
  100. package/dist/src/common/escape.js +33 -17
  101. package/dist/src/common/escape.js.map +1 -1
  102. package/dist/src/common/export.d.ts +144 -32
  103. package/dist/src/common/export.d.ts.map +1 -1
  104. package/dist/src/common/export.js +216 -42
  105. package/dist/src/common/export.js.map +1 -1
  106. package/dist/src/common/format.d.ts +23 -1
  107. package/dist/src/common/format.d.ts.map +1 -1
  108. package/dist/src/common/format.js +26 -1
  109. package/dist/src/common/format.js.map +1 -1
  110. package/dist/src/common/ids.d.ts +9 -2
  111. package/dist/src/common/ids.d.ts.map +1 -1
  112. package/dist/src/common/ids.js +6 -2
  113. package/dist/src/common/ids.js.map +1 -1
  114. package/dist/src/common/input.d.ts +122 -28
  115. package/dist/src/common/input.d.ts.map +1 -1
  116. package/dist/src/common/input.js +890 -124
  117. package/dist/src/common/input.js.map +1 -1
  118. package/dist/src/common/json-elements.d.ts +144 -20
  119. package/dist/src/common/json-elements.d.ts.map +1 -1
  120. package/dist/src/common/json-elements.js +868 -188
  121. package/dist/src/common/json-elements.js.map +1 -1
  122. package/dist/src/common/line-format.d.ts +90 -0
  123. package/dist/src/common/line-format.d.ts.map +1 -0
  124. package/dist/src/common/line-format.js +185 -0
  125. package/dist/src/common/line-format.js.map +1 -0
  126. package/dist/src/common/lists.d.ts +6 -1
  127. package/dist/src/common/lists.d.ts.map +1 -1
  128. package/dist/src/common/lists.js +2 -0
  129. package/dist/src/common/lists.js.map +1 -1
  130. package/dist/src/common/ontology-export.d.ts +167 -0
  131. package/dist/src/common/ontology-export.d.ts.map +1 -0
  132. package/dist/src/common/ontology-export.js +359 -0
  133. package/dist/src/common/ontology-export.js.map +1 -0
  134. package/dist/src/common/ontology.d.ts +25 -3
  135. package/dist/src/common/ontology.d.ts.map +1 -1
  136. package/dist/src/common/ontology.js +30 -9
  137. package/dist/src/common/ontology.js.map +1 -1
  138. package/dist/src/common/options.d.ts +62 -12
  139. package/dist/src/common/options.d.ts.map +1 -1
  140. package/dist/src/common/options.js +89 -11
  141. package/dist/src/common/options.js.map +1 -1
  142. package/dist/src/common/plural.d.ts +31 -0
  143. package/dist/src/common/plural.d.ts.map +1 -0
  144. package/dist/src/common/plural.js +46 -0
  145. package/dist/src/common/plural.js.map +1 -0
  146. package/dist/src/common/report.d.ts +72 -14
  147. package/dist/src/common/report.d.ts.map +1 -1
  148. package/dist/src/common/report.js +146 -22
  149. package/dist/src/common/report.js.map +1 -1
  150. package/dist/src/common/temporal.d.ts +22 -5
  151. package/dist/src/common/temporal.d.ts.map +1 -1
  152. package/dist/src/common/temporal.js +13 -2
  153. package/dist/src/common/temporal.js.map +1 -1
  154. package/dist/src/common/text.d.ts +39 -23
  155. package/dist/src/common/text.d.ts.map +1 -1
  156. package/dist/src/common/text.js +51 -21
  157. package/dist/src/common/text.js.map +1 -1
  158. package/dist/src/common/weights.d.ts +37 -4
  159. package/dist/src/common/weights.d.ts.map +1 -1
  160. package/dist/src/common/weights.js +61 -2
  161. package/dist/src/common/weights.js.map +1 -1
  162. package/dist/src/common/writer.d.ts +19 -3
  163. package/dist/src/common/writer.d.ts.map +1 -1
  164. package/dist/src/common/writer.js +30 -2
  165. package/dist/src/common/writer.js.map +1 -1
  166. package/dist/src/common/xml.d.ts +125 -9
  167. package/dist/src/common/xml.d.ts.map +1 -1
  168. package/dist/src/common/xml.js +400 -83
  169. package/dist/src/common/xml.js.map +1 -1
  170. package/dist/src/common/zip.d.ts +44 -4
  171. package/dist/src/common/zip.d.ts.map +1 -1
  172. package/dist/src/common/zip.js +134 -5
  173. package/dist/src/common/zip.js.map +1 -1
  174. package/dist/src/formats/csv/exporter.d.ts +80 -24
  175. package/dist/src/formats/csv/exporter.d.ts.map +1 -1
  176. package/dist/src/formats/csv/exporter.js +145 -32
  177. package/dist/src/formats/csv/exporter.js.map +1 -1
  178. package/dist/src/formats/csv/header.d.ts +38 -9
  179. package/dist/src/formats/csv/header.d.ts.map +1 -1
  180. package/dist/src/formats/csv/header.js +46 -10
  181. package/dist/src/formats/csv/header.js.map +1 -1
  182. package/dist/src/formats/csv/importer.d.ts +187 -37
  183. package/dist/src/formats/csv/importer.d.ts.map +1 -1
  184. package/dist/src/formats/csv/importer.js +835 -204
  185. package/dist/src/formats/csv/importer.js.map +1 -1
  186. package/dist/src/formats/csv/index.d.ts +100 -19
  187. package/dist/src/formats/csv/index.d.ts.map +1 -1
  188. package/dist/src/formats/csv/index.js +94 -21
  189. package/dist/src/formats/csv/index.js.map +1 -1
  190. package/dist/src/formats/csv/records.d.ts +95 -10
  191. package/dist/src/formats/csv/records.d.ts.map +1 -1
  192. package/dist/src/formats/csv/records.js +333 -122
  193. package/dist/src/formats/csv/records.js.map +1 -1
  194. package/dist/src/formats/csv/values.d.ts +1 -0
  195. package/dist/src/formats/csv/values.d.ts.map +1 -1
  196. package/dist/src/formats/csv/values.js +1 -0
  197. package/dist/src/formats/csv/values.js.map +1 -1
  198. package/dist/src/formats/cx/exporter.d.ts +102 -0
  199. package/dist/src/formats/cx/exporter.d.ts.map +1 -0
  200. package/dist/src/formats/cx/exporter.js +1217 -0
  201. package/dist/src/formats/cx/exporter.js.map +1 -0
  202. package/dist/src/formats/cx/importer.d.ts +79 -32
  203. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  204. package/dist/src/formats/cx/importer.js +680 -285
  205. package/dist/src/formats/cx/importer.js.map +1 -1
  206. package/dist/src/formats/cx/index.d.ts +4 -3
  207. package/dist/src/formats/cx/index.d.ts.map +1 -1
  208. package/dist/src/formats/cx/index.js +4 -3
  209. package/dist/src/formats/cx/index.js.map +1 -1
  210. package/dist/src/formats/cx2/exporter.d.ts +29 -11
  211. package/dist/src/formats/cx2/exporter.d.ts.map +1 -1
  212. package/dist/src/formats/cx2/exporter.js +39 -268
  213. package/dist/src/formats/cx2/exporter.js.map +1 -1
  214. package/dist/src/formats/cx2/importer.d.ts +78 -28
  215. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  216. package/dist/src/formats/cx2/importer.js +226 -79
  217. package/dist/src/formats/cx2/importer.js.map +1 -1
  218. package/dist/src/formats/cx2/index.d.ts +2 -1
  219. package/dist/src/formats/cx2/index.d.ts.map +1 -1
  220. package/dist/src/formats/cx2/index.js +2 -1
  221. package/dist/src/formats/cx2/index.js.map +1 -1
  222. package/dist/src/formats/cys/constants.d.ts +66 -17
  223. package/dist/src/formats/cys/constants.d.ts.map +1 -1
  224. package/dist/src/formats/cys/constants.js +59 -18
  225. package/dist/src/formats/cys/constants.js.map +1 -1
  226. package/dist/src/formats/cys/exporter.d.ts +118 -0
  227. package/dist/src/formats/cys/exporter.d.ts.map +1 -0
  228. package/dist/src/formats/cys/exporter.js +1072 -0
  229. package/dist/src/formats/cys/exporter.js.map +1 -0
  230. package/dist/src/formats/cys/importer.d.ts +22 -8
  231. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  232. package/dist/src/formats/cys/importer.js +510 -149
  233. package/dist/src/formats/cys/importer.js.map +1 -1
  234. package/dist/src/formats/cys/index.d.ts +4 -2
  235. package/dist/src/formats/cys/index.d.ts.map +1 -1
  236. package/dist/src/formats/cys/index.js +4 -2
  237. package/dist/src/formats/cys/index.js.map +1 -1
  238. package/dist/src/formats/cys/session.d.ts +46 -7
  239. package/dist/src/formats/cys/session.d.ts.map +1 -1
  240. package/dist/src/formats/cys/session.js +98 -24
  241. package/dist/src/formats/cys/session.js.map +1 -1
  242. package/dist/src/formats/cys/tables.d.ts +9 -2
  243. package/dist/src/formats/cys/tables.d.ts.map +1 -1
  244. package/dist/src/formats/cys/tables.js +29 -7
  245. package/dist/src/formats/cys/tables.js.map +1 -1
  246. package/dist/src/formats/dot/exporter.d.ts +42 -14
  247. package/dist/src/formats/dot/exporter.d.ts.map +1 -1
  248. package/dist/src/formats/dot/exporter.js +56 -29
  249. package/dist/src/formats/dot/exporter.js.map +1 -1
  250. package/dist/src/formats/dot/importer.d.ts +91 -29
  251. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  252. package/dist/src/formats/dot/importer.js +190 -39
  253. package/dist/src/formats/dot/importer.js.map +1 -1
  254. package/dist/src/formats/dot/index.d.ts +2 -1
  255. package/dist/src/formats/dot/index.d.ts.map +1 -1
  256. package/dist/src/formats/dot/index.js +2 -1
  257. package/dist/src/formats/dot/index.js.map +1 -1
  258. package/dist/src/formats/dot/names.d.ts +44 -11
  259. package/dist/src/formats/dot/names.d.ts.map +1 -1
  260. package/dist/src/formats/dot/names.js +44 -11
  261. package/dist/src/formats/dot/names.js.map +1 -1
  262. package/dist/src/formats/dot/tokenizer.d.ts +9 -2
  263. package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
  264. package/dist/src/formats/dot/tokenizer.js +20 -5
  265. package/dist/src/formats/dot/tokenizer.js.map +1 -1
  266. package/dist/src/formats/gexf/exporter.d.ts +46 -15
  267. package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
  268. package/dist/src/formats/gexf/exporter.js +45 -15
  269. package/dist/src/formats/gexf/exporter.js.map +1 -1
  270. package/dist/src/formats/gexf/importer.d.ts +87 -23
  271. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  272. package/dist/src/formats/gexf/importer.js +471 -90
  273. package/dist/src/formats/gexf/importer.js.map +1 -1
  274. package/dist/src/formats/gexf/index.d.ts +84 -21
  275. package/dist/src/formats/gexf/index.d.ts.map +1 -1
  276. package/dist/src/formats/gexf/index.js +80 -23
  277. package/dist/src/formats/gexf/index.js.map +1 -1
  278. package/dist/src/formats/gexf/schema.d.ts +67 -15
  279. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  280. package/dist/src/formats/gexf/schema.js +59 -13
  281. package/dist/src/formats/gexf/schema.js.map +1 -1
  282. package/dist/src/formats/gml/exporter.d.ts +69 -21
  283. package/dist/src/formats/gml/exporter.d.ts.map +1 -1
  284. package/dist/src/formats/gml/exporter.js +74 -29
  285. package/dist/src/formats/gml/exporter.js.map +1 -1
  286. package/dist/src/formats/gml/importer.d.ts +116 -25
  287. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  288. package/dist/src/formats/gml/importer.js +290 -61
  289. package/dist/src/formats/gml/importer.js.map +1 -1
  290. package/dist/src/formats/gml/index.d.ts +87 -24
  291. package/dist/src/formats/gml/index.d.ts.map +1 -1
  292. package/dist/src/formats/gml/index.js +79 -26
  293. package/dist/src/formats/gml/index.js.map +1 -1
  294. package/dist/src/formats/gml/syntax.d.ts +67 -18
  295. package/dist/src/formats/gml/syntax.d.ts.map +1 -1
  296. package/dist/src/formats/gml/syntax.js +108 -26
  297. package/dist/src/formats/gml/syntax.js.map +1 -1
  298. package/dist/src/formats/graphml/constants.d.ts +174 -44
  299. package/dist/src/formats/graphml/constants.d.ts.map +1 -1
  300. package/dist/src/formats/graphml/constants.js +165 -44
  301. package/dist/src/formats/graphml/constants.js.map +1 -1
  302. package/dist/src/formats/graphml/exporter.d.ts +17 -9
  303. package/dist/src/formats/graphml/exporter.d.ts.map +1 -1
  304. package/dist/src/formats/graphml/exporter.js +33 -12
  305. package/dist/src/formats/graphml/exporter.js.map +1 -1
  306. package/dist/src/formats/graphml/importer.d.ts +19 -7
  307. package/dist/src/formats/graphml/importer.d.ts.map +1 -1
  308. package/dist/src/formats/graphml/importer.js +466 -39
  309. package/dist/src/formats/graphml/importer.js.map +1 -1
  310. package/dist/src/formats/graphml/index.d.ts +2 -1
  311. package/dist/src/formats/graphml/index.d.ts.map +1 -1
  312. package/dist/src/formats/graphml/index.js +2 -1
  313. package/dist/src/formats/graphml/index.js.map +1 -1
  314. package/dist/src/formats/graphml/tree.d.ts +6 -2
  315. package/dist/src/formats/graphml/tree.d.ts.map +1 -1
  316. package/dist/src/formats/graphml/tree.js +6 -2
  317. package/dist/src/formats/graphml/tree.js.map +1 -1
  318. package/dist/src/formats/graphml/yfiles.d.ts +8 -3
  319. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  320. package/dist/src/formats/graphml/yfiles.js +36 -15
  321. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  322. package/dist/src/formats/json/dialect.d.ts +88 -24
  323. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  324. package/dist/src/formats/json/dialect.js +109 -19
  325. package/dist/src/formats/json/dialect.js.map +1 -1
  326. package/dist/src/formats/json/exporter.d.ts +134 -22
  327. package/dist/src/formats/json/exporter.d.ts.map +1 -1
  328. package/dist/src/formats/json/exporter.js +135 -54
  329. package/dist/src/formats/json/exporter.js.map +1 -1
  330. package/dist/src/formats/json/importer.d.ts +173 -52
  331. package/dist/src/formats/json/importer.d.ts.map +1 -1
  332. package/dist/src/formats/json/importer.js +899 -220
  333. package/dist/src/formats/json/importer.js.map +1 -1
  334. package/dist/src/formats/json/index.d.ts +3 -2
  335. package/dist/src/formats/json/index.d.ts.map +1 -1
  336. package/dist/src/formats/json/index.js +3 -2
  337. package/dist/src/formats/json/index.js.map +1 -1
  338. package/dist/src/formats/json/obographs-export.d.ts +68 -0
  339. package/dist/src/formats/json/obographs-export.d.ts.map +1 -0
  340. package/dist/src/formats/json/obographs-export.js +941 -0
  341. package/dist/src/formats/json/obographs-export.js.map +1 -0
  342. package/dist/src/formats/json/obographs.d.ts +26 -0
  343. package/dist/src/formats/json/obographs.d.ts.map +1 -1
  344. package/dist/src/formats/json/obographs.js +297 -80
  345. package/dist/src/formats/json/obographs.js.map +1 -1
  346. package/dist/src/formats/neo4j/exporter.d.ts +109 -21
  347. package/dist/src/formats/neo4j/exporter.d.ts.map +1 -1
  348. package/dist/src/formats/neo4j/exporter.js +238 -85
  349. package/dist/src/formats/neo4j/exporter.js.map +1 -1
  350. package/dist/src/formats/neo4j/header.d.ts +17 -4
  351. package/dist/src/formats/neo4j/header.d.ts.map +1 -1
  352. package/dist/src/formats/neo4j/header.js +36 -4
  353. package/dist/src/formats/neo4j/header.js.map +1 -1
  354. package/dist/src/formats/neo4j/importer.d.ts +107 -27
  355. package/dist/src/formats/neo4j/importer.d.ts.map +1 -1
  356. package/dist/src/formats/neo4j/importer.js +415 -63
  357. package/dist/src/formats/neo4j/importer.js.map +1 -1
  358. package/dist/src/formats/neo4j/index.d.ts +73 -23
  359. package/dist/src/formats/neo4j/index.d.ts.map +1 -1
  360. package/dist/src/formats/neo4j/index.js +65 -25
  361. package/dist/src/formats/neo4j/index.js.map +1 -1
  362. package/dist/src/formats/obo/exporter.d.ts +150 -0
  363. package/dist/src/formats/obo/exporter.d.ts.map +1 -0
  364. package/dist/src/formats/obo/exporter.js +1736 -0
  365. package/dist/src/formats/obo/exporter.js.map +1 -0
  366. package/dist/src/formats/obo/importer.d.ts +95 -19
  367. package/dist/src/formats/obo/importer.d.ts.map +1 -1
  368. package/dist/src/formats/obo/importer.js +475 -104
  369. package/dist/src/formats/obo/importer.js.map +1 -1
  370. package/dist/src/formats/obo/index.d.ts +6 -3
  371. package/dist/src/formats/obo/index.d.ts.map +1 -1
  372. package/dist/src/formats/obo/index.js +6 -3
  373. package/dist/src/formats/obo/index.js.map +1 -1
  374. package/dist/src/formats/obo/syntax.d.ts +108 -4
  375. package/dist/src/formats/obo/syntax.d.ts.map +1 -1
  376. package/dist/src/formats/obo/syntax.js +211 -34
  377. package/dist/src/formats/obo/syntax.js.map +1 -1
  378. package/dist/src/formats/pajek/exporter.d.ts +54 -16
  379. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  380. package/dist/src/formats/pajek/exporter.js +66 -34
  381. package/dist/src/formats/pajek/exporter.js.map +1 -1
  382. package/dist/src/formats/pajek/importer.d.ts +84 -22
  383. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  384. package/dist/src/formats/pajek/importer.js +303 -83
  385. package/dist/src/formats/pajek/importer.js.map +1 -1
  386. package/dist/src/formats/pajek/index.d.ts +2 -1
  387. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  388. package/dist/src/formats/pajek/index.js +2 -1
  389. package/dist/src/formats/pajek/index.js.map +1 -1
  390. package/dist/src/formats/pajek/syntax.d.ts +77 -14
  391. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  392. package/dist/src/formats/pajek/syntax.js +183 -51
  393. package/dist/src/formats/pajek/syntax.js.map +1 -1
  394. package/dist/src/formats/xgmml/columns.d.ts +1 -0
  395. package/dist/src/formats/xgmml/columns.d.ts.map +1 -1
  396. package/dist/src/formats/xgmml/columns.js +4 -0
  397. package/dist/src/formats/xgmml/columns.js.map +1 -1
  398. package/dist/src/formats/xgmml/constants.d.ts +186 -56
  399. package/dist/src/formats/xgmml/constants.d.ts.map +1 -1
  400. package/dist/src/formats/xgmml/constants.js +181 -57
  401. package/dist/src/formats/xgmml/constants.js.map +1 -1
  402. package/dist/src/formats/xgmml/document.d.ts +65 -11
  403. package/dist/src/formats/xgmml/document.d.ts.map +1 -1
  404. package/dist/src/formats/xgmml/document.js +157 -28
  405. package/dist/src/formats/xgmml/document.js.map +1 -1
  406. package/dist/src/formats/xgmml/emit.d.ts +61 -3
  407. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  408. package/dist/src/formats/xgmml/emit.js +129 -26
  409. package/dist/src/formats/xgmml/emit.js.map +1 -1
  410. package/dist/src/formats/xgmml/exporter.d.ts +13 -6
  411. package/dist/src/formats/xgmml/exporter.d.ts.map +1 -1
  412. package/dist/src/formats/xgmml/exporter.js +20 -21
  413. package/dist/src/formats/xgmml/exporter.js.map +1 -1
  414. package/dist/src/formats/xgmml/importer.d.ts +33 -12
  415. package/dist/src/formats/xgmml/importer.d.ts.map +1 -1
  416. package/dist/src/formats/xgmml/importer.js +35 -72
  417. package/dist/src/formats/xgmml/importer.js.map +1 -1
  418. package/dist/src/formats/xgmml/index.d.ts +1 -0
  419. package/dist/src/formats/xgmml/index.d.ts.map +1 -1
  420. package/dist/src/formats/xgmml/index.js +1 -0
  421. package/dist/src/formats/xgmml/index.js.map +1 -1
  422. package/dist/src/formats/xgmml/values.d.ts +8 -1
  423. package/dist/src/formats/xgmml/values.d.ts.map +1 -1
  424. package/dist/src/formats/xgmml/values.js +7 -2
  425. package/dist/src/formats/xgmml/values.js.map +1 -1
  426. package/dist/src/index.d.ts +23 -18
  427. package/dist/src/index.d.ts.map +1 -1
  428. package/dist/src/index.js +28 -16
  429. package/dist/src/index.js.map +1 -1
  430. package/dist/src/registry.d.ts +478 -92
  431. package/dist/src/registry.d.ts.map +1 -1
  432. package/dist/src/registry.js +807 -88
  433. package/dist/src/registry.js.map +1 -1
  434. package/dist/src/sniff.d.ts +61 -19
  435. package/dist/src/sniff.d.ts.map +1 -1
  436. package/dist/src/sniff.js +121 -29
  437. package/dist/src/sniff.js.map +1 -1
  438. package/dist/src/types.d.ts +362 -112
  439. package/dist/src/types.d.ts.map +1 -1
  440. package/dist/src/types.js +28 -7
  441. package/dist/src/types.js.map +1 -1
  442. package/dist/xgmml.js +2 -2
  443. package/docs/samples/README.md +25 -0
  444. package/docs/samples/got-edges.csv +353 -0
  445. package/docs/samples/got-network.graphml +1384 -0
  446. package/docs/samples/got-nodes.csv +108 -0
  447. package/docs/samples/got.cx +930 -0
  448. package/docs/samples/got.cx2 +465 -0
  449. package/docs/samples/got.gexf +471 -0
  450. package/docs/samples/got.gml +2650 -0
  451. package/docs/samples/got.json +2546 -0
  452. package/docs/samples/got.net +461 -0
  453. package/docs/samples/movies-nodes.csv +9 -0
  454. package/docs/samples/movies-rels.csv +8 -0
  455. package/docs/samples/networks.cys +0 -0
  456. package/docs/samples/proteins.xgmml +9 -0
  457. package/docs/samples/teams.gv +24 -0
  458. package/docs/samples/vehicles.obo +25 -0
  459. package/package.json +9 -4
  460. package/src/children.ts +18 -6
  461. package/src/common/attributes.ts +29 -11
  462. package/src/common/cell-budget.ts +11 -3
  463. package/src/common/choose.ts +89 -0
  464. package/src/common/codes.ts +490 -66
  465. package/src/common/compare.ts +472 -0
  466. package/src/common/cx-export.ts +432 -0
  467. package/src/common/declared-types.ts +38 -4
  468. package/src/common/direction.ts +78 -51
  469. package/src/common/escape.ts +33 -17
  470. package/src/common/export.ts +284 -47
  471. package/src/common/format.ts +30 -1
  472. package/src/common/ids.ts +14 -3
  473. package/src/common/input.ts +1057 -134
  474. package/src/common/json-elements.ts +1034 -198
  475. package/src/common/line-format.ts +249 -0
  476. package/src/common/lists.ts +6 -1
  477. package/src/common/ontology-export.ts +461 -0
  478. package/src/common/ontology.ts +31 -9
  479. package/src/common/options.ts +110 -15
  480. package/src/common/plural.ts +49 -0
  481. package/src/common/report.ts +168 -25
  482. package/src/common/temporal.ts +22 -5
  483. package/src/common/text.ts +62 -23
  484. package/src/common/weights.ts +74 -4
  485. package/src/common/writer.ts +37 -3
  486. package/src/common/xml.ts +477 -88
  487. package/src/common/zip.ts +169 -7
  488. package/src/formats/csv/exporter.ts +201 -46
  489. package/src/formats/csv/header.ts +50 -11
  490. package/src/formats/csv/importer.ts +1133 -245
  491. package/src/formats/csv/index.ts +106 -19
  492. package/src/formats/csv/records.ts +396 -122
  493. package/src/formats/csv/values.ts +1 -0
  494. package/src/formats/cx/exporter.ts +1483 -0
  495. package/src/formats/cx/importer.ts +888 -300
  496. package/src/formats/cx/index.ts +4 -3
  497. package/src/formats/cx2/exporter.ts +61 -338
  498. package/src/formats/cx2/importer.ts +317 -86
  499. package/src/formats/cx2/index.ts +2 -1
  500. package/src/formats/cys/constants.ts +62 -17
  501. package/src/formats/cys/exporter.ts +1368 -0
  502. package/src/formats/cys/importer.ts +659 -157
  503. package/src/formats/cys/index.ts +4 -2
  504. package/src/formats/cys/session.ts +139 -31
  505. package/src/formats/cys/tables.ts +47 -9
  506. package/src/formats/dot/exporter.ts +83 -37
  507. package/src/formats/dot/importer.ts +248 -54
  508. package/src/formats/dot/index.ts +2 -1
  509. package/src/formats/dot/names.ts +44 -11
  510. package/src/formats/dot/tokenizer.ts +25 -6
  511. package/src/formats/gexf/exporter.ts +57 -18
  512. package/src/formats/gexf/importer.ts +636 -105
  513. package/src/formats/gexf/index.ts +90 -21
  514. package/src/formats/gexf/schema.ts +67 -15
  515. package/src/formats/gml/exporter.ts +90 -36
  516. package/src/formats/gml/importer.ts +388 -67
  517. package/src/formats/gml/index.ts +85 -24
  518. package/src/formats/gml/syntax.ts +111 -26
  519. package/src/formats/graphml/constants.ts +178 -44
  520. package/src/formats/graphml/exporter.ts +52 -18
  521. package/src/formats/graphml/importer.ts +640 -60
  522. package/src/formats/graphml/index.ts +2 -1
  523. package/src/formats/graphml/tree.ts +6 -2
  524. package/src/formats/graphml/yfiles.ts +37 -15
  525. package/src/formats/json/dialect.ts +128 -29
  526. package/src/formats/json/exporter.ts +205 -68
  527. package/src/formats/json/importer.ts +1163 -253
  528. package/src/formats/json/index.ts +3 -1
  529. package/src/formats/json/obographs-export.ts +1197 -0
  530. package/src/formats/json/obographs.ts +353 -92
  531. package/src/formats/neo4j/exporter.ts +320 -101
  532. package/src/formats/neo4j/header.ts +44 -6
  533. package/src/formats/neo4j/importer.ts +512 -73
  534. package/src/formats/neo4j/index.ts +75 -23
  535. package/src/formats/obo/exporter.ts +2210 -0
  536. package/src/formats/obo/importer.ts +622 -109
  537. package/src/formats/obo/index.ts +6 -3
  538. package/src/formats/obo/syntax.ts +232 -37
  539. package/src/formats/pajek/exporter.ts +89 -41
  540. package/src/formats/pajek/importer.ts +407 -93
  541. package/src/formats/pajek/index.ts +2 -1
  542. package/src/formats/pajek/syntax.ts +213 -52
  543. package/src/formats/xgmml/columns.ts +10 -0
  544. package/src/formats/xgmml/constants.ts +183 -56
  545. package/src/formats/xgmml/document.ts +212 -34
  546. package/src/formats/xgmml/emit.ts +175 -34
  547. package/src/formats/xgmml/exporter.ts +35 -27
  548. package/src/formats/xgmml/importer.ts +64 -86
  549. package/src/formats/xgmml/index.ts +1 -0
  550. package/src/formats/xgmml/values.ts +11 -3
  551. package/src/index.ts +81 -11
  552. package/src/registry.ts +1121 -135
  553. package/src/sniff.ts +163 -32
  554. package/src/types.ts +385 -114
  555. package/dist/chunks/escape-B-tkk_Cl.js.map +0 -1
  556. package/dist/chunks/export-Bh60Dv-n.js +0 -582
  557. package/dist/chunks/export-Bh60Dv-n.js.map +0 -1
  558. package/dist/chunks/exporter-BGrsWamJ.js.map +0 -1
  559. package/dist/chunks/exporter-DIeGJXAZ.js.map +0 -1
  560. package/dist/chunks/importer-BWY2FFc5.js.map +0 -1
  561. package/dist/chunks/importer-DD-xv9_Y.js +0 -1471
  562. package/dist/chunks/importer-DD-xv9_Y.js.map +0 -1
  563. package/dist/chunks/importer-DET1tg6s.js.map +0 -1
  564. package/dist/chunks/importer-DEcKhsmQ.js +0 -1614
  565. package/dist/chunks/importer-DEcKhsmQ.js.map +0 -1
  566. package/dist/chunks/importer-DIrbbnAf.js.map +0 -1
  567. package/dist/chunks/importer-D_e7e7LX.js.map +0 -1
  568. package/dist/chunks/importer-eUREhBGj.js.map +0 -1
  569. package/dist/chunks/importer-vi3bSdtw.js.map +0 -1
  570. package/dist/chunks/importer-zGLo8Dg_.js.map +0 -1
  571. package/dist/chunks/json-elements-DDS8N2Dd.js +0 -779
  572. package/dist/chunks/json-elements-DDS8N2Dd.js.map +0 -1
  573. package/dist/chunks/ontology-BnrJ4I98.js +0 -113
  574. package/dist/chunks/ontology-BnrJ4I98.js.map +0 -1
  575. package/dist/chunks/records-dbRkxwaq.js.map +0 -1
  576. package/dist/chunks/report-B1z4WT9e.js +0 -2372
  577. package/dist/chunks/report-B1z4WT9e.js.map +0 -1
  578. package/dist/chunks/text-Dr0Ifpag.js.map +0 -1
  579. package/dist/chunks/weights-Dzba96G3.js +0 -176
  580. package/dist/chunks/weights-Dzba96G3.js.map +0 -1
  581. package/dist/chunks/writer-C7flM-Ih.js.map +0 -1
package/src/types.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
- * The io contract types of @graphty/graph-io (design section 12.4, normative): what every importer
2
+ * The io contract types of @graphty/graph-io: what every importer
3
3
  * and exporter implements and what every caller of one programs against. They are declared here
4
4
  * rather than in the core because ImportInput and CommonImportOptions reference ReadableStream and
5
5
  * AbortSignal, which need the DOM lib (or @types/node >= 18); the core's public types reference only
6
6
  * ES2020 globals (decision D-IO-TYPES). Every declaration is transcribed verbatim from the design;
7
- * the behaviour behind each option is specified in sections 8.4 (import), 8.5 (export) and 8.6
7
+ * the behavior behind each option is specified in sections 8.4 (import), 8.5 (export) and 8.6
8
8
  * (report and error aggregation).
9
9
  */
10
10
 
@@ -18,76 +18,188 @@ import {
18
18
  } from "@graphty/graph-format";
19
19
 
20
20
  /**
21
- * What an importer reads (design section 8.4): whole text, whole bytes, a byte stream (a browser
21
+ * What an importer reads: whole text, whole bytes, a byte stream (a browser
22
22
  * `File.stream()`, a fetch body) or an async iterable of text or byte chunks. Bytes are decoded
23
23
  * strictly in the encoding the `encoding` option, a byte order mark or the file's own declaration
24
24
  * names, else as UTF-8 (undeclared bytes that are not UTF-8 are read as windows-1252 with a
25
25
  * warning), so an invalid sequence is a parse-error and never a silent U+FFFD that could alias two ids.
26
+ * @category Loading
26
27
  */
27
28
  export type ImportInput = string | Uint8Array | ReadableStream<Uint8Array> | AsyncIterable<string | Uint8Array>;
28
29
 
29
30
  /**
30
- * The options every importer accepts next to its format-specific ones (design section 8.4). The
31
+ * The options every importer accepts next to its format-specific ones. The
31
32
  * builder-policy fields (`addMissingNodes`, `duplicateEdges`, `selfLoops`, `weightDtype`) seed the
32
33
  * registry's builder; on a caller's sink they are read back from `sink.options` and every option the
33
- * sink cannot honour is reported.
34
+ * sink cannot honor is reported.
35
+ * @category Loading
34
36
  */
35
37
  export interface CommonImportOptions {
36
38
  /**
37
- * Id coercion rule applied before an id reaches the sink (design section 4.1): "canonical" by default for
38
- * text-cell formats, "keep" for JSON.
39
+ * How id text becomes a node id. "canonical": integer text such as "42" becomes the number 42
40
+ * and everything else ("042", "4.2", "a") stays text. "string": every id stays text. "number":
41
+ * every id is read as a number, so "042" and "42" become one node (with a warning) and text that
42
+ * is not a number is an error. "keep": ids keep the type the file gives them. The default is
43
+ * "keep" for JSON, OBO, XGMML, CX, CX2 and Cytoscape sessions, and "canonical" for the other
44
+ * formats.
45
+ * @defaultValue per format
39
46
  */
40
47
  ids?: IdCoercion | undefined;
41
- /** Which field becomes the node id; "id" by default; "label" / "index" resolve the GML / Pajek / d3 ambiguity. */
48
+ /**
49
+ * Which value becomes the node id: the file's own id ("id"), the node's label ("label"), or its
50
+ * position among the nodes, counting from 0 ("index"). Use it when a file's ids are meaningless
51
+ * numbers and the labels are the real names. In d3 JSON, "index" also reads edges whose ends are
52
+ * node positions. In GML and Pajek it only renames: every node still needs its id key or vertex
53
+ * number, because edges refer to nodes by it, and a GML node without an `id` key is skipped
54
+ * with E_MISSING_ID. CSV reads this option only when there is a node table, and it does not
55
+ * just rename: with "label" the node table's label column (`label`, or the `labelColumn`
56
+ * option) gives the ids, so the edge table must name its nodes by those labels.
57
+ * @defaultValue "id"
58
+ */
42
59
  nodeIdFrom?: "id" | "label" | "index" | undefined;
43
- /** Whether an edge may reference an undeclared node (default true; the GEXF importer defaults false for edges). */
60
+ /**
61
+ * Whether an edge may name a node the file never declares; that node is then created. When
62
+ * false, such an edge is skipped as an error. The default is false for GEXF, XGMML, CX, CX2 and
63
+ * Cytoscape sessions, whose files must declare every node, and true for the other formats.
64
+ * @defaultValue per format
65
+ */
44
66
  addMissingNodes?: boolean | undefined;
45
- /** The builder's duplicate-edge policy seed; default "keep". */
67
+ /**
68
+ * What to do with a second edge between the same two nodes: "keep" keeps both, "first" / "last"
69
+ * keep one, "sum" / "min" / "max" keep one with the weights combined, and "error" stops the
70
+ * import. Merged edges are reported once as W_EDGES_MERGED.
71
+ * @defaultValue "keep"
72
+ */
46
73
  duplicateEdges?: DuplicatePolicy | undefined;
47
- /** The builder's self-loop policy seed; default "keep". */
74
+ /**
75
+ * What to do with an edge from a node to itself: "keep", "drop" (reported once as
76
+ * W_SELF_LOOPS_DROPPED with the number removed), or "error" to stop the import.
77
+ * @defaultValue "keep"
78
+ */
48
79
  selfLoops?: "keep" | "drop" | "error" | undefined;
49
- /** What to do with a file whose edges disagree on direction (design section 3.6); default "expand". */
80
+ /**
81
+ * How edge direction is read. "expand" (the default) keeps the file's direction, and for a file
82
+ * that has both directed and undirected edges makes a directed graph in which each undirected
83
+ * edge is two edges, marked so an export can write them back as one. "directed" / "undirected"
84
+ * read every edge of any file that way, including a file whose edges all have the other
85
+ * direction, with a W_DIRECTION_FORCED warning. "error" stops the import at the first edge whose
86
+ * direction differs from the file's.
87
+ * @defaultValue "expand"
88
+ */
50
89
  onMixedDirection?: "expand" | "directed" | "undirected" | "error" | undefined;
51
- /** The direction assumed for a file that declares none (GEXF: undirected per spec). */
90
+ /**
91
+ * Whether the graph is directed when the file does not say. The default is undirected for
92
+ * GraphML, GEXF, GML, JSON and XGMML, and directed for CSV, Pajek and Cytoscape sessions. DOT,
93
+ * Neo4j, CX, CX2 and OBO files always settle the direction themselves (DOT by `graph` or
94
+ * `digraph`; the others are always directed), so those formats do not read this option and
95
+ * report it as W_OPTION_IGNORED.
96
+ * @defaultValue per format
97
+ */
52
98
  defaultDirected?: boolean | undefined;
53
- /** The attribute that becomes THE weight (per-format default: "weight", GML "value"); null = unweighted. */
99
+ /**
100
+ * The edge attribute read as the edge weight. The default is "weight", except "value" for GML
101
+ * and Pajek and none for OBO. Pass null to read every attribute as a plain attribute and leave
102
+ * the graph unweighted. A name no edge has leaves the graph unweighted, with a W_WEIGHT_NOT_FOUND
103
+ * warning: one options object with `weightFrom: "weight"` shared across formats reads GML and
104
+ * Pajek files, which keep their weights in `value`, without weights. An edge whose weight cell is
105
+ * empty or missing gets the default weight 1, and an export writes no weight for it.
106
+ * @defaultValue per format
107
+ */
54
108
  weightFrom?: string | null | undefined;
55
- /** Weight staging precision; "f64" for every importer by default so 0.1 and 16777217 survive. */
109
+ /**
110
+ * Whether weights a 32-bit float cannot hold exactly are also kept exactly. "f64" keeps them in
111
+ * an edge column that `snapshot.edges.byRole("weight")` finds, so 0.1 and 16777217
112
+ * stay exact. "f32" keeps no such column and uses less memory: the 32-bit weight arrays
113
+ * `snapshot.weights` and `snapshot.edgeList().weights`, which every import fills, are then the
114
+ * only weights.
115
+ * @defaultValue "f64"
116
+ */
56
117
  weightDtype?: "f32" | "f64" | undefined;
57
- /** How a declared `long` column is stored: "f64" (default) or "string" (design section 5.1). */
118
+ /**
119
+ * How a column the file declares as a 64-bit integer is stored: "f64" (a number, exact up to
120
+ * 2^53) or "string" (every digit kept, as text). GML declares no types, so there it applies to a
121
+ * key whose integer values go beyond 2^53.
122
+ * @defaultValue "f64"
123
+ */
58
124
  long?: "f64" | "string" | undefined;
59
- /** Restore ids mangled by sanitizeIds "mangle" from the graphty:originalId attribute (default true). */
125
+ /**
126
+ * Whether to give back the original ids that an export with `sanitizeIds: "mangle"` had to
127
+ * rewrite. The export writes them to the file in an attribute whose name each format page
128
+ * gives. When false, the rewritten ids stay the ids and the originals are an ordinary node
129
+ * attribute, named after the format's spelling: `graphty.originalId` in GraphML,
130
+ * `graphty_originalId` in GML and Pajek, `graphty:originalId` in CX, CX2 and Cytoscape sessions,
131
+ * and a `graphty:originalId` entry of the `property_value` attribute in OBO.
132
+ * @defaultValue true
133
+ */
60
134
  restoreMangledIds?: boolean | undefined;
61
- /** GraphML / JGF hyperedges: refuse, skip with a report entry (default), or expand to a star / clique. */
135
+ /**
136
+ * What to do with a GraphML or JGF hyperedge (an edge with more than two ends): "skip" leaves it
137
+ * out with a warning, "error" stops the import, and "star" and "clique" turn it into ordinary
138
+ * edges. "clique" joins every pair of ends. "star" works differently per format: GraphML adds a
139
+ * new hub node joined to every end, while JGF makes the hyperedge's first node the hub, so no
140
+ * node is added. A directed JGF hyperedge (`source` and `target` arrays) becomes one edge from
141
+ * every source to every target under both. In JGF every edge made from a hyperedge carries the
142
+ * hyperedge's id, label, relation and metadata; GraphML drops a hyperedge's `<data>` and its
143
+ * `<desc>`, with a warning.
144
+ * @defaultValue "skip"
145
+ */
62
146
  hyperedges?: "error" | "skip" | "star" | "clique" | undefined;
63
- /** Errors tolerated before the importer aborts with E_IMPORT (default 100). */
147
+ /**
148
+ * How many errors an import tolerates. Each error skips one node, edge or value and is listed in
149
+ * the report; one error more than this stops the import with an ImportError. Pass 0 to stop at
150
+ * the first error.
151
+ * @defaultValue 100
152
+ */
64
153
  errorLimit?: number | undefined;
65
- /** Cancellation; the importer stops between chunks and rejects with the signal's reason. */
154
+ /**
155
+ * Cancels the import. When it aborts, the import stops and rejects with the signal's reason
156
+ * (an AbortError, or a TimeoutError from `AbortSignal.timeout()`).
157
+ */
66
158
  signal?: AbortSignal | undefined;
67
- /** Progress in bytes; `bytesTotal` is known for in-memory input only. */
159
+ /**
160
+ * Called as the input is read, with the bytes read so far and the total. For a string or a
161
+ * Uint8Array the total is known from the first call. For a stream (which includes loadFromUrl()
162
+ * and loadFromFile()) it is undefined until the last call, which always has
163
+ * `bytesDone === bytesTotal`. Text counts its UTF-8 length.
164
+ */
68
165
  onProgress?: ((bytesDone: number, bytesTotal?: number) => void) | undefined;
69
166
  /**
70
- * The character encoding of byte input (a WHATWG label such as "utf-8", "windows-1252",
71
- * "iso-8859-1", "utf-16le"); overrides the byte order mark and any encoding the file declares.
72
- * Absent: a BOM decides, else the declaration (XML prolog, DOT `charset`), else UTF-8, and
73
- * bytes that are not valid UTF-8 are read as windows-1252 with a warning. Ignored for text input.
167
+ * The character encoding of byte input, as a label such as "utf-8", "windows-1252" or
168
+ * "utf-16le". Without it graph-io uses a byte order mark, then the encoding the file declares
169
+ * (an XML declaration, DOT's `charset`), then UTF-8, and reads bytes that are not UTF-8 as
170
+ * windows-1252 with a warning. A byte order mark wins over this option. A string input is
171
+ * already text: setting this option for one adds a W_OPTION_IGNORED warning, once per input (a
172
+ * CSV import with a `nodes` table has two inputs).
74
173
  */
75
174
  encoding?: string | undefined;
76
175
  }
77
176
 
78
177
  /**
79
- * Which graph of an input that holds several to read: by position or by name, never both. An
80
- * importer of a format that can hold several graphs (a Cytoscape session, a CX collection, a JGF
81
- * or OBO Graphs `graphs` array) accepts these next to its own options; absent, it reads the first.
178
+ * Which graph to read from a file that holds several: by position or by name, never both. Without
179
+ * either, the first graph is read.
180
+ * @category Loading
82
181
  */
83
182
  export interface GraphChoiceOptions {
84
- /** The 0-based position of the graph, as `GraphListing.index` gives it. */
183
+ /**
184
+ * The 0-based position of the graph to read from a file that holds several (`listGraphs()`
185
+ * gives each graph's `index`). A position past the last graph stops the import with an
186
+ * ImportError whose `issue.code` is E_GRAPH_NOT_FOUND; its message lists the file's graphs.
187
+ * @defaultValue 0
188
+ */
85
189
  graphIndex?: number | undefined;
86
- /** The name of the graph, as `GraphListing.name` gives it; a name two graphs share is refused. */
190
+ /**
191
+ * The name of the graph to read from a file that holds several (`listGraphs()` gives each
192
+ * graph's `name`). A name no graph has stops the import with an ImportError whose `issue.code`
193
+ * is E_GRAPH_NOT_FOUND, and a name two graphs share with one whose `issue.code` is
194
+ * E_AMBIGUOUS_GRAPH_NAME.
195
+ */
87
196
  graphName?: string | undefined;
88
197
  }
89
198
 
90
- /** One graph of an input that can hold several, as an importer's listGraphs() describes it. */
199
+ /**
200
+ * One graph of an input that can hold several, as an importer's listGraphs() describes it.
201
+ * @category Loading
202
+ */
91
203
  export interface GraphListing {
92
204
  /** The value graphIndex takes to read it. */
93
205
  readonly index: number;
@@ -100,37 +212,49 @@ export interface GraphListing {
100
212
  }
101
213
 
102
214
  /**
103
- * An importer plugin (design section 8.4): pushes scalars into the caller's sink in one pass and
104
- * never freezes. `Opts` is its format-specific option set; the default `unknown` lets a caller pass
105
- * the common options to an importer typed without one.
215
+ * A format's reader. It reads the input once, from start to end, and adds each node, edge and
216
+ * attribute to a graph builder (`GraphSink`, which `GraphBuilder` from @graphty/graph-format
217
+ * implements); importGraph() then builds the snapshot. Register one with
218
+ * `registry.registerImporter()` to teach graph-io a new format. `Opts` is the type of the format's
219
+ * own options.
220
+ * @category Writing a format
106
221
  */
107
222
  export interface GraphImporter<Opts = unknown> {
108
- /** The format name: "gexf", "graphml", "gml", "dot", "pajek", "csv", "json", "neo4j". */
223
+ /** The name callers pass as `format`, such as "graphml" or "csv"; lowercase, unique in a registry. */
109
224
  readonly format: string;
110
- /** File extensions with the leading dot. */
225
+ /** File extensions with the leading dot, most common first; used to detect the format from a file name. */
111
226
  readonly extensions: readonly string[];
112
- /** MIME types the format is served as. */
227
+ /** MIME types the format is served as, most specific first; used to detect the format from a Content-Type. */
113
228
  readonly mimeTypes: readonly string[];
114
229
  /**
115
- * Confidence that `head` is this format, for the registry's sniff().
230
+ * The names of this format's own options (`["separator"]`), when you want misspelled options
231
+ * reported. While every registered importer lists its options, a load warns `W_UNKNOWN_OPTION` for
232
+ * a name that no format and no load function takes. Leave it out to report nothing.
233
+ */
234
+ readonly options?: readonly string[] | undefined;
235
+ /**
236
+ * How sure you are that `head`, the first bytes of a file (up to SNIFF_HEAD_BYTES), is this
237
+ * format: 0 for no, up to 1 for certain. Below 0.5 counts as a weak guess, which loses to a
238
+ * file extension another format claims. Without this method the format is detected only by
239
+ * file name and MIME type.
116
240
  * @param head - the first bytes of the input
117
241
  * @returns a confidence in 0..1
118
242
  */
119
243
  sniff?(head: Uint8Array): number;
120
244
  /**
121
- * Read `input` into `sink`; per-element errors are aggregated into the report until the error
122
- * limit, then the importer throws ImportError with the partial report.
245
+ * Read `input` into `sink`. Record each problem in an ImportReportBuilder and skip the element;
246
+ * the builder throws ImportError once there are more errors than `errorLimit`.
123
247
  * @param input - the text, bytes or stream to read
124
- * @param sink - the builder (or a recording sink) to push into
125
- * @param options - format-specific and common options
126
- * @returns the import report
248
+ * @param sink - the graph builder to add nodes, edges and attributes to
249
+ * @param options - the format's own options and the options every importer takes
250
+ * @returns the import report (`report.finish()`)
127
251
  */
128
252
  import(input: ImportInput, sink: GraphSink, options?: Opts & CommonImportOptions): Promise<ImportReport>;
129
253
  /**
130
- * Read every graph of an input that can hold several (a DOT file with several graphs, a
131
- * Pajek project with several networks, a JGF `graphs` array), each into its own sink. An
132
- * importer without this method reads one graph per input. `import()` reads the first graph
133
- * and warns how many it skipped.
254
+ * Optional, for a format whose files can hold several graphs: read every graph, each into its
255
+ * own sink. importAllGraphs() calls it; with it, importGraph() also honors `graphIndex` and
256
+ * `graphName` by reading every graph and returning the chosen one. `import()` should read the
257
+ * first graph and warn W_MULTIPLE_GRAPHS with the number skipped.
134
258
  * @param input - the text, bytes or stream to read
135
259
  * @param sinkFor - called once per graph, in document order, before that graph's first push
136
260
  * @param options - format-specific and common options
@@ -142,9 +266,10 @@ export interface GraphImporter<Opts = unknown> {
142
266
  options?: Opts & CommonImportOptions,
143
267
  ): Promise<ImportReport[]>;
144
268
  /**
145
- * List the graphs of an input that can hold several without importing them, so a caller can
146
- * offer a choice before reading one with `graphIndex` or `graphName`. An importer without this
147
- * method does not list its graphs; `import()` reads the first.
269
+ * Optional: list the graphs of a file without importing them, so a caller can offer a choice.
270
+ * listGraphs() calls it. An importer that has it must also honor `graphIndex` and `graphName`
271
+ * in `import()` itself (`chooseGraph()` resolves them); one without it lists nothing and the
272
+ * registry makes the choice through `importAll()`.
148
273
  * @param input - the text, bytes or stream to read
149
274
  * @param options - format-specific and common options
150
275
  * @returns one listing per graph, in document order
@@ -153,98 +278,185 @@ export interface GraphImporter<Opts = unknown> {
153
278
  }
154
279
 
155
280
  /**
156
- * What a format can express without loss (design section 8.5): the fidelity matrix of research
157
- * note 07 section 9 as a table, and the acceptance test list for check().
281
+ * What a format can store exactly. checkCapabilities() compares a graph against it and returns a
282
+ * loss note for everything the graph has that the format cannot store.
283
+ * @category Saving
158
284
  */
159
285
  export interface ExportCapabilities {
160
- /** Directed and undirected edges in one file. */
286
+ /**
287
+ * Whether one file can hold directed and undirected edges together. When false, a graph with both
288
+ * needs `onMixedDirection` ("directed" or "undirected") to be saved.
289
+ */
161
290
  readonly mixedDirection: boolean;
162
- /** Parallel edges. */
291
+ /**
292
+ * Whether the file can hold two edges between the same pair of nodes. When false, the extra
293
+ * edges are not kept as separate edges.
294
+ */
163
295
  readonly multiEdges: boolean;
164
- /** Self-loops. */
296
+ /** Whether the file can hold an edge from a node to itself. When false, such edges are lost. */
165
297
  readonly selfLoops: boolean;
166
- /** Whether edge ids are required (generated when absent), optional or unsupported. */
298
+ /**
299
+ * Whether edges carry ids. "required": every edge has one, and ids are made up (e0, e1, ...)
300
+ * for a graph without them. "optional": edge ids are written when the graph has them. "none":
301
+ * edge ids are lost.
302
+ */
167
303
  readonly edgeIds: "required" | "optional" | "none";
168
- /** Which node ids can be written unchanged. */
304
+ /**
305
+ * Which node ids the format can write as they are: "any"; "nmtoken" (XML name tokens: letters,
306
+ * digits and `. - _ :`, no spaces); "integer"; or "dense-1-based" (the nodes are always numbered
307
+ * 1 to N). Other ids need `sanitizeIds: "mangle"`, which writes the original ids too.
308
+ */
169
309
  readonly idCharset: "any" | "nmtoken" | "integer" | "dense-1-based";
170
- /** The column dtypes the format keeps as declared. */
310
+ /**
311
+ * The attribute types the format keeps exactly: "bool", "i32" (32-bit integer), "u32" (unsigned
312
+ * 32-bit integer), "u8" (byte), "f32" (32-bit float), "f64" (64-bit float, a JavaScript number),
313
+ * "string" (text), "dict" (text stored as a dictionary of repeated values), "list" and "json".
314
+ * An attribute of another type is written as the nearest one the format has, with a
315
+ * W_DTYPE_UNSUPPORTED note.
316
+ */
171
317
  readonly dtypes: readonly Dtype[];
172
- /** Multi-component (stride) columns. */
318
+ /**
319
+ * Whether an attribute other than the node position can hold several numbers per node or edge
320
+ * (a vector). When false, such an attribute does not read back as one attribute. Positions
321
+ * are covered by `positions`.
322
+ */
173
323
  readonly components: boolean;
174
- /** List columns. */
324
+ /** Whether an attribute can hold a list per node or edge. When false, list attributes are lost or flattened. */
175
325
  readonly lists: boolean;
176
- /** Nested json columns. */
326
+ /**
327
+ * Whether an attribute can hold nested JSON objects and arrays. When false, such attributes are
328
+ * written as text or lost.
329
+ */
177
330
  readonly json: boolean;
178
- /** Declared defaults. */
331
+ /** Whether the file can declare a default value for an attribute. When false, declared defaults are lost. */
179
332
  readonly defaults: boolean;
180
- /** Declared enumerations (GEXF options). */
333
+ /**
334
+ * Whether the file can declare the allowed values of an attribute (GEXF `options`). When false,
335
+ * those declarations are lost; the values themselves are kept.
336
+ */
181
337
  readonly options: boolean;
182
- /** Containment (parent / parents roles). */
338
+ /** Whether nodes can sit inside other nodes (groups or clusters). When false, the nesting is lost. */
183
339
  readonly hierarchy: boolean;
184
- /** Temporal support level. */
340
+ /**
341
+ * What the file can say about time: "none" (time attributes are lost), "intervals" (one start
342
+ * and end per element), "spells" (several intervals per element), or "dynamic-values"
343
+ * (attribute values that change over time, as well).
344
+ */
185
345
  readonly temporal: "none" | "intervals" | "spells" | "dynamic-values";
186
- /** Graph-level attributes. */
346
+ /** Whether the file can hold attributes of the graph itself. When false, graph attributes are lost. */
187
347
  readonly graphAttributes: boolean;
188
- /** The position role. */
348
+ /** Whether the file can hold node positions. When false, the layout is lost. */
189
349
  readonly positions: boolean;
190
- /** The visual roles (color, size, shape, thickness). */
350
+ /** Whether the file can hold node and edge color, size, shape and thickness. When false, they are lost. */
191
351
  readonly viz: boolean;
192
352
  }
193
353
 
194
- /** One thing an exporter cannot represent, reported by check() before anything is written (design section 8.5). */
354
+ /**
355
+ * One thing a format cannot store, returned by checkExport() before anything is written.
356
+ * @category Saving
357
+ */
195
358
  export interface LossNote {
196
- /** A stable code such as "W_OPEN_INTERVAL". */
359
+ /**
360
+ * A stable code. Codes starting with "E_" mean the export refuses to write under these options:
361
+ * the exportGraph*() functions throw a GraphFormatError. Codes starting with "W_" mean the file
362
+ * is written, but this part will not read back the same.
363
+ */
197
364
  readonly code: string;
198
- /** A plain-ASCII human-readable explanation. */
365
+ /** A plain-English explanation. */
199
366
  readonly message: string;
200
- /** The affected column, or null when the note is not about a column. */
367
+ /** The attribute column involved, or null. */
201
368
  readonly column: string | null;
202
- /** How many rows or elements are affected, or null when not counted. */
369
+ /** How many nodes, edges or values are affected, or null when not counted. */
203
370
  readonly count: number | null;
204
371
  }
205
372
 
206
- /** The options every exporter accepts next to its format-specific ones (design section 8.5). */
373
+ /**
374
+ * The options every exporter accepts next to its format-specific ones.
375
+ * @category Saving
376
+ */
207
377
  export interface CommonExportOptions {
208
- /** "error" (default): never rename a node; "mangle": rewrite ids the format cannot hold and keep the original. */
378
+ /**
379
+ * What to do with node ids the format cannot hold. "error": the export throws (E_INVALID_ID) and
380
+ * no node is renamed. "mangle": such ids are rewritten and the originals are written to the
381
+ * file too, so an import with `restoreMangledIds` (on by default) reads the original ids back.
382
+ * Pajek is the exception: it always numbers nodes 1 to N and keeps the old ids as labels.
383
+ * @defaultValue "error"
384
+ */
209
385
  sanitizeIds?: "error" | "mangle" | undefined;
210
- /** For formats without mixed-direction support: refuse (default) or write every edge one way. */
386
+ /**
387
+ * What a format with one direction per file does with a graph that has both directed and
388
+ * undirected edges: "error" throws (E_DIRECTED), "directed" writes every edge as directed (an
389
+ * undirected edge once, as one directed edge), "undirected" writes the whole graph undirected.
390
+ * A format that keeps each edge's own direction (GraphML, GEXF, CSV, Pajek, XGMML, Cytoscape
391
+ * sessions, and the JGF and graphology JSON dialects) ignores it and writes both kinds; to make
392
+ * such a graph all one direction, read it with the import option `onMixedDirection`.
393
+ * @defaultValue "error"
394
+ */
211
395
  onMixedDirection?: "error" | "directed" | "undirected" | undefined;
212
396
  }
213
397
 
214
398
  /**
215
- * An exporter plugin (design section 8.5): iterates nodes and logical edges (never arcs) in index
216
- * order and reads the role columns of section 3.6 / 3.7 to fold expanded pairs and emit explicit
217
- * weights only.
399
+ * A format's writer. Register one with `registry.registerExporter()` to make a format writable by
400
+ * every save function. `Opts` is the type of the format's own options.
401
+ * @category Writing a format
218
402
  */
219
403
  export interface GraphExporter<Opts = unknown> {
220
- /** The format name. */
404
+ /** The name callers pass as `format`; the same as the importer's when the format has both. */
221
405
  readonly format: string;
222
- /** What the format can express. */
406
+ /** What the format can store exactly; build it with `capabilities()`. */
223
407
  readonly capabilities: ExportCapabilities;
224
408
  /**
225
- * Pre-flight: what export() would lose, without writing anything.
226
- * @param snapshot - the snapshot to check
227
- * @param options - format-specific and common options
228
- * @returns the loss notes, empty when the export is exact
409
+ * File extensions with the leading dot, most common first. Optional; listFormats() uses them
410
+ * when no importer is registered for the format (an export-only format).
411
+ */
412
+ readonly extensions?: readonly string[] | undefined;
413
+ /** MIME types, most specific first. Optional; used the same way as `extensions`. */
414
+ readonly mimeTypes?: readonly string[] | undefined;
415
+ /**
416
+ * The names of this format's own save options, when you want misspelled options reported. While
417
+ * every registered exporter lists its options, `checkExport()` returns a `W_UNKNOWN_OPTION` note for
418
+ * a name that no format and no save function takes. Leave it out to report nothing.
419
+ */
420
+ readonly options?: readonly string[] | undefined;
421
+ /**
422
+ * What a save would lose, without writing anything; checkExport(snapshot, format, options) calls
423
+ * it. Start from `checkCapabilities(snapshot, capabilities, resolveExportOptions(options))` and
424
+ * add a note for anything else your format changes. Every difference a re-import would show
425
+ * needs a note.
426
+ * @param snapshot - the graph to check
427
+ * @param options - the format's own options and the options every exporter takes
428
+ * @returns the loss notes, empty when the save is exact
229
429
  */
230
430
  check(snapshot: GraphSnapshot, options?: Opts & CommonExportOptions): readonly LossNote[];
231
431
  /**
232
- * Write the snapshot as UTF-8 chunks.
233
- * @param snapshot - the snapshot to write
234
- * @param options - format-specific and common options
235
- * @returns the encoded chunks
432
+ * Write the graph as byte chunks: UTF-8 text for a text format (`encodeChunks()` turns string
433
+ * parts into them), the raw bytes for a binary one. Throw a GraphFormatError before writing for
434
+ * every "E_" note `check()` returns.
435
+ * @param snapshot - the graph to write
436
+ * @param options - the format's own options and the options every exporter takes
437
+ * @returns the file's bytes, chunk by chunk
236
438
  */
237
439
  export(snapshot: GraphSnapshot, options?: Opts & CommonExportOptions): AsyncIterable<Uint8Array>;
238
440
  /**
239
- * Write the snapshot as one string.
240
- * @param snapshot - the snapshot to write
241
- * @param options - format-specific and common options
242
- * @returns the whole document
441
+ * Write the graph as one string (`joinText()` joins string parts). A binary format rejects with
442
+ * a GraphFormatError E_UNSUPPORTED (`details.reason` "binary") instead.
443
+ * @param snapshot - the graph to write
444
+ * @param options - the format's own options and the options every exporter takes
445
+ * @returns the whole file
243
446
  */
244
447
  exportToString(snapshot: GraphSnapshot, options?: Opts & CommonExportOptions): Promise<string>;
245
448
  }
246
449
 
247
- /** The categories of an ImportIssue (design section 8.6). */
450
+ /**
451
+ * What an ImportIssue is about, for errors and warnings alike: "parse-error" (the text is not valid
452
+ * in the format), "missing-value" (something required is absent), "validation-error" (a value
453
+ * breaks a rule of the format or of an option; an error skips it, a warning keeps it as written,
454
+ * such as an id with spaces around it), "unsupported" (the file uses something graph-io does not
455
+ * read), "precision" (a value was rounded), "coercion" (a value or id changed type) and "merged"
456
+ * (elements were combined). Sort by `severity` first: the category says what kind of problem it
457
+ * is, not how serious.
458
+ * @category Reports and errors
459
+ */
248
460
  export type IssueCategory =
249
461
  | "parse-error"
250
462
  | "missing-value"
@@ -254,37 +466,49 @@ export type IssueCategory =
254
466
  | "coercion"
255
467
  | "merged";
256
468
 
257
- /** One problem found while importing (design section 8.6). */
469
+ /**
470
+ * One problem found while importing.
471
+ * @category Reports and errors
472
+ */
258
473
  export interface ImportIssue {
259
474
  /** The category. */
260
475
  readonly category: IssueCategory;
261
- /** Errors count toward the error limit; warnings do not. */
476
+ /**
477
+ * "error": the element was skipped and counts toward `errorLimit`. "warning": the element was
478
+ * kept, possibly changed.
479
+ */
262
480
  readonly severity: "error" | "warning";
263
- /** A stable code such as "E_UNKNOWN_NODE" or "W_WIDENED". */
481
+ /** A stable code; E_ for errors, W_ for warnings ("E_UNKNOWN_NODE", "W_WIDENED"). */
264
482
  readonly code: string;
265
- /** A plain-ASCII human-readable message. */
483
+ /** A plain-English message. */
266
484
  readonly message: string;
267
- /** The 1-based source line, or null when unknown. */
485
+ /** The 1-based line in the input, or null when the format has no lines or it is unknown. */
268
486
  readonly line: number | null;
269
- /** The element (a node or edge id, an attribute name), or null when unknown. */
487
+ /** The node id, edge id or attribute name involved, or null. */
270
488
  readonly element: string | null;
271
489
  }
272
490
 
273
- /** What an import produced besides the sink's contents (design section 8.6). */
491
+ /**
492
+ * What happened while a file was read.
493
+ * @category Reports and errors
494
+ */
274
495
  export interface ImportReport {
275
- /** The importer's format name. */
496
+ /** The format the file was read as. */
276
497
  readonly format: string;
277
- /** Element counts. */
498
+ /**
499
+ * What was read from the file, counted before the graph was built: `duplicateEdges` and
500
+ * `selfLoops: "drop"` can leave fewer edges in the snapshot (each reported as a warning).
501
+ */
278
502
  readonly counts: {
279
- /** Nodes pushed. */
503
+ /** Nodes read. */
280
504
  readonly nodes: number;
281
- /** Logical edges pushed (both halves of an expanded edge count). */
505
+ /** Edges read (an undirected edge expanded into two by onMixedDirection "expand" counts twice). */
282
506
  readonly edges: number;
283
507
  /** Nodes skipped after an error. */
284
508
  readonly skippedNodes: number;
285
509
  /** Edges skipped after an error. */
286
510
  readonly skippedEdges: number;
287
- /** Edges expanded under onMixedDirection "expand" (design section 3.6). */
511
+ /** Undirected edges expanded into two by onMixedDirection "expand". */
288
512
  readonly expandedMixed: number;
289
513
  };
290
514
  /** Every issue recorded, in order. */
@@ -297,28 +521,75 @@ export interface ImportReport {
297
521
  readonly truncated: boolean;
298
522
  /** What the importer could not represent. */
299
523
  readonly lossy: readonly LossNote[];
300
- /** Wall time of the parse phase; the caller's freeze reports separately. */
524
+ /** How long reading the file took, in milliseconds. */
301
525
  readonly durationMs: number;
302
526
  }
303
527
 
304
528
  /**
305
- * The error an importer throws when the error limit is reached or the input cannot be read at all
306
- * (design section 8.6): a GraphFormatError with code "E_IMPORT" (reserved in the core's union so
307
- * `err.code === "E_IMPORT"` narrows) carrying the partial report.
529
+ * What a load function throws when the input cannot be read: the URL failed, the format was not
530
+ * recognized, the file could not be parsed, or there were more errors than `errorLimit`. It is a
531
+ * GraphFormatError with code "E_IMPORT"; `issue` says what stopped the import and `report` holds
532
+ * everything recorded until then.
533
+ * @category Reports and errors
308
534
  */
309
535
  export class ImportError extends GraphFormatError {
310
- /** The report as it stood when the import aborted. */
311
- readonly report: ImportReport;
536
+ /**
537
+ * Everything recorded up to the point the import stopped. It is not an enumerable property, so an
538
+ * uncaught ImportError prints its message and issue, not every issue of the report.
539
+ */
540
+ declare readonly report: ImportReport;
541
+
542
+ /**
543
+ * The issue that stopped the import: its `code` ("E_FETCH", "E_UNKNOWN_FORMAT", "E_CSV_UNCLOSED_QUOTE", ...),
544
+ * `message`, `line` and `element`. This is the value to branch on; `code` is always "E_IMPORT".
545
+ * Null only for an ImportError constructed by hand without a matching issue.
546
+ * @example
547
+ * ```ts
548
+ * if (err instanceof ImportError) {
549
+ * switch (err.issue?.code) {
550
+ * case "E_FETCH":
551
+ * console.error(`download failed with status ${String(err.details.status)}`);
552
+ * break;
553
+ * case "E_UNKNOWN_FORMAT":
554
+ * console.error("not a graph file this library can read; pass `format`");
555
+ * break;
556
+ * default:
557
+ * console.error(err.message);
558
+ * }
559
+ * }
560
+ * ```
561
+ */
562
+ readonly issue: ImportIssue | null;
312
563
 
313
564
  /**
314
565
  * Create an ImportError.
315
566
  * @param message - a plain-ASCII human-readable message
316
567
  * @param report - the partial report
317
- * @param details - optional machine-readable context
568
+ * @param details - optional machine-readable context; its `code` names the issue that stopped the import
318
569
  */
319
570
  constructor(message: string, report: ImportReport, details?: Readonly<Record<string, unknown>>) {
320
571
  super("E_IMPORT", message, details);
321
572
  this.name = "ImportError";
322
- this.report = report;
573
+ Object.defineProperty(this, "report", { value: report, enumerable: false });
574
+ this.issue = stoppingIssue(report.issues, details?.code);
575
+ }
576
+ }
577
+
578
+ /**
579
+ * The issue that stopped an import: the last one with the code the abort named, else the last error.
580
+ * @param issues - the report's issues
581
+ * @param code - the code the abort named, if any
582
+ * @returns the issue, or null
583
+ */
584
+ function stoppingIssue(issues: readonly ImportIssue[], code: unknown): ImportIssue | null {
585
+ let lastError: ImportIssue | null = null;
586
+ for (let i = issues.length - 1; i >= 0; i--) {
587
+ if (issues[i].code === code) {
588
+ return issues[i];
589
+ }
590
+ if (lastError === null && issues[i].severity === "error") {
591
+ lastError = issues[i];
592
+ }
323
593
  }
594
+ return lastError;
324
595
  }