@graphty/graph-io 0.3.48 → 0.3.49

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 (570) hide show
  1. package/dist/chunks/{approximations-C2riR4NT.js → approximations-Bzn3L-je.js} +2 -2
  2. package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-Bzn3L-je.js.map} +1 -1
  3. package/dist/chunks/bends-BGXjv_U4.js +129 -0
  4. package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
  5. package/dist/chunks/{block-Cu22ewuS.js → block-iptrlMBb.js} +906 -164
  6. package/dist/chunks/block-iptrlMBb.js.map +1 -0
  7. package/dist/chunks/choose-CczZJaX_.js +717 -0
  8. package/dist/chunks/choose-CczZJaX_.js.map +1 -0
  9. package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
  10. package/dist/chunks/codes-BE2xir2k.js.map +1 -0
  11. package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
  12. package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
  13. package/dist/chunks/{context-cgmmOxZ2.js → context-C3p0RQxR.js} +5 -4
  14. package/dist/chunks/{context-cgmmOxZ2.js.map → context-C3p0RQxR.js.map} +1 -1
  15. package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
  16. package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
  17. package/dist/chunks/{credentials-BiQsnMTb.js → credentials-DXHx7nwR.js} +16 -14
  18. package/dist/chunks/credentials-DXHx7nwR.js.map +1 -0
  19. package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
  20. package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
  21. package/dist/chunks/descriptor-B28U25x4.js +60 -0
  22. package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
  23. package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-DLA5kINx.js} +7 -2
  24. package/dist/chunks/descriptor-DLA5kINx.js.map +1 -0
  25. package/dist/chunks/{emit-CD8xnY8s.js → emit-BwHQkZle.js} +1660 -133
  26. package/dist/chunks/emit-BwHQkZle.js.map +1 -0
  27. package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
  28. package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
  29. package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
  30. package/dist/chunks/export-Cha4dRFz.js.map +1 -0
  31. package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
  32. package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
  33. package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-D2CETOMK.js} +1222 -156
  34. package/dist/chunks/exporter-D2CETOMK.js.map +1 -0
  35. package/dist/chunks/{exporter-BIdaoIgh.js → exporter-D9yMtocA.js} +7 -7
  36. package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-D9yMtocA.js.map} +1 -1
  37. package/dist/chunks/{exporter-DtVU80Fa.js → exporter-_jrBTnos.js} +9 -8
  38. package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-_jrBTnos.js.map} +1 -1
  39. package/dist/chunks/{exporter-ChjL5fmP.js → exporter-nDfxIK5D.js} +9 -8
  40. package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-nDfxIK5D.js.map} +1 -1
  41. package/dist/chunks/format-BXiAb-1h.js +408 -0
  42. package/dist/chunks/format-BXiAb-1h.js.map +1 -0
  43. package/dist/chunks/{generic-CP6YD34u.js → generic-ymWCETAJ.js} +387 -31
  44. package/dist/chunks/generic-ymWCETAJ.js.map +1 -0
  45. package/dist/chunks/{importer-e3huMZbm.js → importer-B92x1xY5.js} +14 -10
  46. package/dist/chunks/importer-B92x1xY5.js.map +1 -0
  47. package/dist/chunks/{importer-B87_fmVx.js → importer-CT9mJ1nn.js} +326 -84
  48. package/dist/chunks/importer-CT9mJ1nn.js.map +1 -0
  49. package/dist/chunks/{importer-CB_zV5_L.js → importer-DaLTjbds.js} +116 -1102
  50. package/dist/chunks/importer-DaLTjbds.js.map +1 -0
  51. package/dist/chunks/{importer-DPZDN40-.js → importer-GREKMdIf.js} +25 -17
  52. package/dist/chunks/importer-GREKMdIf.js.map +1 -0
  53. package/dist/chunks/{importer-Bji2MeWr.js → importer-PqaaKKnY.js} +13 -10
  54. package/dist/chunks/{importer-Bji2MeWr.js.map → importer-PqaaKKnY.js.map} +1 -1
  55. package/dist/chunks/{importer-Cyy6UseH.js → importer-Vn5QvmmJ.js} +66 -13
  56. package/dist/chunks/importer-Vn5QvmmJ.js.map +1 -0
  57. package/dist/chunks/{importer-CVT-JyDE.js → importer-vRq4h3j5.js} +1469 -356
  58. package/dist/chunks/importer-vRq4h3j5.js.map +1 -0
  59. package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
  60. package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
  61. package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
  62. package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
  63. package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-Clf4QIyl.js} +282 -74
  64. package/dist/chunks/lexicon-Clf4QIyl.js.map +1 -0
  65. package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
  66. package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
  67. package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
  68. package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
  69. package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
  70. package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
  71. package/dist/chunks/round-trip-Zm3_ivgq.js +79 -0
  72. package/dist/chunks/round-trip-Zm3_ivgq.js.map +1 -0
  73. package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-EokFic1V.js} +5 -5
  74. package/dist/chunks/sigv4-EokFic1V.js.map +1 -0
  75. package/dist/chunks/{styles-CaABMoO1.js → styles-CCs214_3.js} +1237 -138
  76. package/dist/chunks/styles-CCs214_3.js.map +1 -0
  77. package/dist/chunks/styles-Cm62yyQX.js +2812 -0
  78. package/dist/chunks/styles-Cm62yyQX.js.map +1 -0
  79. package/dist/chunks/styles-DPQQIig4.js +1928 -0
  80. package/dist/chunks/styles-DPQQIig4.js.map +1 -0
  81. package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-UMFdNqze.js} +503 -172
  82. package/dist/chunks/styles-yed-UMFdNqze.js.map +1 -0
  83. package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
  84. package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
  85. package/dist/csv.js +7 -7
  86. package/dist/cx.js +2 -2
  87. package/dist/cx2.js +2 -2
  88. package/dist/cys.js +1 -1
  89. package/dist/dot.js +5 -4
  90. package/dist/dot.js.map +1 -1
  91. package/dist/gexf.js +42 -12
  92. package/dist/gexf.js.map +1 -1
  93. package/dist/gml.js +847 -193
  94. package/dist/gml.js.map +1 -1
  95. package/dist/graph-io.js +232 -220
  96. package/dist/graph-io.js.map +1 -1
  97. package/dist/graphml.js +3 -3
  98. package/dist/json.js +3 -2
  99. package/dist/neo4j.js +6 -6
  100. package/dist/obo.js +1 -1
  101. package/dist/pajek.js +1 -1
  102. package/dist/positions.js +45 -3
  103. package/dist/positions.js.map +1 -1
  104. package/dist/sources-cypher.js +138 -23
  105. package/dist/sources-cypher.js.map +1 -1
  106. package/dist/sources-ndex.js +2 -2
  107. package/dist/sources-rest.js +16 -6
  108. package/dist/sources-rest.js.map +1 -1
  109. package/dist/sources-sparql.d.ts +1 -0
  110. package/dist/sources-sparql.js +405 -0
  111. package/dist/sources-sparql.js.map +1 -0
  112. package/dist/src/formats/cx/importer.d.ts.map +1 -1
  113. package/dist/src/formats/cx/importer.js +5 -1
  114. package/dist/src/formats/cx/importer.js.map +1 -1
  115. package/dist/src/formats/cx/styles.d.ts +24 -1
  116. package/dist/src/formats/cx/styles.d.ts.map +1 -1
  117. package/dist/src/formats/cx/styles.js +117 -11
  118. package/dist/src/formats/cx/styles.js.map +1 -1
  119. package/dist/src/formats/cx2/importer.d.ts.map +1 -1
  120. package/dist/src/formats/cx2/importer.js +1 -0
  121. package/dist/src/formats/cx2/importer.js.map +1 -1
  122. package/dist/src/formats/cx2/styles.d.ts.map +1 -1
  123. package/dist/src/formats/cx2/styles.js +3 -1
  124. package/dist/src/formats/cx2/styles.js.map +1 -1
  125. package/dist/src/formats/cys/importer.d.ts.map +1 -1
  126. package/dist/src/formats/cys/importer.js +1 -0
  127. package/dist/src/formats/cys/importer.js.map +1 -1
  128. package/dist/src/formats/cys/styles.d.ts +2 -0
  129. package/dist/src/formats/cys/styles.d.ts.map +1 -1
  130. package/dist/src/formats/cys/styles.js +15 -7
  131. package/dist/src/formats/cys/styles.js.map +1 -1
  132. package/dist/src/formats/dot/drawing.d.ts +98 -0
  133. package/dist/src/formats/dot/drawing.d.ts.map +1 -0
  134. package/dist/src/formats/dot/drawing.js +734 -0
  135. package/dist/src/formats/dot/drawing.js.map +1 -0
  136. package/dist/src/formats/dot/importer.d.ts.map +1 -1
  137. package/dist/src/formats/dot/importer.js +108 -31
  138. package/dist/src/formats/dot/importer.js.map +1 -1
  139. package/dist/src/formats/dot/label-places.d.ts +34 -0
  140. package/dist/src/formats/dot/label-places.d.ts.map +1 -0
  141. package/dist/src/formats/dot/label-places.js +179 -0
  142. package/dist/src/formats/dot/label-places.js.map +1 -0
  143. package/dist/src/formats/dot/record.d.ts +50 -0
  144. package/dist/src/formats/dot/record.d.ts.map +1 -0
  145. package/dist/src/formats/dot/record.js +275 -0
  146. package/dist/src/formats/dot/record.js.map +1 -0
  147. package/dist/src/formats/dot/styles.d.ts +62 -2
  148. package/dist/src/formats/dot/styles.d.ts.map +1 -1
  149. package/dist/src/formats/dot/styles.js +1454 -119
  150. package/dist/src/formats/dot/styles.js.map +1 -1
  151. package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
  152. package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
  153. package/dist/src/formats/gexf/dialog-metrics.js +59 -0
  154. package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
  155. package/dist/src/formats/gexf/importer.d.ts +7 -0
  156. package/dist/src/formats/gexf/importer.d.ts.map +1 -1
  157. package/dist/src/formats/gexf/importer.js +41 -5
  158. package/dist/src/formats/gexf/importer.js.map +1 -1
  159. package/dist/src/formats/gexf/preview.d.ts +77 -0
  160. package/dist/src/formats/gexf/preview.d.ts.map +1 -0
  161. package/dist/src/formats/gexf/preview.js +191 -0
  162. package/dist/src/formats/gexf/preview.js.map +1 -0
  163. package/dist/src/formats/gexf/schema.d.ts.map +1 -1
  164. package/dist/src/formats/gexf/schema.js +2 -1
  165. package/dist/src/formats/gexf/schema.js.map +1 -1
  166. package/dist/src/formats/gexf/styles.d.ts +58 -31
  167. package/dist/src/formats/gexf/styles.d.ts.map +1 -1
  168. package/dist/src/formats/gexf/styles.js +848 -225
  169. package/dist/src/formats/gexf/styles.js.map +1 -1
  170. package/dist/src/formats/gml/importer.d.ts +5 -2
  171. package/dist/src/formats/gml/importer.d.ts.map +1 -1
  172. package/dist/src/formats/gml/importer.js +258 -71
  173. package/dist/src/formats/gml/importer.js.map +1 -1
  174. package/dist/src/formats/gml/index.d.ts +1 -1
  175. package/dist/src/formats/gml/index.d.ts.map +1 -1
  176. package/dist/src/formats/gml/index.js +1 -1
  177. package/dist/src/formats/gml/index.js.map +1 -1
  178. package/dist/src/formats/gml/positions.d.ts +7 -0
  179. package/dist/src/formats/gml/positions.d.ts.map +1 -1
  180. package/dist/src/formats/gml/positions.js +29 -7
  181. package/dist/src/formats/gml/positions.js.map +1 -1
  182. package/dist/src/formats/gml/styles.d.ts.map +1 -1
  183. package/dist/src/formats/gml/styles.js +753 -101
  184. package/dist/src/formats/gml/styles.js.map +1 -1
  185. package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
  186. package/dist/src/formats/graphml/styles-plain.js +6 -10
  187. package/dist/src/formats/graphml/styles-plain.js.map +1 -1
  188. package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
  189. package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
  190. package/dist/src/formats/graphml/styles-yed.js +692 -161
  191. package/dist/src/formats/graphml/styles-yed.js.map +1 -1
  192. package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
  193. package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
  194. package/dist/src/formats/graphml/styles-yfiles3.js +429 -64
  195. package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
  196. package/dist/src/formats/graphml/yfiles.d.ts +3 -3
  197. package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
  198. package/dist/src/formats/graphml/yfiles.js +16 -6
  199. package/dist/src/formats/graphml/yfiles.js.map +1 -1
  200. package/dist/src/formats/json/dialect.d.ts +3 -2
  201. package/dist/src/formats/json/dialect.d.ts.map +1 -1
  202. package/dist/src/formats/json/dialect.js +39 -5
  203. package/dist/src/formats/json/dialect.js.map +1 -1
  204. package/dist/src/formats/json/importer.d.ts +13 -2
  205. package/dist/src/formats/json/importer.d.ts.map +1 -1
  206. package/dist/src/formats/json/importer.js +42 -6
  207. package/dist/src/formats/json/importer.js.map +1 -1
  208. package/dist/src/formats/json/index.d.ts +1 -1
  209. package/dist/src/formats/json/index.d.ts.map +1 -1
  210. package/dist/src/formats/json/index.js +1 -1
  211. package/dist/src/formats/json/index.js.map +1 -1
  212. package/dist/src/formats/json/positions.d.ts +5 -2
  213. package/dist/src/formats/json/positions.d.ts.map +1 -1
  214. package/dist/src/formats/json/positions.js +20 -4
  215. package/dist/src/formats/json/positions.js.map +1 -1
  216. package/dist/src/formats/json/styles.d.ts +12 -1
  217. package/dist/src/formats/json/styles.d.ts.map +1 -1
  218. package/dist/src/formats/json/styles.js +1755 -136
  219. package/dist/src/formats/json/styles.js.map +1 -1
  220. package/dist/src/formats/pajek/draw.d.ts +96 -0
  221. package/dist/src/formats/pajek/draw.d.ts.map +1 -0
  222. package/dist/src/formats/pajek/draw.js +372 -0
  223. package/dist/src/formats/pajek/draw.js.map +1 -0
  224. package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
  225. package/dist/src/formats/pajek/exporter.js +70 -51
  226. package/dist/src/formats/pajek/exporter.js.map +1 -1
  227. package/dist/src/formats/pajek/importer.d.ts +9 -0
  228. package/dist/src/formats/pajek/importer.d.ts.map +1 -1
  229. package/dist/src/formats/pajek/importer.js +233 -102
  230. package/dist/src/formats/pajek/importer.js.map +1 -1
  231. package/dist/src/formats/pajek/index.d.ts +1 -0
  232. package/dist/src/formats/pajek/index.d.ts.map +1 -1
  233. package/dist/src/formats/pajek/index.js.map +1 -1
  234. package/dist/src/formats/pajek/styles.d.ts +15 -7
  235. package/dist/src/formats/pajek/styles.d.ts.map +1 -1
  236. package/dist/src/formats/pajek/styles.js +1278 -114
  237. package/dist/src/formats/pajek/styles.js.map +1 -1
  238. package/dist/src/formats/pajek/syntax.d.ts +10 -1
  239. package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
  240. package/dist/src/formats/pajek/syntax.js +26 -2
  241. package/dist/src/formats/pajek/syntax.js.map +1 -1
  242. package/dist/src/formats/xgmml/emit.d.ts +1 -0
  243. package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
  244. package/dist/src/formats/xgmml/emit.js +65 -5
  245. package/dist/src/formats/xgmml/emit.js.map +1 -1
  246. package/dist/src/formats/xgmml/styles.d.ts +23 -3
  247. package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
  248. package/dist/src/formats/xgmml/styles.js +277 -60
  249. package/dist/src/formats/xgmml/styles.js.map +1 -1
  250. package/dist/src/index.d.ts +4 -3
  251. package/dist/src/index.d.ts.map +1 -1
  252. package/dist/src/index.js +4 -3
  253. package/dist/src/index.js.map +1 -1
  254. package/dist/src/positions/convert.d.ts.map +1 -1
  255. package/dist/src/positions/convert.js +11 -1
  256. package/dist/src/positions/convert.js.map +1 -1
  257. package/dist/src/positions/extract.d.ts.map +1 -1
  258. package/dist/src/positions/extract.js +53 -1
  259. package/dist/src/positions/extract.js.map +1 -1
  260. package/dist/src/positions/index.d.ts +1 -1
  261. package/dist/src/positions/index.d.ts.map +1 -1
  262. package/dist/src/positions/types.d.ts +59 -0
  263. package/dist/src/positions/types.d.ts.map +1 -1
  264. package/dist/src/sources/builtins.d.ts +1 -1
  265. package/dist/src/sources/builtins.d.ts.map +1 -1
  266. package/dist/src/sources/builtins.js +8 -2
  267. package/dist/src/sources/builtins.js.map +1 -1
  268. package/dist/src/sources/context.d.ts.map +1 -1
  269. package/dist/src/sources/context.js +1 -0
  270. package/dist/src/sources/context.js.map +1 -1
  271. package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
  272. package/dist/src/sources/cypher/descriptor.js +5 -0
  273. package/dist/src/sources/cypher/descriptor.js.map +1 -1
  274. package/dist/src/sources/cypher/index.d.ts.map +1 -1
  275. package/dist/src/sources/cypher/index.js +124 -18
  276. package/dist/src/sources/cypher/index.js.map +1 -1
  277. package/dist/src/sources/cypher/params.d.ts +1 -1
  278. package/dist/src/sources/cypher/params.d.ts.map +1 -1
  279. package/dist/src/sources/cypher/query-builder.d.ts +17 -0
  280. package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
  281. package/dist/src/sources/cypher/query-builder.js +31 -0
  282. package/dist/src/sources/cypher/query-builder.js.map +1 -1
  283. package/dist/src/sources/ids.d.ts +5 -0
  284. package/dist/src/sources/ids.d.ts.map +1 -1
  285. package/dist/src/sources/ids.js +5 -0
  286. package/dist/src/sources/ids.js.map +1 -1
  287. package/dist/src/sources/params.d.ts +3 -0
  288. package/dist/src/sources/params.d.ts.map +1 -1
  289. package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
  290. package/dist/src/sources/rest/descriptor.js +5 -0
  291. package/dist/src/sources/rest/descriptor.js.map +1 -1
  292. package/dist/src/sources/rest/source.d.ts.map +1 -1
  293. package/dist/src/sources/rest/source.js +15 -0
  294. package/dist/src/sources/rest/source.js.map +1 -1
  295. package/dist/src/sources/sigv4.d.ts +5 -3
  296. package/dist/src/sources/sigv4.d.ts.map +1 -1
  297. package/dist/src/sources/sigv4.js +6 -4
  298. package/dist/src/sources/sigv4.js.map +1 -1
  299. package/dist/src/sources/sparql/descriptor.d.ts +10 -0
  300. package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
  301. package/dist/src/sources/sparql/descriptor.js +64 -0
  302. package/dist/src/sources/sparql/descriptor.js.map +1 -0
  303. package/dist/src/sources/sparql/index.d.ts +28 -0
  304. package/dist/src/sources/sparql/index.d.ts.map +1 -0
  305. package/dist/src/sources/sparql/index.js +314 -0
  306. package/dist/src/sources/sparql/index.js.map +1 -0
  307. package/dist/src/sources/sparql/ntriples.d.ts +69 -0
  308. package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
  309. package/dist/src/sources/sparql/ntriples.js +180 -0
  310. package/dist/src/sources/sparql/ntriples.js.map +1 -0
  311. package/dist/src/sources/sparql/params.d.ts +27 -0
  312. package/dist/src/sources/sparql/params.d.ts.map +1 -0
  313. package/dist/src/sources/sparql/params.js +5 -0
  314. package/dist/src/sources/sparql/params.js.map +1 -0
  315. package/dist/src/sources/sparql/query.d.ts +72 -0
  316. package/dist/src/sources/sparql/query.d.ts.map +1 -0
  317. package/dist/src/sources/sparql/query.js +113 -0
  318. package/dist/src/sources/sparql/query.js.map +1 -0
  319. package/dist/src/sources/types.d.ts +31 -0
  320. package/dist/src/sources/types.d.ts.map +1 -1
  321. package/dist/src/styles/annotations.d.ts +61 -5
  322. package/dist/src/styles/annotations.d.ts.map +1 -1
  323. package/dist/src/styles/annotations.js +130 -22
  324. package/dist/src/styles/annotations.js.map +1 -1
  325. package/dist/src/styles/canon/bends.d.ts +46 -0
  326. package/dist/src/styles/canon/bends.d.ts.map +1 -1
  327. package/dist/src/styles/canon/bends.js +123 -0
  328. package/dist/src/styles/canon/bends.js.map +1 -1
  329. package/dist/src/styles/canon/color-tables.d.ts +6 -1
  330. package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
  331. package/dist/src/styles/canon/color-tables.js +10 -4
  332. package/dist/src/styles/canon/color-tables.js.map +1 -1
  333. package/dist/src/styles/canon/color.d.ts +3 -1
  334. package/dist/src/styles/canon/color.d.ts.map +1 -1
  335. package/dist/src/styles/canon/color.js +103 -3
  336. package/dist/src/styles/canon/color.js.map +1 -1
  337. package/dist/src/styles/canon/enums.d.ts +2 -2
  338. package/dist/src/styles/canon/enums.d.ts.map +1 -1
  339. package/dist/src/styles/canon/enums.js +81 -7
  340. package/dist/src/styles/canon/enums.js.map +1 -1
  341. package/dist/src/styles/canon/graphviz.d.ts +12 -3
  342. package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
  343. package/dist/src/styles/canon/graphviz.js +57 -9
  344. package/dist/src/styles/canon/graphviz.js.map +1 -1
  345. package/dist/src/styles/canon/number.d.ts +8 -0
  346. package/dist/src/styles/canon/number.d.ts.map +1 -1
  347. package/dist/src/styles/canon/number.js +18 -0
  348. package/dist/src/styles/canon/number.js.map +1 -1
  349. package/dist/src/styles/canon/text.d.ts +29 -2
  350. package/dist/src/styles/canon/text.d.ts.map +1 -1
  351. package/dist/src/styles/canon/text.js +156 -16
  352. package/dist/src/styles/canon/text.js.map +1 -1
  353. package/dist/src/styles/codes.d.ts +2 -0
  354. package/dist/src/styles/codes.d.ts.map +1 -1
  355. package/dist/src/styles/codes.js +2 -0
  356. package/dist/src/styles/codes.js.map +1 -1
  357. package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
  358. package/dist/src/styles/cyjs/cascade.js +1015 -79
  359. package/dist/src/styles/cyjs/cascade.js.map +1 -1
  360. package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
  361. package/dist/src/styles/cyjs/defaults-table.js +3 -0
  362. package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
  363. package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
  364. package/dist/src/styles/cyjs/emit.js +202 -9
  365. package/dist/src/styles/cyjs/emit.js.map +1 -1
  366. package/dist/src/styles/cyjs/face.d.ts +20 -0
  367. package/dist/src/styles/cyjs/face.d.ts.map +1 -0
  368. package/dist/src/styles/cyjs/face.js +332 -0
  369. package/dist/src/styles/cyjs/face.js.map +1 -0
  370. package/dist/src/styles/cyjs/mappers.d.ts +44 -1
  371. package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
  372. package/dist/src/styles/cyjs/mappers.js +461 -26
  373. package/dist/src/styles/cyjs/mappers.js.map +1 -1
  374. package/dist/src/styles/cyjs/routes.d.ts +53 -0
  375. package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
  376. package/dist/src/styles/cyjs/routes.js +360 -0
  377. package/dist/src/styles/cyjs/routes.js.map +1 -0
  378. package/dist/src/styles/cytoscape/charts.d.ts +23 -0
  379. package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
  380. package/dist/src/styles/cytoscape/charts.js +560 -0
  381. package/dist/src/styles/cytoscape/charts.js.map +1 -0
  382. package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
  383. package/dist/src/styles/cytoscape/emit.js +156 -48
  384. package/dist/src/styles/cytoscape/emit.js.map +1 -1
  385. package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
  386. package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
  387. package/dist/src/styles/cytoscape/lexicon.js +387 -77
  388. package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
  389. package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
  390. package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
  391. package/dist/src/styles/cytoscape/mappings.js +92 -0
  392. package/dist/src/styles/cytoscape/mappings.js.map +1 -1
  393. package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
  394. package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
  395. package/dist/src/styles/cytoscape/resolve.js +623 -17
  396. package/dist/src/styles/cytoscape/resolve.js.map +1 -1
  397. package/dist/src/styles/defaults.d.ts +46 -26
  398. package/dist/src/styles/defaults.d.ts.map +1 -1
  399. package/dist/src/styles/defaults.js +308 -71
  400. package/dist/src/styles/defaults.js.map +1 -1
  401. package/dist/src/styles/index.d.ts +4 -3
  402. package/dist/src/styles/index.d.ts.map +1 -1
  403. package/dist/src/styles/index.js +3 -2
  404. package/dist/src/styles/index.js.map +1 -1
  405. package/dist/src/styles/internal.d.ts +1 -0
  406. package/dist/src/styles/internal.d.ts.map +1 -1
  407. package/dist/src/styles/internal.js +1 -0
  408. package/dist/src/styles/internal.js.map +1 -1
  409. package/dist/src/styles/io/generic.d.ts.map +1 -1
  410. package/dist/src/styles/io/generic.js +56 -16
  411. package/dist/src/styles/io/generic.js.map +1 -1
  412. package/dist/src/styles/io/round-trip.d.ts +56 -0
  413. package/dist/src/styles/io/round-trip.d.ts.map +1 -0
  414. package/dist/src/styles/io/round-trip.js +138 -0
  415. package/dist/src/styles/io/round-trip.js.map +1 -0
  416. package/dist/src/styles/io/writer.d.ts.map +1 -1
  417. package/dist/src/styles/io/writer.js +6 -1
  418. package/dist/src/styles/io/writer.js.map +1 -1
  419. package/dist/src/styles/notes.d.ts.map +1 -1
  420. package/dist/src/styles/notes.js +1 -0
  421. package/dist/src/styles/notes.js.map +1 -1
  422. package/dist/src/styles/plan/features.d.ts +1 -1
  423. package/dist/src/styles/plan/features.d.ts.map +1 -1
  424. package/dist/src/styles/plan/features.js +22 -2
  425. package/dist/src/styles/plan/features.js.map +1 -1
  426. package/dist/src/styles/plan/index.d.ts +1 -1
  427. package/dist/src/styles/plan/index.d.ts.map +1 -1
  428. package/dist/src/styles/plan/index.js +1 -1
  429. package/dist/src/styles/plan/index.js.map +1 -1
  430. package/dist/src/styles/plan/plan.d.ts.map +1 -1
  431. package/dist/src/styles/plan/plan.js +61 -4
  432. package/dist/src/styles/plan/plan.js.map +1 -1
  433. package/dist/src/styles/plan/resolve.d.ts +11 -0
  434. package/dist/src/styles/plan/resolve.d.ts.map +1 -1
  435. package/dist/src/styles/plan/resolve.js +40 -4
  436. package/dist/src/styles/plan/resolve.js.map +1 -1
  437. package/dist/src/styles/slots.d.ts +14 -0
  438. package/dist/src/styles/slots.d.ts.map +1 -0
  439. package/dist/src/styles/slots.js +20 -0
  440. package/dist/src/styles/slots.js.map +1 -0
  441. package/dist/src/styles/types.d.ts +622 -6
  442. package/dist/src/styles/types.d.ts.map +1 -1
  443. package/dist/src/styles/vocabulary.d.ts +3 -2
  444. package/dist/src/styles/vocabulary.d.ts.map +1 -1
  445. package/dist/src/styles/vocabulary.js +203 -0
  446. package/dist/src/styles/vocabulary.js.map +1 -1
  447. package/dist/styles.js +30 -239
  448. package/dist/styles.js.map +1 -1
  449. package/dist/xgmml.js +3 -3
  450. package/package.json +27 -7
  451. package/src/formats/cx/importer.ts +6 -1
  452. package/src/formats/cx/styles.ts +143 -9
  453. package/src/formats/cx2/importer.ts +1 -0
  454. package/src/formats/cx2/styles.ts +3 -1
  455. package/src/formats/cys/importer.ts +1 -0
  456. package/src/formats/cys/styles.ts +27 -5
  457. package/src/formats/dot/drawing.ts +799 -0
  458. package/src/formats/dot/importer.ts +120 -35
  459. package/src/formats/dot/label-places.ts +228 -0
  460. package/src/formats/dot/record.ts +336 -0
  461. package/src/formats/dot/styles.ts +1654 -153
  462. package/src/formats/gexf/dialog-metrics.ts +61 -0
  463. package/src/formats/gexf/importer.ts +50 -5
  464. package/src/formats/gexf/preview.ts +217 -0
  465. package/src/formats/gexf/schema.ts +2 -1
  466. package/src/formats/gexf/styles.ts +1099 -245
  467. package/src/formats/gml/importer.ts +291 -76
  468. package/src/formats/gml/index.ts +1 -1
  469. package/src/formats/gml/positions.ts +29 -7
  470. package/src/formats/gml/styles.ts +851 -109
  471. package/src/formats/graphml/styles-plain.ts +6 -15
  472. package/src/formats/graphml/styles-yed.ts +762 -173
  473. package/src/formats/graphml/styles-yfiles3.ts +485 -63
  474. package/src/formats/graphml/yfiles.ts +19 -6
  475. package/src/formats/json/dialect.ts +41 -5
  476. package/src/formats/json/importer.ts +59 -7
  477. package/src/formats/json/index.ts +1 -0
  478. package/src/formats/json/positions.ts +22 -5
  479. package/src/formats/json/styles.ts +2041 -185
  480. package/src/formats/pajek/draw.ts +458 -0
  481. package/src/formats/pajek/exporter.ts +81 -49
  482. package/src/formats/pajek/importer.ts +278 -103
  483. package/src/formats/pajek/index.ts +1 -0
  484. package/src/formats/pajek/styles.ts +1381 -133
  485. package/src/formats/pajek/syntax.ts +27 -2
  486. package/src/formats/xgmml/emit.ts +73 -5
  487. package/src/formats/xgmml/styles.ts +330 -71
  488. package/src/index.ts +5 -1
  489. package/src/positions/convert.ts +12 -1
  490. package/src/positions/extract.ts +55 -1
  491. package/src/positions/index.ts +1 -0
  492. package/src/positions/types.ts +60 -0
  493. package/src/sources/builtins.ts +8 -1
  494. package/src/sources/context.ts +1 -0
  495. package/src/sources/cypher/descriptor.ts +7 -1
  496. package/src/sources/cypher/index.ts +148 -18
  497. package/src/sources/cypher/params.ts +1 -1
  498. package/src/sources/cypher/query-builder.ts +33 -0
  499. package/src/sources/ids.ts +6 -0
  500. package/src/sources/params.ts +3 -0
  501. package/src/sources/rest/descriptor.ts +5 -0
  502. package/src/sources/rest/source.ts +16 -0
  503. package/src/sources/sigv4.ts +6 -4
  504. package/src/sources/sparql/descriptor.ts +67 -0
  505. package/src/sources/sparql/index.ts +356 -0
  506. package/src/sources/sparql/ntriples.ts +219 -0
  507. package/src/sources/sparql/params.ts +28 -0
  508. package/src/sources/sparql/query.ts +162 -0
  509. package/src/sources/types.ts +35 -0
  510. package/src/styles/annotations.ts +201 -27
  511. package/src/styles/canon/bends.ts +137 -0
  512. package/src/styles/canon/color-tables.ts +10 -4
  513. package/src/styles/canon/color.ts +105 -3
  514. package/src/styles/canon/enums.ts +98 -8
  515. package/src/styles/canon/graphviz.ts +71 -10
  516. package/src/styles/canon/number.ts +19 -0
  517. package/src/styles/canon/text.ts +187 -16
  518. package/src/styles/codes.ts +2 -0
  519. package/src/styles/cyjs/cascade.ts +1160 -84
  520. package/src/styles/cyjs/defaults-table.ts +3 -0
  521. package/src/styles/cyjs/emit.ts +233 -13
  522. package/src/styles/cyjs/face.ts +372 -0
  523. package/src/styles/cyjs/mappers.ts +492 -27
  524. package/src/styles/cyjs/routes.ts +432 -0
  525. package/src/styles/cytoscape/charts.ts +684 -0
  526. package/src/styles/cytoscape/emit.ts +170 -48
  527. package/src/styles/cytoscape/lexicon.ts +431 -78
  528. package/src/styles/cytoscape/mappings.ts +108 -0
  529. package/src/styles/cytoscape/resolve.ts +741 -17
  530. package/src/styles/defaults.ts +417 -108
  531. package/src/styles/index.ts +5 -0
  532. package/src/styles/internal.ts +1 -0
  533. package/src/styles/io/generic.ts +79 -23
  534. package/src/styles/io/round-trip.ts +202 -0
  535. package/src/styles/io/writer.ts +6 -1
  536. package/src/styles/notes.ts +1 -0
  537. package/src/styles/plan/features.ts +23 -2
  538. package/src/styles/plan/index.ts +1 -1
  539. package/src/styles/plan/plan.ts +69 -5
  540. package/src/styles/plan/resolve.ts +47 -4
  541. package/src/styles/slots.ts +25 -0
  542. package/src/styles/types.ts +633 -5
  543. package/src/styles/vocabulary.ts +211 -2
  544. package/dist/chunks/block-Cu22ewuS.js.map +0 -1
  545. package/dist/chunks/choose-Cdx6Enl2.js +0 -57
  546. package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
  547. package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
  548. package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
  549. package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
  550. package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
  551. package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
  552. package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
  553. package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
  554. package/dist/chunks/format-BMS-1Nxb.js +0 -64
  555. package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
  556. package/dist/chunks/generic-CP6YD34u.js.map +0 -1
  557. package/dist/chunks/importer-B87_fmVx.js.map +0 -1
  558. package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
  559. package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
  560. package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
  561. package/dist/chunks/importer-DPZDN40-.js.map +0 -1
  562. package/dist/chunks/importer-e3huMZbm.js.map +0 -1
  563. package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
  564. package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
  565. package/dist/chunks/styles-CaABMoO1.js.map +0 -1
  566. package/dist/chunks/styles-P_gmFAOi.js +0 -770
  567. package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
  568. package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
  569. package/dist/chunks/writer-DvHTl36J.js +0 -449
  570. package/dist/chunks/writer-DvHTl36J.js.map +0 -1
@@ -6,6 +6,7 @@
6
6
  import { type CypherParams } from "./cypher/params.js";
7
7
  import { type NdexParams } from "./ndex/params.js";
8
8
  import { type OpenAlexParams, type RestParams } from "./rest/params.js";
9
+ import { type SparqlParams } from "./sparql/params.js";
9
10
 
10
11
  /**
11
12
  * Parameter types by source id; extend it by declaration merging:
@@ -26,4 +27,6 @@ export interface SourceParamsMap {
26
27
  rest: RestParams;
27
28
  /** OpenAlex. */
28
29
  openalex: OpenAlexParams;
30
+ /** Any SPARQL 1.1 endpoint. */
31
+ sparql: SparqlParams;
29
32
  }
@@ -17,6 +17,8 @@ export const REST_DESCRIPTOR: SourceDescriptor = Object.freeze({
17
17
  version: 1,
18
18
  auth: ["bearer", "api-key"],
19
19
  authRequired: "optional",
20
+ // ponytail: a mapping without `expand` or paging cannot do either; per-mapping features when a form needs them
21
+ features: ["expand", "probe", "validate", "page"],
20
22
  params: [{ name: "mapping", plainName: "Mapping", type: "text", required: true }],
21
23
  samples: [
22
24
  {
@@ -47,7 +49,9 @@ export const OPENALEX_DESCRIPTOR: SourceDescriptor = Object.freeze({
47
49
  defaultEndpoint: "https://api.openalex.org",
48
50
  auth: ["api-key"],
49
51
  authRequired: "optional",
52
+ apiKey: { query: "api_key" },
50
53
  rateLimit: { requests: 10, perMs: 1000 },
54
+ features: ["expand", "probe", "validate", "page"],
51
55
  params: [
52
56
  { name: "work", plainName: "Work", type: "string" },
53
57
  { name: "author", plainName: "Author", type: "string" },
@@ -69,6 +73,7 @@ export const OPENALEX_DESCRIPTOR: SourceDescriptor = Object.freeze({
69
73
  plainName: "Watts-Strogatz paper's citations",
70
74
  params: { work: "W2112090702" },
71
75
  whole: false,
76
+ firstPage: 200,
72
77
  },
73
78
  ],
74
79
  });
@@ -697,6 +697,21 @@ export type RestSourceInfo = {
697
697
  readonly id: string;
698
698
  } & Partial<SourceDescriptor>;
699
699
 
700
+ /**
701
+ * Where a mapping's API key goes, as a descriptor says it.
702
+ * @param auth - the mapping's auth
703
+ * @returns `{ apiKey }`, or nothing when the mapping takes no key or does not say where
704
+ */
705
+ function apiKeyOf(auth: RestMapping["auth"]): Pick<SourceDescriptor, "apiKey"> {
706
+ if (auth?.kind !== "api-key") {
707
+ return {};
708
+ }
709
+ if (auth.header !== undefined) {
710
+ return { apiKey: { header: auth.header } };
711
+ }
712
+ return auth.query === undefined ? {} : { apiKey: { query: auth.query } };
713
+ }
714
+
700
715
  /**
701
716
  * Turn a REST mapping into a source: a `records` source that loads the mapping's `load` request
702
717
  * page by page, with `expand` (breadth-first over the `expand` requests, `{ids}` batched; depth 0
@@ -733,6 +748,7 @@ export function restSource(mapping: RestMapping, info: RestSourceInfo): GraphSou
733
748
  defaultEndpoint: mapping.endpoint,
734
749
  auth,
735
750
  authRequired: auth.length === 0 ? "none" : "optional",
751
+ ...apiKeyOf(mapping.auth),
736
752
  ...(mapping.rateLimit === undefined ? {} : { rateLimit: mapping.rateLimit }),
737
753
  ...fields,
738
754
  });
@@ -75,12 +75,14 @@ async function sha256(data: Uint8Array | ArrayBuffer): Promise<string> {
75
75
  }
76
76
 
77
77
  /**
78
- * SHA-256 of a text's UTF-8 bytes, as lowercase hex (the Cypher source's content hash).
79
- * @param text - the text
78
+ * SHA-256 as 64 lowercase hexadecimal digits: of bytes exactly as given, or of a text's UTF-8 bytes
79
+ * (the Cypher source's content hash, a project file's record of a file it loaded). Web Crypto where
80
+ * there is one, else plain JavaScript (a page that is not a secure context). Experimental.
81
+ * @param data - the bytes or the text
80
82
  * @returns the digest
81
83
  */
82
- export function sha256Hex(text: string): Promise<string> {
83
- return sha256(utf8(text));
84
+ export function sha256Hex(data: string | Uint8Array): Promise<string> {
85
+ return sha256(typeof data === "string" ? utf8(data) : data);
84
86
  }
85
87
 
86
88
  /**
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The SPARQL source's descriptor: catalog data, available without loading the source's code.
3
+ */
4
+
5
+ import { type SourceDescriptor } from "../types.js";
6
+
7
+ /** A small Wikidata query: physics Nobel laureates and their doctoral advisors. */
8
+ const WIKIDATA_ADVISORS = `PREFIX wd: <http://www.wikidata.org/entity/>
9
+ PREFIX wdt: <http://www.wikidata.org/prop/direct/>
10
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
11
+ CONSTRUCT { ?person wdt:P184 ?advisor . ?person rdfs:label ?name . ?advisor rdfs:label ?advisorName . }
12
+ WHERE {
13
+ ?person wdt:P166 wd:Q38104 ; wdt:P184 ?advisor ; rdfs:label ?name .
14
+ ?advisor rdfs:label ?advisorName .
15
+ FILTER(lang(?name) = "en" && lang(?advisorName) = "en")
16
+ }`;
17
+
18
+ /**
19
+ * The descriptor of the `sparql` source. Experimental.
20
+ * @category Network sources
21
+ */
22
+ export const SPARQL_DESCRIPTOR: SourceDescriptor = Object.freeze({
23
+ plainName: "SPARQL endpoint",
24
+ kind: "sparql",
25
+ version: 1,
26
+ auth: ["basic", "bearer"],
27
+ authRequired: "optional",
28
+ features: ["expand", "probe", "validate", "page"],
29
+ params: [
30
+ { name: "query", plainName: "Query", type: "query", language: "sparql" },
31
+ {
32
+ name: "mode",
33
+ plainName: "Mode",
34
+ type: "enum",
35
+ values: [
36
+ { value: "query", label: "Query" },
37
+ { value: "all", label: "Everything" },
38
+ { value: "neighborhood", label: "Seed nodes" },
39
+ ],
40
+ },
41
+ { name: "ids", plainName: "Seed IRIs", type: "node-id" },
42
+ { name: "language", plainName: "Language", type: "string", advanced: true },
43
+ { name: "predicates", plainName: "Follow predicates", type: "string", advanced: true },
44
+ {
45
+ name: "pageSize",
46
+ plainName: "Page size",
47
+ type: "integer",
48
+ default: 1000,
49
+ min: 1,
50
+ max: 10000,
51
+ advanced: true,
52
+ },
53
+ ],
54
+ samples: [
55
+ {
56
+ id: "wikidata-physics-advisors",
57
+ plainName: "Wikidata: physics Nobel laureates and their advisors",
58
+ endpoint: "https://query.wikidata.org/sparql",
59
+ params: {
60
+ query: WIKIDATA_ADVISORS,
61
+ pageSize: 100,
62
+ language: "en",
63
+ predicates: ["http://www.wikidata.org/prop/direct/"], // NOSONAR(S5332): an RDF namespace IRI, never fetched; Wikidata's IRIs are http
64
+ },
65
+ },
66
+ ],
67
+ });
@@ -0,0 +1,356 @@
1
+ /**
2
+ * `@graphty/graph-io/sources/sparql`: the SPARQL source. It sends CONSTRUCT (or DESCRIBE) queries
3
+ * over the SPARQL 1.1 protocol (a form POST, N-Triples back) and reads the triples as a graph: an
4
+ * IRI or blank-node object is an edge from the subject (`type` is the predicate's local name,
5
+ * `predicate` the full IRI), a literal is an attribute of the subject named by the predicate's
6
+ * local name. Node ids are the IRIs.
7
+ *
8
+ * - Paging: the source adds `ORDER BY` (the template's variables) and `LIMIT` / `OFFSET` to the
9
+ * caller's query, unless it sets its own; a load stops between pages at a cap and hands back
10
+ * `{ offset }` as its cursor. A page is `pageSize` solutions, so its triple count varies; the
11
+ * first empty page ends the load.
12
+ * - Expand: the triples of the seeds, `VALUES ?s { ... }` out and `VALUES ?o { ... }` in.
13
+ * - Validate: SHA-256 of the first page's triples.
14
+ *
15
+ * Experimental.
16
+ * @module @graphty/graph-io/sources/sparql
17
+ */
18
+
19
+ import { type GraphSink } from "@graphty/graph-format";
20
+
21
+ import { throwIfAborted } from "../../common/input.js";
22
+ import { type ImportReport } from "../../types.js";
23
+ import { defineSource } from "../define.js";
24
+ import { failOn } from "../fail.js";
25
+ import { SPARQL_SOURCE_ID } from "../ids.js";
26
+ import { sha256Hex } from "../sigv4.js";
27
+ import {
28
+ type ExpandRequest,
29
+ type GraphSource,
30
+ type SourceContext,
31
+ type SourceCursor,
32
+ type SourceFreshness,
33
+ type SourceProbe,
34
+ } from "../types.js";
35
+ import { SPARQL_DESCRIPTOR } from "./descriptor.js";
36
+ import { canonicalTriple, type Graphed, graphTriples, parseNTriples, type Triple } from "./ntriples.js";
37
+ import { type SparqlParams } from "./params.js";
38
+ import { allQuery, aroundQuery, iriTerm, pagedQuery, readQuery, validLanguage } from "./query.js";
39
+
40
+ export { SPARQL_DESCRIPTOR } from "./descriptor.js";
41
+ export { type SparqlParams } from "./params.js";
42
+
43
+ /** Solutions per page when the params name none. */
44
+ const DEFAULT_PAGE_SIZE = 1000;
45
+
46
+ /** Triples per hop of an expansion when the request names no limit. */
47
+ const DEFAULT_EXPAND_LIMIT = 500;
48
+
49
+ /** The deepest expansion, as for every built-in source. */
50
+ const MAX_DEPTH = 10;
51
+
52
+ /** What CONSTRUCT and DESCRIBE are asked to answer. */
53
+ const ACCEPT_TRIPLES = "application/n-triples, text/plain;q=0.9";
54
+
55
+ /** One page's query, by offset; `paged` false when the query is sent once, as written. */
56
+ interface Plan {
57
+ /** The query of the page at an offset. */
58
+ readonly at: (offset: number) => string;
59
+ /** Whether the source pages it. */
60
+ readonly paged: boolean;
61
+ }
62
+
63
+ /**
64
+ * Send a query and read the answer as N-Triples.
65
+ * @param ctx - the context
66
+ * @param query - the query
67
+ * @returns the triples
68
+ */
69
+ async function send(ctx: SourceContext, query: string): Promise<Triple[]> {
70
+ throwIfAborted(ctx.signal);
71
+ const response = await ctx.fetch(ctx.endpoint ?? "", {
72
+ method: "POST",
73
+ idempotent: true,
74
+ headers: { Accept: ACCEPT_TRIPLES, "Content-Type": "application/x-www-form-urlencoded" },
75
+ body: new URLSearchParams({ query }).toString(),
76
+ allowStatus: [400],
77
+ });
78
+ if (response.status === 400) {
79
+ const text = (await response.text()).trim().slice(0, 500);
80
+ failOn(ctx.report, "E_SOURCE_QUERY", "the endpoint refused the query", {
81
+ serverCode: null,
82
+ line: null,
83
+ column: null,
84
+ serverMessage: text === "" ? null : text,
85
+ });
86
+ }
87
+ const contentType = response.headers.get("content-type");
88
+ const notTriples = (): never =>
89
+ failOn(ctx.report, "E_SOURCE_RESPONSE", "the endpoint did not answer N-Triples", {
90
+ expected: "n-triples",
91
+ contentType,
92
+ });
93
+ if (contentType !== null && /html|json|xml/i.test(contentType)) {
94
+ notTriples();
95
+ }
96
+ const { triples, badLine } = parseNTriples(await response.text());
97
+ if (badLine !== null) {
98
+ notTriples();
99
+ }
100
+ return triples;
101
+ }
102
+
103
+ /**
104
+ * A whole-number param, checked.
105
+ * @param value - the value
106
+ * @param name - the param
107
+ * @param max - the largest allowed
108
+ * @param ctx - the context
109
+ * @returns the number
110
+ */
111
+ function integer(value: number, name: string, max: number, ctx: SourceContext): number {
112
+ if (!Number.isInteger(value) || value < 1 || value > max) {
113
+ failOn(ctx.report, "E_SOURCE_PARAM", `${name} is an integer from 1 to ${String(max)}`, {
114
+ name,
115
+ reason: "range",
116
+ });
117
+ }
118
+ return value;
119
+ }
120
+
121
+ /**
122
+ * The language filter, lowercase and checked, or "" for none.
123
+ * @param params - the params
124
+ * @param ctx - the context
125
+ * @returns the tag
126
+ */
127
+ function languageOf(params: SparqlParams, ctx: SourceContext): string {
128
+ const language = params.language ?? "";
129
+ if (language !== "" && !validLanguage(language)) {
130
+ failOn(ctx.report, "E_SOURCE_PARAM", "language is a language tag", { name: "language", reason: "type" });
131
+ }
132
+ return language.toLowerCase();
133
+ }
134
+
135
+ /**
136
+ * The predicate prefixes generated queries follow, checked.
137
+ * @param params - the params
138
+ * @param ctx - the context
139
+ * @returns the prefixes; empty means every predicate
140
+ */
141
+ function predicatesOf(params: SparqlParams, ctx: SourceContext): readonly string[] {
142
+ const list = params.predicates ?? [];
143
+ const prefixes = typeof list === "string" ? [list] : list;
144
+ for (const p of prefixes) {
145
+ if (typeof p !== "string" || iriTerm(p) === null) {
146
+ failOn(ctx.report, "E_SOURCE_PARAM", "predicates are IRI prefixes", { name: "predicates", reason: "iri" });
147
+ }
148
+ }
149
+ return prefixes;
150
+ }
151
+
152
+ /**
153
+ * Seed ids as IRI terms; a blank node or anything else that is not an IRI is refused.
154
+ * @param ids - the ids
155
+ * @param name - the param, for the error
156
+ * @param ctx - the context
157
+ * @returns the terms
158
+ */
159
+ function irisOf(ids: readonly unknown[] | undefined, name: string, ctx: SourceContext): string[] {
160
+ if (ids === undefined || ids.length === 0) {
161
+ failOn(ctx.report, "E_SOURCE_PARAM", `${name} needs at least one IRI`, { name, reason: "required" });
162
+ }
163
+ return ids.map(
164
+ (id) => iriTerm(id) ?? failOn(ctx.report, "E_SOURCE_PARAM", `${name}: not an IRI`, { name, reason: "iri" }),
165
+ );
166
+ }
167
+
168
+ /**
169
+ * What a load sends, from its mode.
170
+ * @param params - the params
171
+ * @param ctx - the context
172
+ * @returns the plan
173
+ */
174
+ function planOf(params: SparqlParams, ctx: SourceContext): Plan {
175
+ const size = integer(params.pageSize ?? DEFAULT_PAGE_SIZE, "pageSize", 10_000, ctx);
176
+ const filter = { language: languageOf(params, ctx), predicates: predicatesOf(params, ctx) };
177
+ const query = params.query?.trim() ?? "";
178
+ const mode = params.mode ?? (query === "" ? "all" : "query");
179
+ if (mode === "neighborhood") {
180
+ const iris = irisOf(params.ids, "ids", ctx);
181
+ return { at: (offset) => aroundQuery(iris, "both", filter, size, offset), paged: true };
182
+ }
183
+ if (mode === "all") {
184
+ return { at: (offset) => allQuery(filter, size, offset), paged: true };
185
+ }
186
+ if (query === "") {
187
+ failOn(ctx.report, "E_SOURCE_PARAM", "mode query needs a query", { name: "query", reason: "required" });
188
+ }
189
+ const shape = readQuery(query);
190
+ if (shape.form !== "construct" && shape.form !== "describe") {
191
+ failOn(ctx.report, "E_SOURCE_PARAM", "the query must be CONSTRUCT or DESCRIBE", {
192
+ name: "query",
193
+ reason: "form",
194
+ });
195
+ }
196
+ if (shape.ownLimit) {
197
+ return { at: () => query, paged: false };
198
+ }
199
+ return { at: (offset) => pagedQuery(query, shape, size, offset), paged: true };
200
+ }
201
+
202
+ /**
203
+ * Write nodes and edges into the sink, counting them on the report.
204
+ * @param graphed - the nodes and edges
205
+ * @param sink - where to write
206
+ * @param ctx - the context
207
+ */
208
+ function write(graphed: Graphed, sink: GraphSink, ctx: SourceContext): void {
209
+ const { report } = ctx;
210
+ if (sink.edgeCount === 0) {
211
+ sink.setDirected(true);
212
+ }
213
+ for (const [id, attrs] of graphed.nodes) {
214
+ try {
215
+ sink.addNodeRecord(id, attrs);
216
+ report.counts.nodes++;
217
+ } catch (err) {
218
+ report.recordError(err, { element: id });
219
+ report.counts.skippedNodes++;
220
+ }
221
+ }
222
+ for (const { source, target, ...attrs } of graphed.edges) {
223
+ try {
224
+ sink.addEdgeRecord(source, target, attrs, null);
225
+ report.counts.edges++;
226
+ } catch (err) {
227
+ report.recordError(err, { element: `${source} -> ${target}` });
228
+ report.counts.skippedEdges++;
229
+ }
230
+ }
231
+ }
232
+
233
+ /**
234
+ * The content hash of some triples, in any order.
235
+ * @param triples - the triples
236
+ * @returns the SHA-256, hex
237
+ */
238
+ function hashOf(triples: readonly Triple[]): Promise<string> {
239
+ return sha256Hex(triples.map(canonicalTriple).sort().join("\n")); // NOSONAR(S2871): code-unit order is the point: a locale-free, stable order for the hash
240
+ }
241
+
242
+ /**
243
+ * Load pages into the sink from the cursor's offset until an empty page or a cap.
244
+ * @param params - the params
245
+ * @param sink - where to write
246
+ * @param ctx - the context
247
+ * @returns the report
248
+ */
249
+ async function load(params: SparqlParams, sink: GraphSink, ctx: SourceContext): Promise<ImportReport> {
250
+ const plan = planOf(params, ctx);
251
+ const size = params.pageSize ?? DEFAULT_PAGE_SIZE;
252
+ const start = Number(ctx.cursor?.offset ?? 0);
253
+ const language = languageOf(params, ctx);
254
+ let offset = start;
255
+ let next: SourceCursor | null = null;
256
+ let contentHash: string | undefined;
257
+ for (;;) {
258
+ const triples = await send(ctx, plan.at(offset));
259
+ if (offset === 0) {
260
+ contentHash = await hashOf(triples);
261
+ }
262
+ write(graphTriples(triples, language), sink, ctx);
263
+ const { counts } = ctx.report;
264
+ ctx.progress(counts.nodes + counts.edges, undefined, "items");
265
+ if (!plan.paged || triples.length === 0) {
266
+ next = null;
267
+ break;
268
+ }
269
+ offset += size;
270
+ next = { offset };
271
+ if (ctx.limits.reached()) {
272
+ break;
273
+ }
274
+ }
275
+ return ctx.finish({ next, ...(contentHash === undefined ? {} : { validators: { contentHash } }) });
276
+ }
277
+
278
+ /**
279
+ * Fetch the triples around some IRIs into the sink, hop by hop.
280
+ * @param request - the seeds, direction, depth, limit and predicate filter
281
+ * @param sink - where to write
282
+ * @param ctx - the context
283
+ * @returns the report
284
+ */
285
+ async function expand(
286
+ request: ExpandRequest<SparqlParams>,
287
+ sink: GraphSink,
288
+ ctx: SourceContext,
289
+ ): Promise<ImportReport> {
290
+ const direction = request.direction ?? "both";
291
+ if (!["out", "in", "both"].includes(direction)) {
292
+ failOn(ctx.report, "E_SOURCE_PARAM", "direction must be out, in or both", {
293
+ name: "direction",
294
+ reason: "enum",
295
+ });
296
+ }
297
+ const depth = integer(request.depth ?? 1, "depth", MAX_DEPTH, ctx);
298
+ const limit = integer(request.limit ?? DEFAULT_EXPAND_LIMIT, "limit", Number.MAX_SAFE_INTEGER, ctx);
299
+ const language = languageOf(request.params, ctx);
300
+ const filter = { language, predicates: predicatesOf(request.params, ctx) };
301
+ const types = request.relationshipTypes === undefined ? null : new Set(request.relationshipTypes);
302
+ // a capped one-hop expansion resumes at its offset; deeper ones are read whole per hop
303
+ const offset = depth === 1 ? Number(ctx.cursor?.offset ?? 0) : 0;
304
+ const seen = new Set<string>(request.ids.map(String));
305
+ let frontier = irisOf(request.ids, "ids", ctx);
306
+ let next: SourceCursor | null = null;
307
+ const graphed: Graphed = { nodes: new Map(), edges: [] };
308
+ for (let hop = 0; hop < depth && frontier.length > 0; hop++) {
309
+ const triples = await send(ctx, aroundQuery(frontier, direction, filter, limit, offset));
310
+ const before = graphed.edges.length;
311
+ graphTriples(triples, language, graphed);
312
+ if (types !== null) {
313
+ const kept = graphed.edges.slice(before).filter((e) => types.has(e.type) || types.has(e.predicate));
314
+ graphed.edges.splice(before, Infinity, ...kept);
315
+ }
316
+ if (depth === 1 && triples.length > 0) {
317
+ next = { offset: offset + limit };
318
+ }
319
+ const reached = graphed.edges.slice(before).flatMap((e) => [e.source, e.target]);
320
+ frontier = [...new Set(reached)]
321
+ .filter((id) => !seen.has(id))
322
+ .flatMap((id) => {
323
+ seen.add(id);
324
+ const term = iriTerm(id);
325
+ return term === null ? [] : [term];
326
+ });
327
+ }
328
+ write(graphed, sink, ctx);
329
+ return ctx.finish({ next });
330
+ }
331
+
332
+ /**
333
+ * The SPARQL source: CONSTRUCT or DESCRIBE queries against any SPARQL 1.1 endpoint, paged by
334
+ * `LIMIT` and `OFFSET`, expanded by `VALUES`, validated by a hash of the first page. Experimental.
335
+ * @category Network sources
336
+ */
337
+ export const sparqlSource: GraphSource<SparqlParams> = defineSource<SparqlParams>({
338
+ id: SPARQL_SOURCE_ID,
339
+ descriptor: SPARQL_DESCRIPTOR,
340
+ import: load,
341
+ expand,
342
+ probe: async (params, ctx): Promise<SourceProbe> => {
343
+ // the endpoint answers a one-solution query: it is up, it reads SPARQL, the credential works
344
+ await send(ctx, "CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 1");
345
+ languageOf(params, ctx);
346
+ return { ok: true };
347
+ },
348
+ validate: async (params, seen, ctx): Promise<SourceFreshness> => {
349
+ const contentHash = await hashOf(await send(ctx, planOf(params, ctx).at(0)));
350
+ let status: SourceFreshness["status"] = "unverifiable";
351
+ if (seen.contentHash !== undefined) {
352
+ status = seen.contentHash === contentHash ? "current" : "changed";
353
+ }
354
+ return { status, via: "hash", validators: { contentHash } };
355
+ },
356
+ });