@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
@@ -1 +1 @@
1
- {"version":3,"file":"sources-rest.js","sources":["../src/sources/rest/selectors.ts","../src/sources/rest/templates.ts","../src/sources/rest/mapping.ts","../src/sources/rest/paging.ts","../src/sources/rest/records.ts","../src/sources/rest/source.ts","../src/sources/rest/openalex.ts"],"sourcesContent":["/**\n * Selectors of the REST mapping (design section 13.2): graph-io's dotted paths plus `[]` to flatten\n * an array. `results`, `meta.next_cursor`, `authorships[].author.id`; `.` is the value itself and\n * `#` is a record's position in the array it came from. Not JMESPath, so graph-io keeps zero\n * dependencies.\n */\n\n/** One step of a selector: a key, and whether its value's array is flattened. */\ninterface Step {\n readonly key: string;\n readonly flatten: boolean;\n}\n\n/** A key: anything but a dot or a bracket. */\nconst STEP = /^([^.[\\]]+)(\\[\\])?$/;\n\n/** Parsed selectors, by text. */\nconst PARSED = new Map<string, readonly Step[] | null>();\n\n/**\n * Parse a selector.\n * @param selector - the text\n * @returns its steps ([] for \".\"), or null when it is not a selector\n */\nexport function parseSelector(selector: string): readonly Step[] | null {\n const cached = PARSED.get(selector);\n if (cached !== undefined) {\n return cached;\n }\n let steps: Step[] | null = [];\n if (selector !== \".\") {\n for (const part of selector.split(\".\")) {\n const m = STEP.exec(part);\n if (m === null) {\n steps = null;\n break;\n }\n steps.push({ key: m[1], flatten: m[2] !== undefined });\n }\n }\n PARSED.set(selector, steps);\n return steps;\n}\n\n/**\n * Every value a selector reaches, in document order; missing keys reach nothing.\n * @param value - where to start\n * @param selector - the selector (a checked mapping holds only valid ones)\n * @returns the values\n */\nexport function select(value: unknown, selector: string): unknown[] {\n let out: unknown[] = value === undefined ? [] : [value];\n for (const step of parseSelector(selector) ?? []) {\n const next: unknown[] = [];\n for (const v of out) {\n if (typeof v !== \"object\" || v === null || !Object.hasOwn(v, step.key)) {\n continue;\n }\n const got = (v as Record<string, unknown>)[step.key];\n if (step.flatten && Array.isArray(got)) {\n next.push(...(got as unknown[]));\n } else if (got !== undefined && got !== null) {\n next.push(got);\n }\n }\n out = next;\n }\n return out.filter((v) => v !== null && v !== undefined);\n}\n\n/**\n * The first value a selector reaches.\n * @param value - where to start\n * @param selector - the selector\n * @returns the value, or undefined\n */\nexport function selectOne(value: unknown, selector: string): unknown {\n return select(value, selector)[0];\n}\n\n/**\n * The records a request's `records` selector names: an array it reaches is the records, any other\n * value is one record.\n * @param body - the response body\n * @param selector - the selector\n * @returns the records\n */\nexport function selectRecords(body: unknown, selector: string): unknown[] {\n const out = select(body, selector);\n return out.length === 1 && Array.isArray(out[0]) ? (out[0] as unknown[]) : out;\n}\n","/**\n * Templates of the REST mapping (design section 13.2): `{name}` takes a value. Every value is\n * URL-encoded for its position, a value cannot add a path segment, and the finished URL must have\n * the mapping endpoint's origin and stay under its path.\n */\n\nimport { type ImportReportBuilder } from \"../../common/report.js\";\nimport { failOn } from \"../fail.js\";\nimport { type RestRequest } from \"./params.js\";\n\n/** One `{name}` in a template. */\nconst SLOT = /\\{([^{}]*)\\}/g;\n\n/** A slot name. */\nconst NAME = /^[A-Za-z_][A-Za-z0-9_-]*$/;\n\n/** The values templates are filled from: params as strings, plus `{id}` and `{ids}`. */\nexport type TemplateValues = Readonly<Record<string, string>>;\n\n/**\n * The slot names of a template, or null when its braces are malformed.\n * @param template - the template\n * @returns the names\n */\nexport function templateNames(template: string): string[] | null {\n const names: string[] = [];\n for (const m of template.matchAll(SLOT)) {\n if (!NAME.test(m[1])) {\n return null;\n }\n names.push(m[1]);\n }\n // a brace left over after the slots is malformed\n return /[{}]/.test(template.replaceAll(SLOT, \"\")) ? null : names;\n}\n\n/**\n * Fill a template.\n * @param template - the template\n * @param values - the values\n * @param encode - how a value is encoded for its position\n * @param report - the load's report, for a missing value\n * @returns the filled text\n */\nfunction fill(\n template: string,\n values: TemplateValues,\n encode: (value: string) => string,\n report: ImportReportBuilder,\n): string {\n return template.replaceAll(SLOT, (_, name: string) => {\n const value = values[name];\n if (value === undefined) {\n failOn(report, \"E_SOURCE_PARAM\", `the mapping's template needs ${name}`, { name, reason: \"required\" });\n }\n return encode(value);\n });\n}\n\n/**\n * A path value: percent-encoded, so a slash cannot add a segment, and never a dot segment.\n * @param report - the load's report\n * @returns the encoder\n */\nfunction pathValue(report: ImportReportBuilder): (value: string) => string {\n return (value) => {\n // \".\" and \"..\" stay dot segments even percent-encoded, so the URL parser would climb out\n if (value === \".\" || value === \"..\" || value === \"\") {\n failOn(report, \"E_SOURCE_PARAM\", \"a path value may not be empty or a dot segment\", {\n name: \"path\",\n reason: \"path\",\n });\n }\n return encodeURIComponent(value);\n };\n}\n\n/**\n * Check that a URL stays on the mapping's origin and under its path.\n * @param url - the URL\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the URL\n */\nexport function checkOrigin(url: URL, endpoint: URL, report: ImportReportBuilder): URL {\n const base = endpoint.pathname.replace(/\\/$/, \"\");\n if (url.origin !== endpoint.origin || !(url.pathname === base || url.pathname.startsWith(`${base}/`))) {\n failOn(report, \"E_SOURCE_PARAM\", \"a request left the mapping's endpoint\", { name: \"url\", reason: \"origin\" });\n }\n return url;\n}\n\n/**\n * The URL and init of one request.\n * @param endpoint - the mapping's endpoint\n * @param request - the request\n * @param values - the template values\n * @param report - the load's report\n * @returns the URL and the fetch init\n */\nexport function buildRequest(\n endpoint: URL,\n request: RestRequest,\n values: TemplateValues,\n report: ImportReportBuilder,\n): { url: URL; init: RequestInit & { idempotent?: boolean } } {\n const path = fill(request.path, values, pathValue(report), report);\n const url = new URL(`${endpoint.origin}${endpoint.pathname.replace(/\\/$/, \"\")}${path}`);\n for (const [key, template] of Object.entries(request.query ?? {})) {\n // URLSearchParams encodes the value for the query\n url.searchParams.set(\n key,\n fill(template, values, (v) => v, report),\n );\n }\n checkOrigin(url, endpoint, report);\n if (request.method !== \"POST\") {\n return { url, init: {} };\n }\n const body = fillBody(request.body, values, report);\n return {\n url,\n init: {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body ?? null),\n // a mapping's POST reads; it is a query, so it is as safe to retry as a GET\n idempotent: true,\n },\n };\n}\n\n/**\n * Fill the string leaves of a POST body.\n * @param body - the body template\n * @param values - the values\n * @param report - the load's report\n * @returns the body\n */\nfunction fillBody(body: unknown, values: TemplateValues, report: ImportReportBuilder): unknown {\n if (typeof body === \"string\") {\n return fill(body, values, (v) => v, report);\n }\n if (Array.isArray(body)) {\n return body.map((b) => fillBody(b, values, report));\n }\n if (typeof body === \"object\" && body !== null) {\n return Object.fromEntries(Object.entries(body).map(([k, v]) => [k, fillBody(v, values, report)]));\n }\n return body;\n}\n","/**\n * Checking a REST mapping before it runs (design section 13.2). A mapping is JSON data, typed into\n * a form or read from a project file, so every field is checked and every problem is a coded\n * issue naming where it is.\n */\n\nimport { type RestEdgeRule, type RestEntity, type RestMapping, type RestRequest } from \"./params.js\";\nimport { parseSelector } from \"./selectors.js\";\nimport { templateNames } from \"./templates.js\";\n\n/**\n * What is wrong with one field of a mapping. Open union.\n * @category Network sources\n */\nexport type RestMappingIssueCode =\n | \"version\" // version is not 1\n | \"endpoint\" // not an http(s) URL, or one holding a user, query or fragment\n | \"missing\" // a required field is absent or of the wrong type\n | \"unknown-request\" // names a request the mapping lacks\n | \"unknown-entity\" // names an entity the mapping lacks\n | \"selector\" // not a selector\n | \"template\" // malformed braces or slot names\n | \"paging\" // an unknown paging style or a bad paging field\n | \"batch\" // batch.max is not a positive integer, or join is not a string\n | \"number\" // not a positive number\n | (string & {}); // NOSONAR(S4335): the open-union idiom keeps the listed codes in editor completion\n\n/**\n * One problem `checkRestMapping` found. Experimental.\n * @category Network sources\n */\nexport interface RestMappingIssue {\n /** What is wrong. */\n readonly code: RestMappingIssueCode;\n /** Where, as a dotted path into the mapping (`requests.citing.paging.next`). */\n readonly at: string;\n}\n\n/** The checks' accumulator. */\ntype Push = (code: RestMappingIssueCode, at: string) => void;\n\n/**\n * Whether a value is a plain object.\n * @param v - the value\n * @returns true for an object that is not an array\n */\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * Check a selector field.\n * @param value - the field\n * @param at - where it is\n * @param push - the accumulator\n * @param required - whether it must be present\n * @param index - whether `#` (the record's position) is allowed\n */\nfunction checkSelector(value: unknown, at: string, push: Push, required: boolean, index = false): void {\n if (value === undefined && !required) {\n return;\n }\n if (typeof value !== \"string\") {\n push(\"missing\", at);\n } else if (!(index && value === \"#\") && parseSelector(value) === null) {\n push(\"selector\", at);\n }\n}\n\n/**\n * Check a template field.\n * @param value - the field\n * @param at - where it is\n * @param push - the accumulator\n */\nfunction checkTemplate(value: unknown, at: string, push: Push): void {\n if (typeof value !== \"string\") {\n push(\"missing\", at);\n } else if (templateNames(value) === null) {\n push(\"template\", at);\n }\n}\n\n/**\n * Check a request's query templates.\n * @param query - the query field\n * @param at - where the request is\n * @param push - the accumulator\n */\nfunction checkQuery(query: RestRequest[\"query\"], at: string, push: Push): void {\n if (query === undefined) {\n return;\n }\n if (!isObject(query)) {\n push(\"missing\", `${at}.query`);\n return;\n }\n for (const [k, v] of Object.entries(query)) {\n checkTemplate(v, `${at}.query.${k}`, push);\n }\n}\n\n/**\n * Whether a batch field is well formed: a positive integer max and a string join.\n * @param batch - the batch field\n * @returns true when it is\n */\nfunction isBatch(batch: RestRequest[\"batch\"]): boolean {\n return isObject(batch) && Number.isInteger(batch.max) && batch.max >= 1 && typeof batch.join === \"string\";\n}\n\n/**\n * Check one request.\n * @param r - the request\n * @param at - where it is\n * @param entities - the mapping's entity names\n * @param push - the accumulator\n */\nfunction checkRequest(r: RestRequest, at: string, entities: ReadonlySet<string>, push: Push): void {\n if (!isObject(r)) {\n push(\"missing\", at);\n return;\n }\n if (r.method !== undefined && r.method !== \"GET\" && r.method !== \"POST\") {\n push(\"missing\", `${at}.method`);\n }\n checkTemplate(r.path, `${at}.path`, push);\n if (typeof r.path === \"string\" && !r.path.startsWith(\"/\")) {\n push(\"template\", `${at}.path`);\n }\n checkQuery(r.query, at, push);\n checkSelector(r.records, `${at}.records`, push, true);\n if (typeof r.entity !== \"string\") {\n push(\"missing\", `${at}.entity`);\n } else if (!entities.has(r.entity)) {\n push(\"unknown-entity\", `${at}.entity`);\n }\n if (r.batch !== undefined && !isBatch(r.batch)) {\n push(\"batch\", `${at}.batch`);\n }\n if (r.paging !== undefined) {\n checkPaging(r.paging, `${at}.paging`, push);\n }\n}\n\n/**\n * Check a paging field.\n * @param p - the paging\n * @param at - where it is\n * @param push - the accumulator\n */\nfunction checkPaging(p: RestRequest[\"paging\"], at: string, push: Push): void {\n const paging = p as Record<string, unknown> | undefined;\n if (!isObject(paging)) {\n push(\"paging\", at);\n return;\n }\n switch (paging.style) {\n case \"cursor\":\n if (typeof paging.param !== \"string\" || typeof paging.first !== \"string\") {\n push(\"paging\", at);\n }\n checkSelector(paging.next, `${at}.next`, push, true);\n break;\n case \"offset\": {\n const size = paging.size as Record<string, unknown> | undefined;\n const ok =\n typeof paging.param === \"string\" &&\n isObject(size) &&\n typeof size.param === \"string\" &&\n Number.isInteger(size.value) &&\n (size.value as number) > 0 &&\n (paging.unit === undefined || paging.unit === \"items\" || paging.unit === \"pages\") &&\n (paging.base === undefined || paging.base === 0 || paging.base === 1);\n if (!ok) {\n push(\"paging\", at);\n }\n break;\n }\n case \"link-header\":\n if (paging.rel !== undefined && typeof paging.rel !== \"string\") {\n push(\"paging\", at);\n }\n break;\n case \"next-url\":\n checkSelector(paging.next, `${at}.next`, push, true);\n break;\n default:\n push(\"paging\", `${at}.style`);\n }\n}\n\n/**\n * Check one edge rule.\n * @param rule - the rule\n * @param at - where it is\n * @param entities - the mapping's entity names\n * @param push - the accumulator\n */\nfunction checkEdgeRule(rule: RestEdgeRule, at: string, entities: ReadonlySet<string>, push: Push): void {\n if (!isObject(rule)) {\n push(\"missing\", at);\n return;\n }\n const r = rule as Record<string, unknown>;\n if (typeof r.type !== \"string\") {\n push(\"missing\", `${at}.type`);\n }\n checkSelector(r.each, `${at}.each`, push, false);\n if (\"pairs\" in r) {\n checkSelector(r.pairs, `${at}.pairs`, push, true);\n } else {\n checkSelector(r.to, `${at}.to`, push, true);\n checkSelector(r.from, `${at}.from`, push, false);\n if (isObject(r.fields)) {\n for (const [k, v] of Object.entries(r.fields)) {\n checkSelector(v, `${at}.fields.${k}`, push, true);\n }\n } else if (r.fields !== undefined) {\n push(\"missing\", `${at}.fields`);\n }\n }\n if (r.entity !== undefined && (typeof r.entity !== \"string\" || !entities.has(r.entity))) {\n push(\"unknown-entity\", `${at}.entity`);\n }\n}\n\n/**\n * Check one entity.\n * @param e - the entity\n * @param at - where it is\n * @param entities - the mapping's entity names\n * @param push - the accumulator\n */\nfunction checkEntity(e: RestEntity, at: string, entities: ReadonlySet<string>, push: Push): void {\n if (!isObject(e)) {\n push(\"missing\", at);\n return;\n }\n checkSelector(e.id, `${at}.id`, push, true, true);\n if (e.stripPrefix !== undefined && typeof e.stripPrefix !== \"string\") {\n push(\"missing\", `${at}.stripPrefix`);\n }\n if (e.label !== undefined && typeof e.label !== \"string\") {\n push(\"missing\", `${at}.label`);\n }\n if (e.node !== undefined && e.node) {\n push(\"missing\", `${at}.node`);\n }\n if (isObject(e.fields)) {\n for (const [k, v] of Object.entries(e.fields)) {\n checkSelector(v, `${at}.fields.${k}`, push, true, true);\n }\n } else if (e.fields !== undefined) {\n push(\"missing\", `${at}.fields`);\n }\n if (Array.isArray(e.edges)) {\n (e.edges as readonly RestEdgeRule[]).forEach((rule, i) => {\n checkEdgeRule(rule, `${at}.edges.${String(i)}`, entities, push);\n });\n } else if (e.edges !== undefined) {\n push(\"missing\", `${at}.edges`);\n }\n if (Array.isArray(e.embedded)) {\n e.embedded.forEach((em, i) => {\n const where = `${at}.embedded.${String(i)}`;\n if (!isObject(em)) {\n push(\"missing\", where);\n return;\n }\n checkSelector(em.at, `${where}.at`, push, true);\n if (typeof em.entity !== \"string\" || !entities.has(em.entity)) {\n push(\"unknown-entity\", `${where}.entity`);\n }\n });\n } else if (e.embedded !== undefined) {\n push(\"missing\", `${at}.embedded`);\n }\n}\n\n/**\n * Check the mapping's top-level names of requests.\n * @param m - the mapping\n * @param requests - its request names\n * @param push - the accumulator\n */\nfunction checkRequestNames(m: RestMapping, requests: ReadonlySet<string>, push: Push): void {\n const names: [string, unknown][] = [\n [\"load\", m.load],\n [\"hydrate\", m.hydrate],\n [\"seed\", m.seed],\n ];\n if (isObject(m.expand)) {\n names.push([\"expand.in\", m.expand.in], [\"expand.out\", m.expand.out]);\n } else {\n names.push([\"expand\", m.expand]);\n }\n for (const [at, name] of names) {\n if (name === undefined && at !== \"load\") {\n continue;\n }\n if (typeof name !== \"string\") {\n push(\"missing\", at);\n } else if (!requests.has(name)) {\n push(\"unknown-request\", at);\n }\n }\n}\n\n/**\n * Check the endpoint.\n * @param endpoint - the field\n * @param push - the accumulator\n */\nfunction checkEndpoint(endpoint: unknown, push: Push): void {\n let url: URL | null = null;\n try {\n url = new URL(typeof endpoint === \"string\" ? endpoint : \"\");\n } catch {\n // not a URL\n }\n if (\n url === null ||\n (url.protocol !== \"https:\" && url.protocol !== \"http:\") ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n url.search !== \"\" ||\n url.hash !== \"\"\n ) {\n push(\"endpoint\", \"endpoint\");\n }\n}\n\n/**\n * Check a REST mapping without running it: the version, the endpoint, every request (templates,\n * selectors, paging, batching) and entity (selectors, edge rules, embedded records), and that every\n * name it uses exists. Experimental.\n * @param mapping - the mapping, as data from anywhere\n * @returns every problem found; empty when the mapping can run\n * @category Network sources\n */\nexport function checkRestMapping(mapping: unknown): readonly RestMappingIssue[] {\n const issues: RestMappingIssue[] = [];\n const push: Push = (code, at) => {\n issues.push(Object.freeze({ code, at }));\n };\n if (!isObject(mapping)) {\n push(\"missing\", \"\");\n return issues;\n }\n const m = mapping as unknown as RestMapping;\n if (m.version !== 1) {\n push(\"version\", \"version\");\n }\n checkEndpoint(m.endpoint, push);\n const requests = isObject(m.requests) ? m.requests : {};\n const entities = isObject(m.entities) ? m.entities : {};\n if (!isObject(m.requests)) {\n push(\"missing\", \"requests\");\n }\n if (!isObject(m.entities)) {\n push(\"missing\", \"entities\");\n }\n const entityNames = new Set(Object.keys(entities));\n for (const [name, r] of Object.entries(requests)) {\n checkRequest(r, `requests.${name}`, entityNames, push);\n }\n for (const [name, e] of Object.entries(entities)) {\n checkEntity(e, `entities.${name}`, entityNames, push);\n }\n checkRequestNames(m, new Set(Object.keys(requests)), push);\n checkLimits(m, push);\n checkSelector(m.modified, \"modified\", push, false);\n if (m.directed !== undefined && typeof m.directed !== \"boolean\") {\n push(\"missing\", \"directed\");\n }\n return issues;\n}\n\n/**\n * Check the rate limit and the budget headers.\n * @param m - the mapping\n * @param push - the accumulator\n */\nfunction checkLimits(m: RestMapping, push: Push): void {\n for (const [at, value] of [\n [\"rateLimit.requests\", m.rateLimit?.requests],\n [\"rateLimit.perMs\", m.rateLimit?.perMs],\n ] as const) {\n if (m.rateLimit !== undefined && !(typeof value === \"number\" && value > 0)) {\n push(\"number\", at);\n }\n }\n if (\n m.budgetHeaders !== undefined &&\n (typeof m.budgetHeaders.remaining !== \"string\" ||\n (m.budgetHeaders.reset !== undefined && typeof m.budgetHeaders.reset !== \"string\"))\n ) {\n push(\"missing\", \"budgetHeaders\");\n }\n}\n","/**\n * Paging of the REST mapping (design section 13.2): a cursor in the body, an offset, the `Link`\n * header, or a next URL in the body. A position is a string or a number, so it fits a SourceCursor;\n * a position that is a URL is checked against the mapping's origin before it is followed.\n */\n\nimport { type ImportReportBuilder } from \"../../common/report.js\";\nimport { failOn } from \"../fail.js\";\nimport { type RestPaging } from \"./params.js\";\nimport { selectOne } from \"./selectors.js\";\nimport { checkOrigin } from \"./templates.js\";\n\n/** Where a paged request is: the first page (null), a cursor or offset, or a full URL. */\nexport type PagePosition = string | number | null;\n\n/**\n * The position of the first page.\n * @param paging - the request's paging\n * @returns the position\n */\nfunction firstPosition(paging: RestPaging | undefined): PagePosition {\n switch (paging?.style) {\n case \"cursor\":\n return paging.first;\n case \"offset\":\n return paging.base ?? 0;\n default:\n return null;\n }\n}\n\n/**\n * The URL of a page.\n * @param url - the request's first-page URL\n * @param paging - the request's paging\n * @param position - where to read\n * @param endpoint - the mapping's endpoint, which a full URL must stay on\n * @param report - the load's report\n * @returns the page's URL\n */\nexport function pageUrl(\n url: URL,\n paging: RestPaging | undefined,\n position: PagePosition,\n endpoint: URL,\n report: ImportReportBuilder,\n): URL {\n if (position === null) {\n return url;\n }\n const out = new URL(url);\n switch (paging?.style) {\n case \"cursor\":\n out.searchParams.set(paging.param, String(position));\n return out;\n case \"offset\":\n out.searchParams.set(paging.param, String(position));\n out.searchParams.set(paging.size.param, String(paging.size.value));\n return out;\n default:\n // link-header and next-url positions are full URLs from a response (or a recorded cursor)\n return checkOrigin(new URL(String(position), url), endpoint, report);\n }\n}\n\n/**\n * The first page's URL with its paging parameters, so an offset request carries its size.\n * @param url - the request's URL\n * @param paging - the request's paging\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the URL\n */\nexport function firstPageUrl(\n url: URL,\n paging: RestPaging | undefined,\n endpoint: URL,\n report: ImportReportBuilder,\n): URL {\n return pageUrl(url, paging, firstPosition(paging), endpoint, report);\n}\n\n/**\n * The `rel` URL of a Link header.\n * @param header - the header's value\n * @param rel - the relation\n * @returns the URL text, or null\n */\nfunction linkOf(header: string, rel: string): string | null {\n for (const part of header.split(/,(?=\\s*<)/)) {\n const m = /^\\s*<([^>]*)>(.*)$/.exec(part);\n if (m === null) {\n continue;\n }\n const rels = /;\\s*rel=\"?([^\";]+)\"?/i.exec(m[2]);\n if (rels?.[1].split(/\\s+/).includes(rel)) {\n return m[1];\n }\n }\n return null;\n}\n\n/** What `nextPosition` reads. */\ninterface PageResponse {\n /** The parsed body. */\n readonly body: unknown;\n /** The response headers. */\n readonly headers: Headers;\n /** The URL the page was read from. */\n readonly url: URL;\n /** How many records the page held. */\n readonly records: number;\n /** Where the load runs: a missing Link header in a browser may be one the service hides. */\n readonly runtime: string;\n}\n\n/**\n * The next page's URL from the Link header, or null after the last one.\n * @param rel - the relation that names the next page\n * @param page - this page's response\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the next position\n */\nfunction nextLink(rel: string, page: PageResponse, endpoint: URL, report: ImportReportBuilder): PagePosition {\n const header = page.headers.get(\"link\");\n if (header === null) {\n if (page.runtime === \"browser\") {\n // a browser reads Link only when the service exposes it: never a silent single page\n failOn(report, \"E_SOURCE_RESPONSE\", \"the Link header cannot be read\", {\n expected: \"link-header\",\n contentType: page.headers.get(\"content-type\"),\n });\n }\n return null;\n }\n const next = linkOf(header, rel);\n return next === null ? null : checkOrigin(new URL(next, page.url), endpoint, report).href;\n}\n\n/**\n * Where the next page is, or null after the last one.\n * @param paging - the request's paging\n * @param position - this page's position\n * @param page - this page's response\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the next position\n */\nexport function nextPosition(\n paging: RestPaging | undefined,\n position: PagePosition,\n page: PageResponse,\n endpoint: URL,\n report: ImportReportBuilder,\n): PagePosition {\n switch (paging?.style) {\n case \"cursor\": {\n const next = selectOne(page.body, paging.next);\n return (typeof next === \"string\" && next !== \"\") || typeof next === \"number\" ? next : null;\n }\n case \"offset\": {\n if (page.records < paging.size.value || page.records === 0) {\n return null;\n }\n const step = paging.unit === \"pages\" ? 1 : paging.size.value;\n return Number(position) + step;\n }\n case \"link-header\":\n return nextLink(paging.rel ?? \"next\", page, endpoint, report);\n case \"next-url\": {\n const next = selectOne(page.body, paging.next);\n return typeof next === \"string\" && next !== \"\"\n ? checkOrigin(new URL(next, page.url), endpoint, report).href\n : null;\n }\n default:\n return null;\n }\n}\n","/**\n * Turning a REST API's records into nodes and edges (design section 13.2): each record of an\n * entity is a node, each edge rule makes edges, a target with no record yet becomes a stub, and\n * embedded records are nodes of their own entity. A stub never overwrites a full record.\n */\n\nimport { SOURCE_ENTITY_ATTR, SOURCE_STUB_ATTR } from \"../ids.js\";\nimport { type EdgeRecord, type NodeRecord } from \"../types.js\";\nimport { type RestEdgeRule, type RestEntity, type RestMapping } from \"./params.js\";\nimport { select, selectOne } from \"./selectors.js\";\n\n/** What one load or expansion knows about the ids it wrote, across its pages. */\nexport interface RecordState {\n /** Ids written with a full record. */\n readonly full: Set<string>;\n /** Ids written as stubs. */\n readonly stubs: Set<string>;\n /** Ids the caller already holds (an expansion's seeds and `exclude`): never stubbed. */\n readonly known: ReadonlySet<string>;\n /** The newest modification time seen, for the validators. */\n modified: string | null;\n}\n\n/** The nodes and edges of one page. */\nexport interface PageRecords {\n readonly nodes: NodeRecord[];\n readonly edges: EdgeRecord[];\n}\n\n/**\n * A fresh state.\n * @param known - ids the caller holds already\n * @returns the state\n */\nexport function newState(known: Iterable<string> = []): RecordState {\n return { full: new Set(), stubs: new Set(), known: new Set(known), modified: null };\n}\n\n/**\n * An id as text, with the entity's prefix stripped.\n * @param value - what a selector reached\n * @param entity - the entity whose prefix applies\n * @returns the id, or null when the value is not one\n */\nfunction idText(value: unknown, entity: RestEntity | undefined): string | null {\n if (typeof value !== \"string\" && typeof value !== \"number\") {\n return null;\n }\n const text = String(value);\n const prefix = entity?.stripPrefix;\n return prefix !== undefined && prefix !== \"\" && text.startsWith(prefix) ? text.slice(prefix.length) : text;\n}\n\n/**\n * The value of a field selector: every value for a selector with `[]`, else the first.\n * @param record - the record\n * @param selector - the selector\n * @param index - the record's position, for `#`\n * @returns the value\n */\nfunction fieldValue(record: unknown, selector: string, index: number): unknown {\n if (selector === \"#\") {\n return index;\n }\n return selector.includes(\"[]\") ? select(record, selector) : selectOne(record, selector);\n}\n\n/** Converts the records of one page. */\nclass PageWriter {\n readonly out: PageRecords = { nodes: [], edges: [] };\n /** Edge rules to run once every node of the page is known, so a target on this page is no stub. */\n private readonly pending: { record: unknown; entity: string; id: string | null }[] = [];\n\n /**\n * Create one.\n * @param mapping - the mapping\n * @param state - the load's state\n */\n constructor(\n private readonly mapping: RestMapping,\n private readonly state: RecordState,\n ) {}\n\n /**\n * Add the records of an entity, and their embedded records.\n * @param records - the records\n * @param entityName - their entity\n */\n addRecords(records: readonly unknown[], entityName: string): void {\n const entity = this.mapping.entities[entityName];\n records.forEach((record, index) => {\n const id = entity.node === false ? null : idText(fieldValue(record, entity.id, index), entity);\n if (entity.node !== false) {\n if (id === null) {\n return;\n }\n this.addNode(record, index, id, entityName, entity);\n }\n const modified = this.mapping.modified === undefined ? undefined : selectOne(record, this.mapping.modified);\n if (typeof modified === \"string\" && (this.state.modified === null || modified > this.state.modified)) {\n this.state.modified = modified;\n }\n this.pending.push({ record, entity: entityName, id });\n for (const em of entity.embedded ?? []) {\n this.addRecords(select(record, em.at), em.entity);\n }\n });\n }\n\n /**\n * Write a full record.\n * @param record - the record\n * @param index - its position\n * @param id - its id\n * @param entityName - its entity\n * @param entity - the entity\n */\n private addNode(record: unknown, index: number, id: string, entityName: string, entity: RestEntity): void {\n const attrs: Record<string, unknown> = { labels: [entity.label ?? entityName] };\n if (entity.fields === undefined) {\n // without fields every top-level scalar is kept\n for (const [k, v] of Object.entries(record as Record<string, unknown>)) {\n if (\n k !== \"id\" &&\n k !== \"labels\" &&\n (typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\")\n ) {\n attrs[k] = v;\n }\n }\n } else {\n for (const [name, selector] of Object.entries(entity.fields)) {\n const v = fieldValue(record, selector, index);\n if (v !== undefined) {\n attrs[name] = v;\n }\n }\n }\n if (this.state.stubs.has(id)) {\n // the full record replaces a stub written earlier\n attrs[SOURCE_STUB_ATTR] = false;\n }\n this.state.full.add(id);\n this.out.nodes.push({ id, ...attrs });\n }\n\n /**\n * Make sure an edge end exists: a stub when no record of it was written and the caller does not\n * hold it.\n * @param id - the id\n * @param entity - its entity, when known\n */\n private end(id: string, entity: string | undefined): void {\n const { full, stubs, known } = this.state;\n if (full.has(id) || stubs.has(id) || known.has(id)) {\n return;\n }\n stubs.add(id);\n this.out.nodes.push({\n id,\n [SOURCE_STUB_ATTR]: true,\n ...(entity === undefined ? {} : { [SOURCE_ENTITY_ATTR]: entity }),\n });\n }\n\n /**\n * Run one edge rule over a record.\n * @param rule - the rule\n * @param record - the record\n * @param entityName - the record's entity\n * @param recordId - the record's id (null for a container)\n */\n private runRule(rule: RestEdgeRule, record: unknown, entityName: string, recordId: string | null): void {\n const scopes = rule.each === undefined ? [record] : select(record, rule.each);\n if (\"pairs\" in rule) {\n this.runPairsRule(rule, scopes, entityName);\n } else {\n this.runLinkRule(rule, scopes, entityName, recordId);\n }\n }\n\n /**\n * Run a pairs rule: an edge between every two distinct ids in each scope.\n * @param rule - the rule\n * @param scopes - the scopes it runs over\n * @param entityName - the record's entity\n */\n private runPairsRule(\n rule: Extract<RestEdgeRule, { pairs: string }>,\n scopes: readonly unknown[],\n entityName: string,\n ): void {\n const entityOf = rule.entity ?? entityName;\n const entity = this.mapping.entities[entityOf];\n for (const scope of scopes) {\n const ids = [...new Set(select(scope, rule.pairs).map((v) => idText(v, entity)))].filter(\n (v): v is string => v !== null,\n );\n for (let i = 0; i < ids.length; i++) {\n for (let j = i + 1; j < ids.length; j++) {\n this.end(ids[i], entityOf);\n this.end(ids[j], entityOf);\n this.out.edges.push({ source: ids[i], target: ids[j], type: rule.type });\n }\n }\n }\n }\n\n /**\n * Run a from/to rule: an edge from the record (or a selected id) to each selected id.\n * @param rule - the rule\n * @param scopes - the scopes it runs over\n * @param entityName - the record's entity\n * @param recordId - the record's id (null for a container)\n */\n private runLinkRule(\n rule: Exclude<RestEdgeRule, { pairs: string }>,\n scopes: readonly unknown[],\n entityName: string,\n recordId: string | null,\n ): void {\n const own = this.mapping.entities[entityName];\n const targetEntity = rule.entity === undefined ? own : this.mapping.entities[rule.entity];\n for (const scope of scopes) {\n const from = rule.from === undefined ? recordId : idText(selectOne(scope, rule.from), own);\n if (from === null) {\n continue;\n }\n const tos = select(scope, rule.to)\n .map((t) => idText(t, targetEntity))\n .filter((v): v is string => v !== null);\n for (const to of tos) {\n this.end(from, rule.from === undefined ? entityName : undefined);\n this.end(to, rule.entity);\n this.out.edges.push({ ...edgeFields(rule.fields, scope), source: from, target: to, type: rule.type });\n }\n }\n }\n\n /**\n * Run the edge rules of every record added.\n * @returns the page\n */\n finish(): PageRecords {\n for (const { record, entity, id } of this.pending) {\n for (const rule of this.mapping.entities[entity].edges ?? []) {\n this.runRule(rule, record, entity, id);\n }\n }\n this.pending.length = 0;\n return this.out;\n }\n}\n\n/**\n * An edge's fields, read from its scope.\n * @param fields - the rule's field selectors\n * @param scope - the scope the edge came from\n * @returns the fields that have a value\n */\nfunction edgeFields(fields: Readonly<Record<string, string>> | undefined, scope: unknown): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, selector] of Object.entries(fields ?? {})) {\n const v = fieldValue(scope, selector, 0);\n if (v !== undefined) {\n out[name] = v;\n }\n }\n return out;\n}\n\n/**\n * The nodes and edges of one page of records.\n * @param mapping - the mapping\n * @param groups - the page's records, by entity (a seed's records first)\n * @param state - the load's state, updated\n * @returns the nodes and edges\n */\nexport function toRecords(\n mapping: RestMapping,\n groups: readonly { readonly records: readonly unknown[]; readonly entity: string }[],\n state: RecordState,\n): PageRecords {\n const writer = new PageWriter(mapping, state);\n for (const g of groups) {\n writer.addRecords(g.records, g.entity);\n }\n return writer.finish();\n}\n","/**\n * Running a REST mapping (design section 13.2): `restSource(mapping, info)` turns one into a\n * `records` source with `expand` (breadth-first, batched `{ids}`, depth 0 hydrates), `probe` and\n * `validate`; the generic `rest` source takes the mapping as a parameter. Every request goes through\n * `ctx.fetch`, so the credential, retries, caps and coded errors are the framework's.\n */\n\nimport { type GraphSink } from \"@graphty/graph-format\";\n\nimport { throwIfAborted } from \"../../common/input.js\";\nimport { ImportError, type ImportReport } from \"../../types.js\";\nimport { sleep } from \"../context.js\";\nimport { originOf } from \"../credentials.js\";\nimport { defineSource } from \"../define.js\";\nimport { failAlone, failOn, warnOn } from \"../fail.js\";\nimport { REST_SOURCE_ID } from \"../ids.js\";\nimport {\n type ExpandRequest,\n type GraphSource,\n type RecordBatch,\n type SourceContext,\n type SourceCursor,\n type SourceDescriptor,\n type SourceFinish,\n type SourceFreshness,\n type SourceProbe,\n type SourceValidators,\n} from \"../types.js\";\nimport { REST_DESCRIPTOR } from \"./descriptor.js\";\nimport { checkRestMapping } from \"./mapping.js\";\nimport { firstPageUrl, nextPosition, type PagePosition, pageUrl } from \"./paging.js\";\nimport { type RestMapping, type RestParams, type RestRequest } from \"./params.js\";\nimport { newState, type PageRecords, type RecordState, toRecords } from \"./records.js\";\nimport { selectRecords } from \"./selectors.js\";\nimport { buildRequest, type TemplateValues } from \"./templates.js\";\n\n/** What a call runs: the mapping and the values its templates use. */\nexport interface RestPlan {\n /** The mapping. */\n readonly mapping: RestMapping;\n /** The template values. */\n readonly values: TemplateValues;\n}\n\n/** Why a plan is asked for: the values may differ (a validation selects only what it compares). */\nexport type RestPurpose = \"load\" | \"expand\" | \"probe\" | \"validate\";\n\n/** Turns a call's params into the plan it runs. */\ntype RestPlanner<P> = (params: P, ctx: SourceContext, purpose: RestPurpose) => RestPlan;\n\n/** Auth failures a later page may answer with, keeping the pages before it. */\nconst AUTH_CODES: ReadonlySet<string> = new Set([\"E_SOURCE_AUTH\", \"E_SOURCE_FORBIDDEN\"]);\n\n/** One page read. */\ninterface Page {\n readonly records: unknown[];\n readonly next: PagePosition;\n readonly headers: Headers;\n readonly status: number;\n}\n\n/**\n * How long until a budget resets.\n * @param reset - the reset header's number: past 1e9 an epoch in seconds, otherwise seconds from now\n * @returns milliseconds from now, never negative\n */\nfunction resetDelayMs(reset: number): number {\n return Math.max(0, reset > 1e9 ? reset * 1000 - Date.now() : reset * 1000);\n}\n\n/** One call's running state. */\nclass RestRun {\n readonly endpoint: URL;\n readonly facts: { budget?: SourceFinish[\"budget\"]; validators?: SourceValidators } = {};\n private last = 0;\n\n /**\n * Create one.\n * @param plan - the mapping and values\n * @param ctx - the context\n * @param paced - whether this run paces itself (the generic source, whose descriptor cannot)\n */\n constructor(\n readonly plan: RestPlan,\n readonly ctx: SourceContext,\n private readonly paced: boolean,\n ) {\n this.endpoint = new URL(plan.mapping.endpoint);\n if (ctx.endpoint !== null && originOf(ctx.endpoint) !== this.endpoint.origin) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"the endpoint is not the mapping's\", {\n name: \"endpoint\",\n reason: \"origin\",\n });\n }\n }\n\n /** Wait out the mapping's own rate limit (the generic source only). */\n private async pace(): Promise<void> {\n const rate = this.plan.mapping.rateLimit;\n if (!this.paced || rate === undefined) {\n return;\n }\n // ponytail: even spacing, one request at a time; a burst window is the descriptor's pacer\n const wait = this.last + rate.perMs / rate.requests - Date.now();\n if (wait > 0) {\n await sleep(wait, this.ctx.signal);\n }\n this.last = Date.now();\n }\n\n /**\n * Record the budget headers of a response.\n * @param headers - the response headers\n */\n private noteBudget(headers: Headers): void {\n const names = this.plan.mapping.budgetHeaders;\n const remaining = names === undefined ? null : headers.get(names.remaining);\n if (names === undefined || remaining === null || !Number.isFinite(Number(remaining))) {\n return;\n }\n const reset = names.reset === undefined ? null : Number(headers.get(names.reset) ?? Number.NaN);\n const resetMs = reset === null || !Number.isFinite(reset) ? undefined : resetDelayMs(reset);\n this.facts.budget = { remaining: Number(remaining), ...(resetMs === undefined ? {} : { resetMs }) };\n }\n\n /**\n * Read one page of a request.\n * @param name - the request name\n * @param values - the template values\n * @param position - the page's position, or undefined for the first page\n * @param headers - extra request headers (validation)\n * @returns the page\n */\n async read(\n name: string,\n values: TemplateValues,\n position: PagePosition | undefined,\n headers?: Record<string, string>,\n ): Promise<Page> {\n const request: RestRequest = this.plan.mapping.requests[name];\n const { report } = this.ctx;\n const built = buildRequest(this.endpoint, request, values, report);\n const url =\n position === undefined\n ? firstPageUrl(built.url, request.paging, this.endpoint, report)\n : pageUrl(built.url, request.paging, position, this.endpoint, report);\n await this.pace();\n const response = await this.ctx.fetch(url, {\n ...built.init,\n headers: { accept: \"application/json\", ...(built.init.headers as Record<string, string>), ...headers },\n allowStatus: [304],\n });\n this.noteBudget(response.headers);\n if (response.status === 304) {\n return { records: [], next: null, headers: response.headers, status: 304 };\n }\n const text = await response.text();\n let body: unknown;\n try {\n body = JSON.parse(text) as unknown;\n } catch {\n failOn(report, \"E_SOURCE_RESPONSE\", \"the response is not JSON\", {\n expected: \"json\",\n contentType: response.headers.get(\"content-type\"),\n });\n }\n const records = selectRecords(body, request.records);\n const here = position ?? null;\n const next = nextPosition(\n request.paging,\n position ?? (request.paging?.style === \"offset\" ? (request.paging.base ?? 0) : here),\n { body, headers: response.headers, url, records: records.length, runtime: this.ctx.runtime },\n this.endpoint,\n report,\n );\n return { records, next, headers: response.headers, status: response.status };\n }\n\n /**\n * Record what the facts say so far, so the report carries them even when a later page fails.\n * @param state - the load's record state\n * @param next - where to resume, for an expansion\n * @returns the report so far\n */\n finish(state: RecordState | null, next: SourceCursor | null = null): ImportReport {\n if (state?.modified !== null && state?.modified !== undefined) {\n this.facts.validators = { ...this.facts.validators, modified: state.modified };\n }\n return this.ctx.finish({ ...this.facts, next });\n }\n\n /**\n * Note the HTTP validators of a load's first response.\n * @param headers - its headers\n */\n noteValidators(headers: Headers): void {\n const etag = headers.get(\"etag\");\n const lastModified = headers.get(\"last-modified\");\n this.facts.validators = {\n ...this.facts.validators,\n ...(etag === null ? {} : { etag }),\n ...(lastModified === null ? {} : { lastModified }),\n };\n }\n\n /**\n * The graph facts of a first page.\n * @returns the meta\n */\n meta(): RecordBatch[\"meta\"] {\n const { directed } = this.plan.mapping;\n return directed === undefined ? undefined : { directed };\n }\n}\n\n/**\n * The template values of params: every string, number and boolean, as text.\n * @param params - the params\n * @param skip - a key to leave out\n * @returns the values\n */\nfunction stringValues(params: Readonly<Record<string, unknown>>, skip?: string): TemplateValues {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(params)) {\n if (k !== skip && (typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\")) {\n out[k] = String(v);\n }\n }\n return out;\n}\n\n/**\n * The load: the seed request once, then the load request page by page.\n * @param run - the call\n * @yields one page of nodes and edges\n */\nasync function* loadPages(run: RestRun): AsyncGenerator<RecordBatch> {\n const { mapping, values } = run.plan;\n const { cursor } = run.ctx;\n if (cursor !== null && cursor.r !== mapping.load) {\n failOn(run.ctx.report, \"E_SOURCE_PARAM\", \"the cursor is not this mapping's\", {\n name: \"cursor\",\n reason: \"stale-cursor\",\n });\n }\n const state = newState();\n const groups: { records: unknown[]; entity: string }[] = [];\n if (cursor === null && mapping.seed !== undefined) {\n const seed = await run.read(mapping.seed, values, undefined);\n groups.push({ records: seed.records, entity: mapping.requests[mapping.seed].entity });\n }\n const { entity } = mapping.requests[mapping.load];\n let position: PagePosition | undefined = cursor === null ? undefined : (cursor.at as PagePosition);\n let first = true;\n for (;;) {\n const page = await run.read(mapping.load, values, position);\n if (first && cursor === null) {\n run.noteValidators(page.headers);\n }\n const out = toRecords(mapping, [...groups.splice(0), { records: page.records, entity }], state);\n run.finish(state);\n const next = page.next === null ? null : { r: mapping.load, at: page.next };\n yield { nodes: out.nodes, edges: out.edges, next, meta: first ? run.meta() : undefined };\n if (page.next === null) {\n return;\n }\n first = false;\n position = page.next;\n }\n}\n\n/**\n * Write one page into a sink.\n * @param out - the page\n * @param sink - the sink\n * @param ctx - the context\n * @param types - the relationship types to keep, if any\n */\nfunction writePage(out: PageRecords, sink: GraphSink, ctx: SourceContext, types?: ReadonlySet<string>): void {\n const { report } = ctx;\n let n = 0;\n for (const { id, ...attrs } of out.nodes) {\n if (n++ % 64 === 0) {\n throwIfAborted(ctx.signal);\n }\n try {\n sink.addNodeRecord(id, attrs);\n report.counts.nodes++;\n } catch (err) {\n report.recordError(err, { element: String(id) });\n report.counts.skippedNodes++;\n }\n }\n for (const { source, target, ...attrs } of out.edges) {\n if (n++ % 64 === 0) {\n throwIfAborted(ctx.signal);\n }\n if (types !== undefined && !types.has(String(attrs.type))) {\n continue;\n }\n try {\n sink.addEdgeRecord(source, target, attrs);\n report.counts.edges++;\n } catch (err) {\n report.recordError(err, { element: `${String(source)} -> ${String(target)}` });\n report.counts.skippedEdges++;\n }\n }\n}\n\n/**\n * The requests an expansion runs for a direction; depth 0 hydrates.\n * @param mapping - the mapping\n * @param request - the expansion\n * @returns the request names\n */\nfunction expandRequests(mapping: RestMapping, request: ExpandRequest<unknown>): string[] {\n if (request.depth === 0) {\n return mapping.hydrate === undefined ? [] : [mapping.hydrate];\n }\n const { expand } = mapping;\n if (typeof expand === \"string\" || expand === undefined) {\n return expand === undefined ? [] : [expand];\n }\n const direction = request.direction ?? \"both\";\n const names = [direction !== \"out\" ? expand.in : undefined, direction !== \"in\" ? expand.out : undefined];\n return [...new Set(names.filter((n): n is string => n !== undefined))];\n}\n\n/**\n * Split ids into a request's batches.\n * @param ids - the ids\n * @param max - the batch size\n * @returns the batches\n */\nfunction batches(ids: readonly string[], max: number): string[][] {\n const out: string[][] = [];\n for (let i = 0; i < ids.length; i += max) {\n out.push(ids.slice(i, i + max));\n }\n return out;\n}\n\n/**\n * Breadth-first expansion: each hop runs the direction's requests with the frontier's ids in\n * `{ids}` batches; the nodes it adds are the next frontier. A capped first hop records where it\n * stopped, so expanding again continues from there.\n * @param run - the call\n * @param request - the seeds and how far to go\n * @param sink - where to write\n * @returns the report\n */\nasync function expandInto(run: RestRun, request: ExpandRequest<unknown>, sink: GraphSink): Promise<ImportReport> {\n return new Expansion(run, request, sink).expand();\n}\n\n/** Which batch of which request of which hop is being read. */\ninterface BatchAt {\n readonly hop: number;\n readonly x: number;\n readonly b: number;\n}\n\n/** One expansion's running state. */\nclass Expansion {\n private readonly mapping: RestMapping;\n private readonly names: string[];\n private readonly state: RecordState;\n private readonly types: ReadonlySet<string> | undefined;\n private added = 0;\n private wrote = false;\n\n /**\n * Check the expansion and set the sink's direction.\n * @param run - the call\n * @param request - the seeds and how far to go\n * @param sink - where to write\n */\n constructor(\n private readonly run: RestRun,\n private readonly request: ExpandRequest<unknown>,\n private readonly sink: GraphSink,\n ) {\n const { ctx } = run;\n this.mapping = run.plan.mapping;\n this.names = expandRequests(this.mapping, request);\n if (this.names.length === 0) {\n failOn(ctx.report, \"E_SOURCE_UNSUPPORTED\", \"the mapping has no request for this expansion\", {\n feature: request.depth === 0 ? \"hydrate\" : \"expand\",\n });\n }\n if (request.ids.length === 0) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"an expansion needs seed ids\", { name: \"ids\", reason: \"required\" });\n }\n this.state = newState([...request.ids.map(String), ...(request.exclude ?? []).map(String)]);\n this.types = request.relationshipTypes === undefined ? undefined : new Set(request.relationshipTypes);\n if (this.mapping.directed !== undefined && sink.edgeCount === 0) {\n sink.setDirected(this.mapping.directed);\n }\n }\n\n /**\n * Run every hop.\n * @returns the report\n */\n async expand(): Promise<ImportReport> {\n let frontier = this.request.ids.map(String);\n const depth = Math.max(1, this.request.depth ?? 1);\n for (let hop = 1; hop <= depth && frontier.length > 0; hop++) {\n const reached: string[] = [];\n const stop = await this.hop(hop, frontier, reached);\n if (stop !== null) {\n return stop;\n }\n frontier = [...new Set(reached)];\n }\n return this.run.finish(this.state, null);\n }\n\n /**\n * Run one hop: every request over every batch of the frontier.\n * @param hop - the hop, from 1\n * @param frontier - the ids this hop starts from\n * @param reached - collects the ids this hop adds\n * @returns the report when the expansion stopped, else null\n */\n private async hop(hop: number, frontier: readonly string[], reached: string[]): Promise<ImportReport | null> {\n for (const [x, name] of this.names.entries()) {\n const max = this.mapping.requests[name].batch?.max ?? 1;\n for (const [b, batch] of batches(frontier, max).entries()) {\n if (this.skipped({ hop, x, b })) {\n continue;\n }\n const stop = await this.readBatch({ hop, x, b }, name, batch, frontier, reached);\n if (stop !== null) {\n return stop;\n }\n }\n }\n return null;\n }\n\n /**\n * Whether a resumed first hop already read this batch.\n * @param at - the batch\n * @returns true to skip it\n */\n private skipped(at: BatchAt): boolean {\n const { hop, x, b } = at;\n const resume = this.run.ctx.cursor;\n if (hop !== 1 || resume === null) {\n return false;\n }\n const rx = Number(resume.x);\n return x < rx || (x === rx && b < Number(resume.b));\n }\n\n /**\n * Where a batch starts: the recorded position for the batch a first hop stopped in.\n * @param at - the batch\n * @returns the position, or undefined for the first page\n */\n private startPosition(at: BatchAt): PagePosition | undefined {\n const { hop, x, b } = at;\n const resume = this.run.ctx.cursor;\n return hop === 1 && resume !== null && x === Number(resume.x) && b === Number(resume.b)\n ? ((resume.at as PagePosition) ?? undefined)\n : undefined;\n }\n\n /**\n * Read one batch page by page.\n * @param at - the batch\n * @param name - the request\n * @param batch - its ids\n * @param frontier - the hop's ids\n * @param reached - collects the ids it adds\n * @returns the report when the expansion stopped, else null\n */\n private async readBatch(\n at: BatchAt,\n name: string,\n batch: readonly string[],\n frontier: readonly string[],\n reached: string[],\n ): Promise<ImportReport | null> {\n const r = this.mapping.requests[name];\n const own = { ...this.run.plan.values, id: batch[0], ids: batch.join(r.batch?.join ?? \",\") };\n let position = this.startPosition(at);\n for (;;) {\n let page: Page;\n try {\n page = await this.run.read(name, own, position);\n } catch (err) {\n return this.authStop(err, at.hop === 1 ? { x: at.x, b: at.b, at: position ?? null } : null);\n }\n this.writeNew(page, r.entity, reached);\n const stop = this.capStop(at, page, frontier);\n if (stop !== null || page.next === null) {\n return stop;\n }\n position = page.next;\n }\n }\n\n /**\n * Keep what was written when a later page needs a credential; rethrow anything else.\n * @param err - what the page threw\n * @param cursor - where to resume\n * @returns the report\n */\n private authStop(err: unknown, cursor: SourceCursor | null): ImportReport {\n if (!this.wrote || !(err instanceof ImportError) || !AUTH_CODES.has(String(err.issue?.code))) {\n throw err;\n }\n const p = err.issue?.params ?? {};\n warnOn(this.run.ctx.report, \"W_SOURCE_AUTH\", \"a later page needs a credential; the pages before it are kept\", {\n origin: typeof p.origin === \"string\" ? p.origin : this.run.endpoint.origin,\n status: typeof p.status === \"number\" ? p.status : null,\n });\n return this.run.finish(this.state, cursor);\n }\n\n /**\n * Write a page and collect the nodes it added.\n * @param page - the page\n * @param entity - its records' entity\n * @param reached - collects the ids it adds\n */\n private writeNew(page: Page, entity: string, reached: string[]): void {\n const { state } = this;\n const before = new Set([...state.full, ...state.stubs]);\n const out = toRecords(this.mapping, [{ records: page.records, entity }], state);\n writePage(out, this.sink, this.run.ctx, this.types);\n this.wrote = true;\n for (const node of out.nodes) {\n const id = String(node.id);\n if (!before.has(id) && !state.known.has(id)) {\n reached.push(id);\n this.added++;\n }\n }\n }\n\n /**\n * Stop at the expansion's limit or the load's caps.\n * @param at - the batch\n * @param page - the page just written\n * @param frontier - the hop's ids\n * @returns the report when a cap was reached, else null\n */\n private capStop(at: BatchAt, page: Page, frontier: readonly string[]): ImportReport | null {\n const { hop, x, b } = at;\n const { ctx } = this.run;\n const limited = this.request.limit !== undefined && this.added >= this.request.limit;\n if (limited) {\n warnOn(ctx.report, \"W_SOURCE_LIMIT\", \"the expansion reached its limit\", {\n limit: \"limit\",\n value: this.added,\n });\n }\n if (!limited && !ctx.limits.reached()) {\n return null;\n }\n const more = page.next === null ? null : { x, b, at: page.next };\n // ponytail: only a capped first hop can resume; a deeper hop's frontier is not recorded\n return this.run.finish(\n this.state,\n hop === 1 ? (more ?? nextBatch(x, b, this.names, frontier, this.mapping)) : null,\n );\n }\n}\n\n/**\n * Where a first hop continues after a batch that ended on a cap.\n * @param x - the request index\n * @param b - the batch index\n * @param names - the requests\n * @param frontier - the seeds\n * @param mapping - the mapping\n * @returns the cursor, or null when nothing is left\n */\nfunction nextBatch(\n x: number,\n b: number,\n names: readonly string[],\n frontier: readonly string[],\n mapping: RestMapping,\n): SourceCursor | null {\n const count = Math.ceil(frontier.length / (mapping.requests[names[x]].batch?.max ?? 1));\n if (b + 1 < count) {\n return { x, b: b + 1, at: null };\n }\n return x + 1 < names.length ? { x: x + 1, b: 0, at: null } : null;\n}\n\n/**\n * Whether data loaded earlier changed: the load's first page (with the seed), sent with the\n * recorded HTTP validators; a 304 or an equal ETag is current, else the newest modification time\n * is compared.\n * @param run - the call\n * @param seen - the validators recorded then\n * @returns the freshness\n */\nasync function validateRun(run: RestRun, seen: SourceValidators): Promise<SourceFreshness> {\n const { mapping, values } = run.plan;\n const headers: Record<string, string> = {};\n if (seen.etag !== undefined) {\n headers[\"if-none-match\"] = seen.etag;\n }\n if (seen.lastModified !== undefined) {\n headers[\"if-modified-since\"] = seen.lastModified;\n }\n const state = newState();\n const groups: { records: unknown[]; entity: string }[] = [];\n if (mapping.seed !== undefined) {\n const seed = await run.read(mapping.seed, values, undefined);\n groups.push({ records: seed.records, entity: mapping.requests[mapping.seed].entity });\n }\n const page = await run.read(mapping.load, values, undefined, headers);\n if (page.status === 304) {\n return { status: \"current\", via: seen.etag === undefined ? \"modified\" : \"etag\", validators: seen };\n }\n toRecords(mapping, [...groups, { records: page.records, entity: mapping.requests[mapping.load].entity }], state);\n run.noteValidators(page.headers);\n const now: SourceValidators = {\n ...run.facts.validators,\n ...(state.modified === null ? {} : { modified: state.modified }),\n };\n if (seen.etag !== undefined && now.etag !== undefined) {\n return { status: seen.etag === now.etag ? \"current\" : \"changed\", via: \"etag\", validators: now };\n }\n if (seen.modified !== undefined && now.modified !== undefined) {\n return now.modified > seen.modified\n ? { status: \"changed\", via: \"modified\", changedAt: now.modified, validators: now }\n : { status: \"current\", via: \"modified\", validators: now };\n }\n return { status: \"unverifiable\", validators: now };\n}\n\n/**\n * The methods of a source that runs plans.\n * @param plan - turns params into the plan\n * @param paced - whether the run paces itself\n * @returns records, expand, probe and validate\n */\nexport function restMethods<P>(\n plan: RestPlanner<P>,\n paced: boolean,\n): Pick<Required<GraphSource<P>>, \"expand\" | \"probe\" | \"validate\"> & {\n records: (params: P, ctx: SourceContext) => AsyncIterable<RecordBatch>;\n} {\n return {\n records: (params, ctx) => loadPages(new RestRun(plan(params, ctx, \"load\"), ctx, paced)),\n expand: (request, sink, ctx) =>\n expandInto(new RestRun(plan(request.params, ctx, \"expand\"), ctx, paced), request, sink),\n async probe(params, ctx): Promise<SourceProbe> {\n const run = new RestRun(plan(params, ctx, \"probe\"), ctx, paced);\n const page = await run.read(run.plan.mapping.load, run.plan.values, undefined);\n if (page.records.length === 0 && page.status !== 304) {\n failOn(ctx.report, \"E_SOURCE_NOT_FOUND\", \"the load request found no records\", {\n what: \"records\",\n value: run.plan.mapping.load,\n });\n }\n return { ok: true };\n },\n validate: (params, seen, ctx) => validateRun(new RestRun(plan(params, ctx, \"validate\"), ctx, paced), seen),\n };\n}\n\n/**\n * The plan of a mapping given as data, after it is checked.\n * @param mapping - the mapping\n * @param ctx - the context\n * @returns the mapping, checked\n */\nfunction checkedMapping(mapping: unknown, ctx: SourceContext): RestMapping {\n const [issue] = checkRestMapping(mapping);\n if (issue !== undefined) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", `the mapping is invalid at ${issue.at}`, {\n name: \"mapping\",\n reason: issue.code,\n at: issue.at,\n });\n }\n return mapping as RestMapping;\n}\n\n/**\n * What `restSource` needs beside the mapping: the source id and any descriptor fields to set.\n * Experimental.\n * @category Network sources\n */\nexport type RestSourceInfo = {\n /** The source id: lowercase letters, digits and dashes. */\n readonly id: string;\n} & Partial<SourceDescriptor>;\n\n/**\n * Turn a REST mapping into a source: a `records` source that loads the mapping's `load` request\n * page by page, with `expand` (breadth-first over the `expand` requests, `{ids}` batched; depth 0\n * fetches the seeds' own records through `hydrate`), `probe` and `validate`. The descriptor is\n * derived from the mapping (its endpoint, params, auth and rate limit), and `info` may set any of\n * its fields. A mapping with a problem is refused: E_SOURCE_INVALID with `reason: \"mapping\"`.\n * Experimental.\n * @param mapping - the mapping\n * @param info - the id and descriptor fields\n * @returns the source\n * @example\n * ```ts\n * const people = restSource(mapping, { id: \"people\", plainName: \"People\" });\n * registerSource(people);\n * const { snapshot } = await loadFromSource(\"people\", { team: \"core\" });\n * ```\n * @category Network sources\n */\nexport function restSource(mapping: RestMapping, info: RestSourceInfo): GraphSource<Readonly<Record<string, unknown>>> {\n const [issue] = checkRestMapping(mapping);\n if (issue !== undefined) {\n failAlone(\"E_SOURCE_INVALID\", `the mapping of ${info.id} is invalid at ${issue.at}`, {\n id: info.id,\n reason: \"mapping\",\n at: issue.at,\n });\n }\n const { id, ...fields } = info;\n const auth = mapping.auth === undefined ? [] : [mapping.auth.kind];\n const descriptor: SourceDescriptor = Object.freeze({\n plainName: id,\n kind: \"rest\",\n params: mapping.params ?? [],\n defaultEndpoint: mapping.endpoint,\n auth,\n authRequired: auth.length === 0 ? \"none\" : \"optional\",\n ...(mapping.rateLimit === undefined ? {} : { rateLimit: mapping.rateLimit }),\n ...fields,\n });\n return defineSource<Readonly<Record<string, unknown>>>({\n id,\n descriptor,\n ...restMethods((params) => ({ mapping, values: stringValues(params) }), false),\n });\n}\n\n/**\n * The generic REST mapping source: `params.mapping` says how to read the API, and the other params\n * fill its templates. The mapping is checked before any request (E_SOURCE_PARAM, `name:\n * \"mapping\"`, `reason` the problem's code, `at` where it is). With a credential, pass the mapping's\n * endpoint as `endpoint`, so the credential is bound to it. Experimental.\n * @category Network sources\n */\nexport const restMappingSource: GraphSource<RestParams> = defineSource<RestParams>({\n id: REST_SOURCE_ID,\n descriptor: REST_DESCRIPTOR,\n ...restMethods<RestParams>(\n (params, ctx) => ({ mapping: checkedMapping(params.mapping, ctx), values: stringValues(params, \"mapping\") }),\n true,\n ),\n});\n","/**\n * The `openalex` preset of the REST mapping (design section 13.3): OpenAlex's citation graph\n * around a work, or its co-authorship graph around an author, as a mapping the generic engine runs.\n * The seed's own record comes first; citing works page by cursor; referenced works are stubs until\n * hydrated or expanded. Freshness is the newest `updated_date`.\n */\n\nimport { defineSource } from \"../define.js\";\nimport { failOn } from \"../fail.js\";\nimport { OPENALEX_SOURCE_ID } from \"../ids.js\";\nimport { type GraphSource, type SourceContext } from \"../types.js\";\nimport { OPENALEX_DESCRIPTOR } from \"./descriptor.js\";\nimport { type OpenAlexParams, type RestEntity, type RestMapping } from \"./params.js\";\nimport { restMethods, type RestPlan, type RestPurpose } from \"./source.js\";\n\n/** OpenAlex ids are URLs under this prefix. */\nconst PREFIX = \"https://openalex.org/\";\n\n/** The work fields every citation load selects. */\nconst WORK_FIELDS = \"id,display_name,publication_year,cited_by_count,updated_date,referenced_works\";\n\n/**\n * A list request over works, `{ids}` batched 50 at a time and joined by `|`.\n * @param filter - the filter template\n * @param perPage - the page size\n * @param paged - whether it pages by cursor\n * @returns the request\n */\nfunction works(filter: string, perPage: string, paged: boolean): RestMapping[\"requests\"][string] {\n return {\n path: \"/works\",\n query: { filter, \"per-page\": perPage, select: \"{select}\" },\n batch: { max: 50, join: \"|\" },\n records: \"results\",\n entity: \"work\",\n ...(paged ? { paging: { style: \"cursor\", param: \"cursor\", first: \"*\", next: \"meta.next_cursor\" } } : {}),\n };\n}\n\n/** An entity known by its OpenAlex id and display name. */\nconst named: RestEntity = { id: \"id\", stripPrefix: PREFIX, fields: { name: \"display_name\" } };\n\n/**\n * OpenAlex's citation graph as a mapping: the seed work (`{ids}`), the works citing it page by page,\n * each work's references as `cites` edges, and, when `{select}` asks for `authorships` and\n * `topics`, the authors, their institutions and the topics as nodes. Fill `{ids}` with work ids\n * and `{select}` with the fields to read. The `openalex` source chooses both from its params and\n * leaves out the rules for what is not included. Experimental.\n * @category Network sources\n */\nexport const OPENALEX_MAPPING: RestMapping = Object.freeze<RestMapping>({\n version: 1,\n endpoint: \"https://api.openalex.org\",\n load: \"citing\",\n seed: \"by-id\",\n expand: { in: \"citing\", out: \"by-id\" },\n hydrate: \"by-id\",\n directed: true,\n modified: \"updated_date\",\n auth: { kind: \"api-key\", query: \"api_key\" },\n rateLimit: { requests: 10, perMs: 1000 },\n budgetHeaders: { remaining: \"x-ratelimit-remaining\", reset: \"x-ratelimit-reset\" },\n requests: {\n citing: works(\"cites:{ids}\", \"200\", true),\n \"by-id\": works(\"openalex:{ids}\", \"50\", false),\n authored: works(\"authorships.author.id:{ids}\", \"200\", true),\n \"authors-by-id\": {\n path: \"/authors\",\n query: { filter: \"openalex:{ids}\", \"per-page\": \"50\", select: \"id,display_name\" },\n batch: { max: 50, join: \"|\" },\n records: \"results\",\n entity: \"author\",\n },\n },\n entities: {\n work: {\n id: \"id\",\n stripPrefix: PREFIX,\n fields: {\n title: \"display_name\",\n year: \"publication_year\",\n citedBy: \"cited_by_count\",\n updated: \"updated_date\",\n },\n edges: [\n { to: \"referenced_works[]\", type: \"cites\", entity: \"work\" },\n { to: \"authorships[].author.id\", type: \"authored_by\", entity: \"author\" },\n {\n each: \"authorships[]\",\n from: \"author.id\",\n to: \"institutions[].id\",\n type: \"affiliated_with\",\n entity: \"institution\",\n },\n { to: \"topics[].id\", type: \"has_topic\", entity: \"topic\" },\n ],\n embedded: [\n { at: \"authorships[].author\", entity: \"author\" },\n { at: \"authorships[].institutions[]\", entity: \"institution\" },\n { at: \"topics[]\", entity: \"topic\" },\n ],\n },\n author: named,\n institution: named,\n topic: named,\n },\n});\n\n/** What `include` may hold. */\ntype Include = \"authors\" | \"institutions\" | \"topics\";\n\n/**\n * The included kinds, from an array or a comma-separated string.\n * @param include - the param\n * @returns the set\n */\nfunction includes(include: unknown): Set<Include> {\n const list: unknown[] = typeof include === \"string\" ? include.split(\",\") : [];\n if (Array.isArray(include)) {\n list.push(...(include as unknown[]));\n }\n const out = new Set(list.map((v) => String(v).trim()).filter((v) => v !== \"\") as Include[]);\n if (out.has(\"institutions\")) {\n // an institution hangs off an author, so it brings its authors\n out.add(\"authors\");\n }\n return out;\n}\n\n/**\n * The citation mapping without the rules for what is not included.\n * @param include - what is included\n * @returns the mapping\n */\nfunction citationMapping(include: ReadonlySet<Include>): RestMapping {\n const { work } = OPENALEX_MAPPING.entities;\n const keepEdge = (type: string): boolean =>\n type === \"cites\" ||\n (type === \"authored_by\" && include.has(\"authors\")) ||\n (type === \"affiliated_with\" && include.has(\"institutions\")) ||\n (type === \"has_topic\" && include.has(\"topics\"));\n const keepEmbedded = (entity: string): boolean => include.has(`${entity}s` as Include);\n return {\n ...OPENALEX_MAPPING,\n entities: {\n ...OPENALEX_MAPPING.entities,\n work: {\n ...work,\n edges: work.edges?.filter((e) => keepEdge(e.type)),\n embedded: work.embedded?.filter((e) => keepEmbedded(e.entity)),\n },\n },\n };\n}\n\n/**\n * The co-authorship mapping: works are containers, every two authors of one work are joined by a\n * `coauthor` edge, and an author expands through the works they wrote.\n * @param include - what is included\n * @param seedIsWork - whether the load starts from a work\n * @returns the mapping\n */\nfunction coauthorshipMapping(include: ReadonlySet<Include>, seedIsWork: boolean): RestMapping {\n const institutions = include.has(\"institutions\");\n return {\n ...OPENALEX_MAPPING,\n load: seedIsWork ? \"by-id\" : \"authored\",\n seed: undefined,\n expand: \"authored\",\n hydrate: \"authors-by-id\",\n directed: false,\n entities: {\n ...OPENALEX_MAPPING.entities,\n work: {\n id: \"id\",\n // a rule's `from` is read with the record's own prefix\n stripPrefix: PREFIX,\n node: false,\n edges: [\n { pairs: \"authorships[].author.id\", type: \"coauthor\", entity: \"author\" },\n ...(institutions\n ? [\n {\n each: \"authorships[]\",\n from: \"author.id\",\n to: \"institutions[].id\",\n type: \"affiliated_with\",\n entity: \"institution\",\n },\n ]\n : []),\n ],\n embedded: [\n { at: \"authorships[].author\", entity: \"author\" },\n ...(institutions ? [{ at: \"authorships[].institutions[]\", entity: \"institution\" }] : []),\n ],\n },\n },\n };\n}\n\n/**\n * An OpenAlex id param: `W123` or its URL form, checked so a value cannot add a filter.\n * @param value - the param\n * @param name - its name\n * @param letter - the id's kind letter\n * @param ctx - the context\n * @returns the bare id\n */\nfunction openalexId(value: unknown, name: string, letter: string, ctx: SourceContext): string {\n const text = typeof value === \"string\" ? value.trim().replace(PREFIX, \"\") : \"\";\n if (!new RegExp(String.raw`^${letter}\\d+$`, \"i\").test(text)) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", `${name} is not an OpenAlex id`, { name, reason: \"format\" });\n }\n return text.toUpperCase();\n}\n\n/**\n * The plan of an OpenAlex call.\n * @param params - the params\n * @param ctx - the context\n * @param purpose - what the plan is for\n * @returns the mapping and values\n */\nfunction plan(params: OpenAlexParams, ctx: SourceContext, purpose: RestPurpose): RestPlan {\n const graph = params.graph ?? \"citation\";\n const include = includes(params.include);\n const hasWork = params.work !== undefined && params.work !== \"\";\n const hasAuthor = params.author !== undefined && params.author !== \"\";\n if (purpose !== \"expand\" && hasWork === hasAuthor) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"give exactly one of work and author\", {\n name: \"work\",\n reason: hasWork ? \"exclusive\" : \"required\",\n });\n }\n let seed = \"\";\n if (hasWork) {\n seed = openalexId(params.work, \"work\", \"W\", ctx);\n } else if (hasAuthor) {\n seed = openalexId(params.author, \"author\", \"A\", ctx);\n }\n if (graph === \"coauthorship\") {\n return {\n mapping: coauthorshipMapping(include, hasWork),\n values: { ids: seed, select: purpose === \"validate\" ? \"id,updated_date\" : \"id,updated_date,authorships\" },\n };\n }\n let select =\n WORK_FIELDS + (include.has(\"authors\") ? \",authorships\" : \"\") + (include.has(\"topics\") ? \",topics\" : \"\");\n if (purpose === \"validate\") {\n select = \"id,updated_date\";\n }\n const mapping = citationMapping(include);\n return {\n mapping: hasWork ? mapping : { ...mapping, load: \"authored\", seed: undefined },\n values: { ids: seed, select },\n };\n}\n\n/** OpenAlex's own ids: a kind letter and digits. */\nconst ANY_ID = /^[WAIT]\\d+$/;\n\nconst methods = restMethods<OpenAlexParams>(plan, false);\n\n/**\n * The OpenAlex preset (https://openalex.org): `work` (the citation graph around a work, default)\n * or `author` (the works they wrote), `graph: \"coauthorship\"` for authors joined by shared works,\n * and `include` (`\"authors\"`, `\"institutions\"`, `\"topics\"`) for more node kinds. Without a key,\n * the first page loads and a later one warns W_SOURCE_AUTH with `report.source.next`; pass\n * `credentials.apiKey({ query: \"api_key\" }, key)` and continue with the cursor. Experimental.\n * @category Network sources\n */\nexport const openalexSource: GraphSource<OpenAlexParams> = defineSource<OpenAlexParams>({\n id: OPENALEX_SOURCE_ID,\n descriptor: OPENALEX_DESCRIPTOR,\n ...methods,\n expand(request, sink, ctx) {\n for (const id of request.ids) {\n if (!ANY_ID.test(String(id))) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"an expansion seed is not an OpenAlex id\", {\n name: \"ids\",\n reason: \"format\",\n });\n }\n }\n return methods.expand(request, sink, ctx);\n },\n});\n"],"names":["plan","select"],"mappings":"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"}
1
+ {"version":3,"file":"sources-rest.js","sources":["../src/sources/rest/selectors.ts","../src/sources/rest/templates.ts","../src/sources/rest/mapping.ts","../src/sources/rest/paging.ts","../src/sources/rest/records.ts","../src/sources/rest/source.ts","../src/sources/rest/openalex.ts"],"sourcesContent":["/**\n * Selectors of the REST mapping (design section 13.2): graph-io's dotted paths plus `[]` to flatten\n * an array. `results`, `meta.next_cursor`, `authorships[].author.id`; `.` is the value itself and\n * `#` is a record's position in the array it came from. Not JMESPath, so graph-io keeps zero\n * dependencies.\n */\n\n/** One step of a selector: a key, and whether its value's array is flattened. */\ninterface Step {\n readonly key: string;\n readonly flatten: boolean;\n}\n\n/** A key: anything but a dot or a bracket. */\nconst STEP = /^([^.[\\]]+)(\\[\\])?$/;\n\n/** Parsed selectors, by text. */\nconst PARSED = new Map<string, readonly Step[] | null>();\n\n/**\n * Parse a selector.\n * @param selector - the text\n * @returns its steps ([] for \".\"), or null when it is not a selector\n */\nexport function parseSelector(selector: string): readonly Step[] | null {\n const cached = PARSED.get(selector);\n if (cached !== undefined) {\n return cached;\n }\n let steps: Step[] | null = [];\n if (selector !== \".\") {\n for (const part of selector.split(\".\")) {\n const m = STEP.exec(part);\n if (m === null) {\n steps = null;\n break;\n }\n steps.push({ key: m[1], flatten: m[2] !== undefined });\n }\n }\n PARSED.set(selector, steps);\n return steps;\n}\n\n/**\n * Every value a selector reaches, in document order; missing keys reach nothing.\n * @param value - where to start\n * @param selector - the selector (a checked mapping holds only valid ones)\n * @returns the values\n */\nexport function select(value: unknown, selector: string): unknown[] {\n let out: unknown[] = value === undefined ? [] : [value];\n for (const step of parseSelector(selector) ?? []) {\n const next: unknown[] = [];\n for (const v of out) {\n if (typeof v !== \"object\" || v === null || !Object.hasOwn(v, step.key)) {\n continue;\n }\n const got = (v as Record<string, unknown>)[step.key];\n if (step.flatten && Array.isArray(got)) {\n next.push(...(got as unknown[]));\n } else if (got !== undefined && got !== null) {\n next.push(got);\n }\n }\n out = next;\n }\n return out.filter((v) => v !== null && v !== undefined);\n}\n\n/**\n * The first value a selector reaches.\n * @param value - where to start\n * @param selector - the selector\n * @returns the value, or undefined\n */\nexport function selectOne(value: unknown, selector: string): unknown {\n return select(value, selector)[0];\n}\n\n/**\n * The records a request's `records` selector names: an array it reaches is the records, any other\n * value is one record.\n * @param body - the response body\n * @param selector - the selector\n * @returns the records\n */\nexport function selectRecords(body: unknown, selector: string): unknown[] {\n const out = select(body, selector);\n return out.length === 1 && Array.isArray(out[0]) ? (out[0] as unknown[]) : out;\n}\n","/**\n * Templates of the REST mapping (design section 13.2): `{name}` takes a value. Every value is\n * URL-encoded for its position, a value cannot add a path segment, and the finished URL must have\n * the mapping endpoint's origin and stay under its path.\n */\n\nimport { type ImportReportBuilder } from \"../../common/report.js\";\nimport { failOn } from \"../fail.js\";\nimport { type RestRequest } from \"./params.js\";\n\n/** One `{name}` in a template. */\nconst SLOT = /\\{([^{}]*)\\}/g;\n\n/** A slot name. */\nconst NAME = /^[A-Za-z_][A-Za-z0-9_-]*$/;\n\n/** The values templates are filled from: params as strings, plus `{id}` and `{ids}`. */\nexport type TemplateValues = Readonly<Record<string, string>>;\n\n/**\n * The slot names of a template, or null when its braces are malformed.\n * @param template - the template\n * @returns the names\n */\nexport function templateNames(template: string): string[] | null {\n const names: string[] = [];\n for (const m of template.matchAll(SLOT)) {\n if (!NAME.test(m[1])) {\n return null;\n }\n names.push(m[1]);\n }\n // a brace left over after the slots is malformed\n return /[{}]/.test(template.replaceAll(SLOT, \"\")) ? null : names;\n}\n\n/**\n * Fill a template.\n * @param template - the template\n * @param values - the values\n * @param encode - how a value is encoded for its position\n * @param report - the load's report, for a missing value\n * @returns the filled text\n */\nfunction fill(\n template: string,\n values: TemplateValues,\n encode: (value: string) => string,\n report: ImportReportBuilder,\n): string {\n return template.replaceAll(SLOT, (_, name: string) => {\n const value = values[name];\n if (value === undefined) {\n failOn(report, \"E_SOURCE_PARAM\", `the mapping's template needs ${name}`, { name, reason: \"required\" });\n }\n return encode(value);\n });\n}\n\n/**\n * A path value: percent-encoded, so a slash cannot add a segment, and never a dot segment.\n * @param report - the load's report\n * @returns the encoder\n */\nfunction pathValue(report: ImportReportBuilder): (value: string) => string {\n return (value) => {\n // \".\" and \"..\" stay dot segments even percent-encoded, so the URL parser would climb out\n if (value === \".\" || value === \"..\" || value === \"\") {\n failOn(report, \"E_SOURCE_PARAM\", \"a path value may not be empty or a dot segment\", {\n name: \"path\",\n reason: \"path\",\n });\n }\n return encodeURIComponent(value);\n };\n}\n\n/**\n * Check that a URL stays on the mapping's origin and under its path.\n * @param url - the URL\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the URL\n */\nexport function checkOrigin(url: URL, endpoint: URL, report: ImportReportBuilder): URL {\n const base = endpoint.pathname.replace(/\\/$/, \"\");\n if (url.origin !== endpoint.origin || !(url.pathname === base || url.pathname.startsWith(`${base}/`))) {\n failOn(report, \"E_SOURCE_PARAM\", \"a request left the mapping's endpoint\", { name: \"url\", reason: \"origin\" });\n }\n return url;\n}\n\n/**\n * The URL and init of one request.\n * @param endpoint - the mapping's endpoint\n * @param request - the request\n * @param values - the template values\n * @param report - the load's report\n * @returns the URL and the fetch init\n */\nexport function buildRequest(\n endpoint: URL,\n request: RestRequest,\n values: TemplateValues,\n report: ImportReportBuilder,\n): { url: URL; init: RequestInit & { idempotent?: boolean } } {\n const path = fill(request.path, values, pathValue(report), report);\n const url = new URL(`${endpoint.origin}${endpoint.pathname.replace(/\\/$/, \"\")}${path}`);\n for (const [key, template] of Object.entries(request.query ?? {})) {\n // URLSearchParams encodes the value for the query\n url.searchParams.set(\n key,\n fill(template, values, (v) => v, report),\n );\n }\n checkOrigin(url, endpoint, report);\n if (request.method !== \"POST\") {\n return { url, init: {} };\n }\n const body = fillBody(request.body, values, report);\n return {\n url,\n init: {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body ?? null),\n // a mapping's POST reads; it is a query, so it is as safe to retry as a GET\n idempotent: true,\n },\n };\n}\n\n/**\n * Fill the string leaves of a POST body.\n * @param body - the body template\n * @param values - the values\n * @param report - the load's report\n * @returns the body\n */\nfunction fillBody(body: unknown, values: TemplateValues, report: ImportReportBuilder): unknown {\n if (typeof body === \"string\") {\n return fill(body, values, (v) => v, report);\n }\n if (Array.isArray(body)) {\n return body.map((b) => fillBody(b, values, report));\n }\n if (typeof body === \"object\" && body !== null) {\n return Object.fromEntries(Object.entries(body).map(([k, v]) => [k, fillBody(v, values, report)]));\n }\n return body;\n}\n","/**\n * Checking a REST mapping before it runs (design section 13.2). A mapping is JSON data, typed into\n * a form or read from a project file, so every field is checked and every problem is a coded\n * issue naming where it is.\n */\n\nimport { type RestEdgeRule, type RestEntity, type RestMapping, type RestRequest } from \"./params.js\";\nimport { parseSelector } from \"./selectors.js\";\nimport { templateNames } from \"./templates.js\";\n\n/**\n * What is wrong with one field of a mapping. Open union.\n * @category Network sources\n */\nexport type RestMappingIssueCode =\n | \"version\" // version is not 1\n | \"endpoint\" // not an http(s) URL, or one holding a user, query or fragment\n | \"missing\" // a required field is absent or of the wrong type\n | \"unknown-request\" // names a request the mapping lacks\n | \"unknown-entity\" // names an entity the mapping lacks\n | \"selector\" // not a selector\n | \"template\" // malformed braces or slot names\n | \"paging\" // an unknown paging style or a bad paging field\n | \"batch\" // batch.max is not a positive integer, or join is not a string\n | \"number\" // not a positive number\n | (string & {}); // NOSONAR(S4335): the open-union idiom keeps the listed codes in editor completion\n\n/**\n * One problem `checkRestMapping` found. Experimental.\n * @category Network sources\n */\nexport interface RestMappingIssue {\n /** What is wrong. */\n readonly code: RestMappingIssueCode;\n /** Where, as a dotted path into the mapping (`requests.citing.paging.next`). */\n readonly at: string;\n}\n\n/** The checks' accumulator. */\ntype Push = (code: RestMappingIssueCode, at: string) => void;\n\n/**\n * Whether a value is a plain object.\n * @param v - the value\n * @returns true for an object that is not an array\n */\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * Check a selector field.\n * @param value - the field\n * @param at - where it is\n * @param push - the accumulator\n * @param required - whether it must be present\n * @param index - whether `#` (the record's position) is allowed\n */\nfunction checkSelector(value: unknown, at: string, push: Push, required: boolean, index = false): void {\n if (value === undefined && !required) {\n return;\n }\n if (typeof value !== \"string\") {\n push(\"missing\", at);\n } else if (!(index && value === \"#\") && parseSelector(value) === null) {\n push(\"selector\", at);\n }\n}\n\n/**\n * Check a template field.\n * @param value - the field\n * @param at - where it is\n * @param push - the accumulator\n */\nfunction checkTemplate(value: unknown, at: string, push: Push): void {\n if (typeof value !== \"string\") {\n push(\"missing\", at);\n } else if (templateNames(value) === null) {\n push(\"template\", at);\n }\n}\n\n/**\n * Check a request's query templates.\n * @param query - the query field\n * @param at - where the request is\n * @param push - the accumulator\n */\nfunction checkQuery(query: RestRequest[\"query\"], at: string, push: Push): void {\n if (query === undefined) {\n return;\n }\n if (!isObject(query)) {\n push(\"missing\", `${at}.query`);\n return;\n }\n for (const [k, v] of Object.entries(query)) {\n checkTemplate(v, `${at}.query.${k}`, push);\n }\n}\n\n/**\n * Whether a batch field is well formed: a positive integer max and a string join.\n * @param batch - the batch field\n * @returns true when it is\n */\nfunction isBatch(batch: RestRequest[\"batch\"]): boolean {\n return isObject(batch) && Number.isInteger(batch.max) && batch.max >= 1 && typeof batch.join === \"string\";\n}\n\n/**\n * Check one request.\n * @param r - the request\n * @param at - where it is\n * @param entities - the mapping's entity names\n * @param push - the accumulator\n */\nfunction checkRequest(r: RestRequest, at: string, entities: ReadonlySet<string>, push: Push): void {\n if (!isObject(r)) {\n push(\"missing\", at);\n return;\n }\n if (r.method !== undefined && r.method !== \"GET\" && r.method !== \"POST\") {\n push(\"missing\", `${at}.method`);\n }\n checkTemplate(r.path, `${at}.path`, push);\n if (typeof r.path === \"string\" && !r.path.startsWith(\"/\")) {\n push(\"template\", `${at}.path`);\n }\n checkQuery(r.query, at, push);\n checkSelector(r.records, `${at}.records`, push, true);\n if (typeof r.entity !== \"string\") {\n push(\"missing\", `${at}.entity`);\n } else if (!entities.has(r.entity)) {\n push(\"unknown-entity\", `${at}.entity`);\n }\n if (r.batch !== undefined && !isBatch(r.batch)) {\n push(\"batch\", `${at}.batch`);\n }\n if (r.paging !== undefined) {\n checkPaging(r.paging, `${at}.paging`, push);\n }\n}\n\n/**\n * Check a paging field.\n * @param p - the paging\n * @param at - where it is\n * @param push - the accumulator\n */\nfunction checkPaging(p: RestRequest[\"paging\"], at: string, push: Push): void {\n const paging = p as Record<string, unknown> | undefined;\n if (!isObject(paging)) {\n push(\"paging\", at);\n return;\n }\n switch (paging.style) {\n case \"cursor\":\n if (typeof paging.param !== \"string\" || typeof paging.first !== \"string\") {\n push(\"paging\", at);\n }\n checkSelector(paging.next, `${at}.next`, push, true);\n break;\n case \"offset\": {\n const size = paging.size as Record<string, unknown> | undefined;\n const ok =\n typeof paging.param === \"string\" &&\n isObject(size) &&\n typeof size.param === \"string\" &&\n Number.isInteger(size.value) &&\n (size.value as number) > 0 &&\n (paging.unit === undefined || paging.unit === \"items\" || paging.unit === \"pages\") &&\n (paging.base === undefined || paging.base === 0 || paging.base === 1);\n if (!ok) {\n push(\"paging\", at);\n }\n break;\n }\n case \"link-header\":\n if (paging.rel !== undefined && typeof paging.rel !== \"string\") {\n push(\"paging\", at);\n }\n break;\n case \"next-url\":\n checkSelector(paging.next, `${at}.next`, push, true);\n break;\n default:\n push(\"paging\", `${at}.style`);\n }\n}\n\n/**\n * Check one edge rule.\n * @param rule - the rule\n * @param at - where it is\n * @param entities - the mapping's entity names\n * @param push - the accumulator\n */\nfunction checkEdgeRule(rule: RestEdgeRule, at: string, entities: ReadonlySet<string>, push: Push): void {\n if (!isObject(rule)) {\n push(\"missing\", at);\n return;\n }\n const r = rule as Record<string, unknown>;\n if (typeof r.type !== \"string\") {\n push(\"missing\", `${at}.type`);\n }\n checkSelector(r.each, `${at}.each`, push, false);\n if (\"pairs\" in r) {\n checkSelector(r.pairs, `${at}.pairs`, push, true);\n } else {\n checkSelector(r.to, `${at}.to`, push, true);\n checkSelector(r.from, `${at}.from`, push, false);\n if (isObject(r.fields)) {\n for (const [k, v] of Object.entries(r.fields)) {\n checkSelector(v, `${at}.fields.${k}`, push, true);\n }\n } else if (r.fields !== undefined) {\n push(\"missing\", `${at}.fields`);\n }\n }\n if (r.entity !== undefined && (typeof r.entity !== \"string\" || !entities.has(r.entity))) {\n push(\"unknown-entity\", `${at}.entity`);\n }\n}\n\n/**\n * Check one entity.\n * @param e - the entity\n * @param at - where it is\n * @param entities - the mapping's entity names\n * @param push - the accumulator\n */\nfunction checkEntity(e: RestEntity, at: string, entities: ReadonlySet<string>, push: Push): void {\n if (!isObject(e)) {\n push(\"missing\", at);\n return;\n }\n checkSelector(e.id, `${at}.id`, push, true, true);\n if (e.stripPrefix !== undefined && typeof e.stripPrefix !== \"string\") {\n push(\"missing\", `${at}.stripPrefix`);\n }\n if (e.label !== undefined && typeof e.label !== \"string\") {\n push(\"missing\", `${at}.label`);\n }\n if (e.node !== undefined && e.node) {\n push(\"missing\", `${at}.node`);\n }\n if (isObject(e.fields)) {\n for (const [k, v] of Object.entries(e.fields)) {\n checkSelector(v, `${at}.fields.${k}`, push, true, true);\n }\n } else if (e.fields !== undefined) {\n push(\"missing\", `${at}.fields`);\n }\n if (Array.isArray(e.edges)) {\n (e.edges as readonly RestEdgeRule[]).forEach((rule, i) => {\n checkEdgeRule(rule, `${at}.edges.${String(i)}`, entities, push);\n });\n } else if (e.edges !== undefined) {\n push(\"missing\", `${at}.edges`);\n }\n if (Array.isArray(e.embedded)) {\n e.embedded.forEach((em, i) => {\n const where = `${at}.embedded.${String(i)}`;\n if (!isObject(em)) {\n push(\"missing\", where);\n return;\n }\n checkSelector(em.at, `${where}.at`, push, true);\n if (typeof em.entity !== \"string\" || !entities.has(em.entity)) {\n push(\"unknown-entity\", `${where}.entity`);\n }\n });\n } else if (e.embedded !== undefined) {\n push(\"missing\", `${at}.embedded`);\n }\n}\n\n/**\n * Check the mapping's top-level names of requests.\n * @param m - the mapping\n * @param requests - its request names\n * @param push - the accumulator\n */\nfunction checkRequestNames(m: RestMapping, requests: ReadonlySet<string>, push: Push): void {\n const names: [string, unknown][] = [\n [\"load\", m.load],\n [\"hydrate\", m.hydrate],\n [\"seed\", m.seed],\n ];\n if (isObject(m.expand)) {\n names.push([\"expand.in\", m.expand.in], [\"expand.out\", m.expand.out]);\n } else {\n names.push([\"expand\", m.expand]);\n }\n for (const [at, name] of names) {\n if (name === undefined && at !== \"load\") {\n continue;\n }\n if (typeof name !== \"string\") {\n push(\"missing\", at);\n } else if (!requests.has(name)) {\n push(\"unknown-request\", at);\n }\n }\n}\n\n/**\n * Check the endpoint.\n * @param endpoint - the field\n * @param push - the accumulator\n */\nfunction checkEndpoint(endpoint: unknown, push: Push): void {\n let url: URL | null = null;\n try {\n url = new URL(typeof endpoint === \"string\" ? endpoint : \"\");\n } catch {\n // not a URL\n }\n if (\n url === null ||\n (url.protocol !== \"https:\" && url.protocol !== \"http:\") ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n url.search !== \"\" ||\n url.hash !== \"\"\n ) {\n push(\"endpoint\", \"endpoint\");\n }\n}\n\n/**\n * Check a REST mapping without running it: the version, the endpoint, every request (templates,\n * selectors, paging, batching) and entity (selectors, edge rules, embedded records), and that every\n * name it uses exists. Experimental.\n * @param mapping - the mapping, as data from anywhere\n * @returns every problem found; empty when the mapping can run\n * @category Network sources\n */\nexport function checkRestMapping(mapping: unknown): readonly RestMappingIssue[] {\n const issues: RestMappingIssue[] = [];\n const push: Push = (code, at) => {\n issues.push(Object.freeze({ code, at }));\n };\n if (!isObject(mapping)) {\n push(\"missing\", \"\");\n return issues;\n }\n const m = mapping as unknown as RestMapping;\n if (m.version !== 1) {\n push(\"version\", \"version\");\n }\n checkEndpoint(m.endpoint, push);\n const requests = isObject(m.requests) ? m.requests : {};\n const entities = isObject(m.entities) ? m.entities : {};\n if (!isObject(m.requests)) {\n push(\"missing\", \"requests\");\n }\n if (!isObject(m.entities)) {\n push(\"missing\", \"entities\");\n }\n const entityNames = new Set(Object.keys(entities));\n for (const [name, r] of Object.entries(requests)) {\n checkRequest(r, `requests.${name}`, entityNames, push);\n }\n for (const [name, e] of Object.entries(entities)) {\n checkEntity(e, `entities.${name}`, entityNames, push);\n }\n checkRequestNames(m, new Set(Object.keys(requests)), push);\n checkLimits(m, push);\n checkSelector(m.modified, \"modified\", push, false);\n if (m.directed !== undefined && typeof m.directed !== \"boolean\") {\n push(\"missing\", \"directed\");\n }\n return issues;\n}\n\n/**\n * Check the rate limit and the budget headers.\n * @param m - the mapping\n * @param push - the accumulator\n */\nfunction checkLimits(m: RestMapping, push: Push): void {\n for (const [at, value] of [\n [\"rateLimit.requests\", m.rateLimit?.requests],\n [\"rateLimit.perMs\", m.rateLimit?.perMs],\n ] as const) {\n if (m.rateLimit !== undefined && !(typeof value === \"number\" && value > 0)) {\n push(\"number\", at);\n }\n }\n if (\n m.budgetHeaders !== undefined &&\n (typeof m.budgetHeaders.remaining !== \"string\" ||\n (m.budgetHeaders.reset !== undefined && typeof m.budgetHeaders.reset !== \"string\"))\n ) {\n push(\"missing\", \"budgetHeaders\");\n }\n}\n","/**\n * Paging of the REST mapping (design section 13.2): a cursor in the body, an offset, the `Link`\n * header, or a next URL in the body. A position is a string or a number, so it fits a SourceCursor;\n * a position that is a URL is checked against the mapping's origin before it is followed.\n */\n\nimport { type ImportReportBuilder } from \"../../common/report.js\";\nimport { failOn } from \"../fail.js\";\nimport { type RestPaging } from \"./params.js\";\nimport { selectOne } from \"./selectors.js\";\nimport { checkOrigin } from \"./templates.js\";\n\n/** Where a paged request is: the first page (null), a cursor or offset, or a full URL. */\nexport type PagePosition = string | number | null;\n\n/**\n * The position of the first page.\n * @param paging - the request's paging\n * @returns the position\n */\nfunction firstPosition(paging: RestPaging | undefined): PagePosition {\n switch (paging?.style) {\n case \"cursor\":\n return paging.first;\n case \"offset\":\n return paging.base ?? 0;\n default:\n return null;\n }\n}\n\n/**\n * The URL of a page.\n * @param url - the request's first-page URL\n * @param paging - the request's paging\n * @param position - where to read\n * @param endpoint - the mapping's endpoint, which a full URL must stay on\n * @param report - the load's report\n * @returns the page's URL\n */\nexport function pageUrl(\n url: URL,\n paging: RestPaging | undefined,\n position: PagePosition,\n endpoint: URL,\n report: ImportReportBuilder,\n): URL {\n if (position === null) {\n return url;\n }\n const out = new URL(url);\n switch (paging?.style) {\n case \"cursor\":\n out.searchParams.set(paging.param, String(position));\n return out;\n case \"offset\":\n out.searchParams.set(paging.param, String(position));\n out.searchParams.set(paging.size.param, String(paging.size.value));\n return out;\n default:\n // link-header and next-url positions are full URLs from a response (or a recorded cursor)\n return checkOrigin(new URL(String(position), url), endpoint, report);\n }\n}\n\n/**\n * The first page's URL with its paging parameters, so an offset request carries its size.\n * @param url - the request's URL\n * @param paging - the request's paging\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the URL\n */\nexport function firstPageUrl(\n url: URL,\n paging: RestPaging | undefined,\n endpoint: URL,\n report: ImportReportBuilder,\n): URL {\n return pageUrl(url, paging, firstPosition(paging), endpoint, report);\n}\n\n/**\n * The `rel` URL of a Link header.\n * @param header - the header's value\n * @param rel - the relation\n * @returns the URL text, or null\n */\nfunction linkOf(header: string, rel: string): string | null {\n for (const part of header.split(/,(?=\\s*<)/)) {\n const m = /^\\s*<([^>]*)>(.*)$/.exec(part);\n if (m === null) {\n continue;\n }\n const rels = /;\\s*rel=\"?([^\";]+)\"?/i.exec(m[2]);\n if (rels?.[1].split(/\\s+/).includes(rel)) {\n return m[1];\n }\n }\n return null;\n}\n\n/** What `nextPosition` reads. */\ninterface PageResponse {\n /** The parsed body. */\n readonly body: unknown;\n /** The response headers. */\n readonly headers: Headers;\n /** The URL the page was read from. */\n readonly url: URL;\n /** How many records the page held. */\n readonly records: number;\n /** Where the load runs: a missing Link header in a browser may be one the service hides. */\n readonly runtime: string;\n}\n\n/**\n * The next page's URL from the Link header, or null after the last one.\n * @param rel - the relation that names the next page\n * @param page - this page's response\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the next position\n */\nfunction nextLink(rel: string, page: PageResponse, endpoint: URL, report: ImportReportBuilder): PagePosition {\n const header = page.headers.get(\"link\");\n if (header === null) {\n if (page.runtime === \"browser\") {\n // a browser reads Link only when the service exposes it: never a silent single page\n failOn(report, \"E_SOURCE_RESPONSE\", \"the Link header cannot be read\", {\n expected: \"link-header\",\n contentType: page.headers.get(\"content-type\"),\n });\n }\n return null;\n }\n const next = linkOf(header, rel);\n return next === null ? null : checkOrigin(new URL(next, page.url), endpoint, report).href;\n}\n\n/**\n * Where the next page is, or null after the last one.\n * @param paging - the request's paging\n * @param position - this page's position\n * @param page - this page's response\n * @param endpoint - the mapping's endpoint\n * @param report - the load's report\n * @returns the next position\n */\nexport function nextPosition(\n paging: RestPaging | undefined,\n position: PagePosition,\n page: PageResponse,\n endpoint: URL,\n report: ImportReportBuilder,\n): PagePosition {\n switch (paging?.style) {\n case \"cursor\": {\n const next = selectOne(page.body, paging.next);\n return (typeof next === \"string\" && next !== \"\") || typeof next === \"number\" ? next : null;\n }\n case \"offset\": {\n if (page.records < paging.size.value || page.records === 0) {\n return null;\n }\n const step = paging.unit === \"pages\" ? 1 : paging.size.value;\n return Number(position) + step;\n }\n case \"link-header\":\n return nextLink(paging.rel ?? \"next\", page, endpoint, report);\n case \"next-url\": {\n const next = selectOne(page.body, paging.next);\n return typeof next === \"string\" && next !== \"\"\n ? checkOrigin(new URL(next, page.url), endpoint, report).href\n : null;\n }\n default:\n return null;\n }\n}\n","/**\n * Turning a REST API's records into nodes and edges (design section 13.2): each record of an\n * entity is a node, each edge rule makes edges, a target with no record yet becomes a stub, and\n * embedded records are nodes of their own entity. A stub never overwrites a full record.\n */\n\nimport { SOURCE_ENTITY_ATTR, SOURCE_STUB_ATTR } from \"../ids.js\";\nimport { type EdgeRecord, type NodeRecord } from \"../types.js\";\nimport { type RestEdgeRule, type RestEntity, type RestMapping } from \"./params.js\";\nimport { select, selectOne } from \"./selectors.js\";\n\n/** What one load or expansion knows about the ids it wrote, across its pages. */\nexport interface RecordState {\n /** Ids written with a full record. */\n readonly full: Set<string>;\n /** Ids written as stubs. */\n readonly stubs: Set<string>;\n /** Ids the caller already holds (an expansion's seeds and `exclude`): never stubbed. */\n readonly known: ReadonlySet<string>;\n /** The newest modification time seen, for the validators. */\n modified: string | null;\n}\n\n/** The nodes and edges of one page. */\nexport interface PageRecords {\n readonly nodes: NodeRecord[];\n readonly edges: EdgeRecord[];\n}\n\n/**\n * A fresh state.\n * @param known - ids the caller holds already\n * @returns the state\n */\nexport function newState(known: Iterable<string> = []): RecordState {\n return { full: new Set(), stubs: new Set(), known: new Set(known), modified: null };\n}\n\n/**\n * An id as text, with the entity's prefix stripped.\n * @param value - what a selector reached\n * @param entity - the entity whose prefix applies\n * @returns the id, or null when the value is not one\n */\nfunction idText(value: unknown, entity: RestEntity | undefined): string | null {\n if (typeof value !== \"string\" && typeof value !== \"number\") {\n return null;\n }\n const text = String(value);\n const prefix = entity?.stripPrefix;\n return prefix !== undefined && prefix !== \"\" && text.startsWith(prefix) ? text.slice(prefix.length) : text;\n}\n\n/**\n * The value of a field selector: every value for a selector with `[]`, else the first.\n * @param record - the record\n * @param selector - the selector\n * @param index - the record's position, for `#`\n * @returns the value\n */\nfunction fieldValue(record: unknown, selector: string, index: number): unknown {\n if (selector === \"#\") {\n return index;\n }\n return selector.includes(\"[]\") ? select(record, selector) : selectOne(record, selector);\n}\n\n/** Converts the records of one page. */\nclass PageWriter {\n readonly out: PageRecords = { nodes: [], edges: [] };\n /** Edge rules to run once every node of the page is known, so a target on this page is no stub. */\n private readonly pending: { record: unknown; entity: string; id: string | null }[] = [];\n\n /**\n * Create one.\n * @param mapping - the mapping\n * @param state - the load's state\n */\n constructor(\n private readonly mapping: RestMapping,\n private readonly state: RecordState,\n ) {}\n\n /**\n * Add the records of an entity, and their embedded records.\n * @param records - the records\n * @param entityName - their entity\n */\n addRecords(records: readonly unknown[], entityName: string): void {\n const entity = this.mapping.entities[entityName];\n records.forEach((record, index) => {\n const id = entity.node === false ? null : idText(fieldValue(record, entity.id, index), entity);\n if (entity.node !== false) {\n if (id === null) {\n return;\n }\n this.addNode(record, index, id, entityName, entity);\n }\n const modified = this.mapping.modified === undefined ? undefined : selectOne(record, this.mapping.modified);\n if (typeof modified === \"string\" && (this.state.modified === null || modified > this.state.modified)) {\n this.state.modified = modified;\n }\n this.pending.push({ record, entity: entityName, id });\n for (const em of entity.embedded ?? []) {\n this.addRecords(select(record, em.at), em.entity);\n }\n });\n }\n\n /**\n * Write a full record.\n * @param record - the record\n * @param index - its position\n * @param id - its id\n * @param entityName - its entity\n * @param entity - the entity\n */\n private addNode(record: unknown, index: number, id: string, entityName: string, entity: RestEntity): void {\n const attrs: Record<string, unknown> = { labels: [entity.label ?? entityName] };\n if (entity.fields === undefined) {\n // without fields every top-level scalar is kept\n for (const [k, v] of Object.entries(record as Record<string, unknown>)) {\n if (\n k !== \"id\" &&\n k !== \"labels\" &&\n (typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\")\n ) {\n attrs[k] = v;\n }\n }\n } else {\n for (const [name, selector] of Object.entries(entity.fields)) {\n const v = fieldValue(record, selector, index);\n if (v !== undefined) {\n attrs[name] = v;\n }\n }\n }\n if (this.state.stubs.has(id)) {\n // the full record replaces a stub written earlier\n attrs[SOURCE_STUB_ATTR] = false;\n }\n this.state.full.add(id);\n this.out.nodes.push({ id, ...attrs });\n }\n\n /**\n * Make sure an edge end exists: a stub when no record of it was written and the caller does not\n * hold it.\n * @param id - the id\n * @param entity - its entity, when known\n */\n private end(id: string, entity: string | undefined): void {\n const { full, stubs, known } = this.state;\n if (full.has(id) || stubs.has(id) || known.has(id)) {\n return;\n }\n stubs.add(id);\n this.out.nodes.push({\n id,\n [SOURCE_STUB_ATTR]: true,\n ...(entity === undefined ? {} : { [SOURCE_ENTITY_ATTR]: entity }),\n });\n }\n\n /**\n * Run one edge rule over a record.\n * @param rule - the rule\n * @param record - the record\n * @param entityName - the record's entity\n * @param recordId - the record's id (null for a container)\n */\n private runRule(rule: RestEdgeRule, record: unknown, entityName: string, recordId: string | null): void {\n const scopes = rule.each === undefined ? [record] : select(record, rule.each);\n if (\"pairs\" in rule) {\n this.runPairsRule(rule, scopes, entityName);\n } else {\n this.runLinkRule(rule, scopes, entityName, recordId);\n }\n }\n\n /**\n * Run a pairs rule: an edge between every two distinct ids in each scope.\n * @param rule - the rule\n * @param scopes - the scopes it runs over\n * @param entityName - the record's entity\n */\n private runPairsRule(\n rule: Extract<RestEdgeRule, { pairs: string }>,\n scopes: readonly unknown[],\n entityName: string,\n ): void {\n const entityOf = rule.entity ?? entityName;\n const entity = this.mapping.entities[entityOf];\n for (const scope of scopes) {\n const ids = [...new Set(select(scope, rule.pairs).map((v) => idText(v, entity)))].filter(\n (v): v is string => v !== null,\n );\n for (let i = 0; i < ids.length; i++) {\n for (let j = i + 1; j < ids.length; j++) {\n this.end(ids[i], entityOf);\n this.end(ids[j], entityOf);\n this.out.edges.push({ source: ids[i], target: ids[j], type: rule.type });\n }\n }\n }\n }\n\n /**\n * Run a from/to rule: an edge from the record (or a selected id) to each selected id.\n * @param rule - the rule\n * @param scopes - the scopes it runs over\n * @param entityName - the record's entity\n * @param recordId - the record's id (null for a container)\n */\n private runLinkRule(\n rule: Exclude<RestEdgeRule, { pairs: string }>,\n scopes: readonly unknown[],\n entityName: string,\n recordId: string | null,\n ): void {\n const own = this.mapping.entities[entityName];\n const targetEntity = rule.entity === undefined ? own : this.mapping.entities[rule.entity];\n for (const scope of scopes) {\n const from = rule.from === undefined ? recordId : idText(selectOne(scope, rule.from), own);\n if (from === null) {\n continue;\n }\n const tos = select(scope, rule.to)\n .map((t) => idText(t, targetEntity))\n .filter((v): v is string => v !== null);\n for (const to of tos) {\n this.end(from, rule.from === undefined ? entityName : undefined);\n this.end(to, rule.entity);\n this.out.edges.push({ ...edgeFields(rule.fields, scope), source: from, target: to, type: rule.type });\n }\n }\n }\n\n /**\n * Run the edge rules of every record added.\n * @returns the page\n */\n finish(): PageRecords {\n for (const { record, entity, id } of this.pending) {\n for (const rule of this.mapping.entities[entity].edges ?? []) {\n this.runRule(rule, record, entity, id);\n }\n }\n this.pending.length = 0;\n return this.out;\n }\n}\n\n/**\n * An edge's fields, read from its scope.\n * @param fields - the rule's field selectors\n * @param scope - the scope the edge came from\n * @returns the fields that have a value\n */\nfunction edgeFields(fields: Readonly<Record<string, string>> | undefined, scope: unknown): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, selector] of Object.entries(fields ?? {})) {\n const v = fieldValue(scope, selector, 0);\n if (v !== undefined) {\n out[name] = v;\n }\n }\n return out;\n}\n\n/**\n * The nodes and edges of one page of records.\n * @param mapping - the mapping\n * @param groups - the page's records, by entity (a seed's records first)\n * @param state - the load's state, updated\n * @returns the nodes and edges\n */\nexport function toRecords(\n mapping: RestMapping,\n groups: readonly { readonly records: readonly unknown[]; readonly entity: string }[],\n state: RecordState,\n): PageRecords {\n const writer = new PageWriter(mapping, state);\n for (const g of groups) {\n writer.addRecords(g.records, g.entity);\n }\n return writer.finish();\n}\n","/**\n * Running a REST mapping (design section 13.2): `restSource(mapping, info)` turns one into a\n * `records` source with `expand` (breadth-first, batched `{ids}`, depth 0 hydrates), `probe` and\n * `validate`; the generic `rest` source takes the mapping as a parameter. Every request goes through\n * `ctx.fetch`, so the credential, retries, caps and coded errors are the framework's.\n */\n\nimport { type GraphSink } from \"@graphty/graph-format\";\n\nimport { throwIfAborted } from \"../../common/input.js\";\nimport { ImportError, type ImportReport } from \"../../types.js\";\nimport { sleep } from \"../context.js\";\nimport { originOf } from \"../credentials.js\";\nimport { defineSource } from \"../define.js\";\nimport { failAlone, failOn, warnOn } from \"../fail.js\";\nimport { REST_SOURCE_ID } from \"../ids.js\";\nimport {\n type ExpandRequest,\n type GraphSource,\n type RecordBatch,\n type SourceContext,\n type SourceCursor,\n type SourceDescriptor,\n type SourceFinish,\n type SourceFreshness,\n type SourceProbe,\n type SourceValidators,\n} from \"../types.js\";\nimport { REST_DESCRIPTOR } from \"./descriptor.js\";\nimport { checkRestMapping } from \"./mapping.js\";\nimport { firstPageUrl, nextPosition, type PagePosition, pageUrl } from \"./paging.js\";\nimport { type RestMapping, type RestParams, type RestRequest } from \"./params.js\";\nimport { newState, type PageRecords, type RecordState, toRecords } from \"./records.js\";\nimport { selectRecords } from \"./selectors.js\";\nimport { buildRequest, type TemplateValues } from \"./templates.js\";\n\n/** What a call runs: the mapping and the values its templates use. */\nexport interface RestPlan {\n /** The mapping. */\n readonly mapping: RestMapping;\n /** The template values. */\n readonly values: TemplateValues;\n}\n\n/** Why a plan is asked for: the values may differ (a validation selects only what it compares). */\nexport type RestPurpose = \"load\" | \"expand\" | \"probe\" | \"validate\";\n\n/** Turns a call's params into the plan it runs. */\ntype RestPlanner<P> = (params: P, ctx: SourceContext, purpose: RestPurpose) => RestPlan;\n\n/** Auth failures a later page may answer with, keeping the pages before it. */\nconst AUTH_CODES: ReadonlySet<string> = new Set([\"E_SOURCE_AUTH\", \"E_SOURCE_FORBIDDEN\"]);\n\n/** One page read. */\ninterface Page {\n readonly records: unknown[];\n readonly next: PagePosition;\n readonly headers: Headers;\n readonly status: number;\n}\n\n/**\n * How long until a budget resets.\n * @param reset - the reset header's number: past 1e9 an epoch in seconds, otherwise seconds from now\n * @returns milliseconds from now, never negative\n */\nfunction resetDelayMs(reset: number): number {\n return Math.max(0, reset > 1e9 ? reset * 1000 - Date.now() : reset * 1000);\n}\n\n/** One call's running state. */\nclass RestRun {\n readonly endpoint: URL;\n readonly facts: { budget?: SourceFinish[\"budget\"]; validators?: SourceValidators } = {};\n private last = 0;\n\n /**\n * Create one.\n * @param plan - the mapping and values\n * @param ctx - the context\n * @param paced - whether this run paces itself (the generic source, whose descriptor cannot)\n */\n constructor(\n readonly plan: RestPlan,\n readonly ctx: SourceContext,\n private readonly paced: boolean,\n ) {\n this.endpoint = new URL(plan.mapping.endpoint);\n if (ctx.endpoint !== null && originOf(ctx.endpoint) !== this.endpoint.origin) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"the endpoint is not the mapping's\", {\n name: \"endpoint\",\n reason: \"origin\",\n });\n }\n }\n\n /** Wait out the mapping's own rate limit (the generic source only). */\n private async pace(): Promise<void> {\n const rate = this.plan.mapping.rateLimit;\n if (!this.paced || rate === undefined) {\n return;\n }\n // ponytail: even spacing, one request at a time; a burst window is the descriptor's pacer\n const wait = this.last + rate.perMs / rate.requests - Date.now();\n if (wait > 0) {\n await sleep(wait, this.ctx.signal);\n }\n this.last = Date.now();\n }\n\n /**\n * Record the budget headers of a response.\n * @param headers - the response headers\n */\n private noteBudget(headers: Headers): void {\n const names = this.plan.mapping.budgetHeaders;\n const remaining = names === undefined ? null : headers.get(names.remaining);\n if (names === undefined || remaining === null || !Number.isFinite(Number(remaining))) {\n return;\n }\n const reset = names.reset === undefined ? null : Number(headers.get(names.reset) ?? Number.NaN);\n const resetMs = reset === null || !Number.isFinite(reset) ? undefined : resetDelayMs(reset);\n this.facts.budget = { remaining: Number(remaining), ...(resetMs === undefined ? {} : { resetMs }) };\n }\n\n /**\n * Read one page of a request.\n * @param name - the request name\n * @param values - the template values\n * @param position - the page's position, or undefined for the first page\n * @param headers - extra request headers (validation)\n * @returns the page\n */\n async read(\n name: string,\n values: TemplateValues,\n position: PagePosition | undefined,\n headers?: Record<string, string>,\n ): Promise<Page> {\n const request: RestRequest = this.plan.mapping.requests[name];\n const { report } = this.ctx;\n const built = buildRequest(this.endpoint, request, values, report);\n const url =\n position === undefined\n ? firstPageUrl(built.url, request.paging, this.endpoint, report)\n : pageUrl(built.url, request.paging, position, this.endpoint, report);\n await this.pace();\n const response = await this.ctx.fetch(url, {\n ...built.init,\n headers: { accept: \"application/json\", ...(built.init.headers as Record<string, string>), ...headers },\n allowStatus: [304],\n });\n this.noteBudget(response.headers);\n if (response.status === 304) {\n return { records: [], next: null, headers: response.headers, status: 304 };\n }\n const text = await response.text();\n let body: unknown;\n try {\n body = JSON.parse(text) as unknown;\n } catch {\n failOn(report, \"E_SOURCE_RESPONSE\", \"the response is not JSON\", {\n expected: \"json\",\n contentType: response.headers.get(\"content-type\"),\n });\n }\n const records = selectRecords(body, request.records);\n const here = position ?? null;\n const next = nextPosition(\n request.paging,\n position ?? (request.paging?.style === \"offset\" ? (request.paging.base ?? 0) : here),\n { body, headers: response.headers, url, records: records.length, runtime: this.ctx.runtime },\n this.endpoint,\n report,\n );\n return { records, next, headers: response.headers, status: response.status };\n }\n\n /**\n * Record what the facts say so far, so the report carries them even when a later page fails.\n * @param state - the load's record state\n * @param next - where to resume, for an expansion\n * @returns the report so far\n */\n finish(state: RecordState | null, next: SourceCursor | null = null): ImportReport {\n if (state?.modified !== null && state?.modified !== undefined) {\n this.facts.validators = { ...this.facts.validators, modified: state.modified };\n }\n return this.ctx.finish({ ...this.facts, next });\n }\n\n /**\n * Note the HTTP validators of a load's first response.\n * @param headers - its headers\n */\n noteValidators(headers: Headers): void {\n const etag = headers.get(\"etag\");\n const lastModified = headers.get(\"last-modified\");\n this.facts.validators = {\n ...this.facts.validators,\n ...(etag === null ? {} : { etag }),\n ...(lastModified === null ? {} : { lastModified }),\n };\n }\n\n /**\n * The graph facts of a first page.\n * @returns the meta\n */\n meta(): RecordBatch[\"meta\"] {\n const { directed } = this.plan.mapping;\n return directed === undefined ? undefined : { directed };\n }\n}\n\n/**\n * The template values of params: every string, number and boolean, as text.\n * @param params - the params\n * @param skip - a key to leave out\n * @returns the values\n */\nfunction stringValues(params: Readonly<Record<string, unknown>>, skip?: string): TemplateValues {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(params)) {\n if (k !== skip && (typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\")) {\n out[k] = String(v);\n }\n }\n return out;\n}\n\n/**\n * The load: the seed request once, then the load request page by page.\n * @param run - the call\n * @yields one page of nodes and edges\n */\nasync function* loadPages(run: RestRun): AsyncGenerator<RecordBatch> {\n const { mapping, values } = run.plan;\n const { cursor } = run.ctx;\n if (cursor !== null && cursor.r !== mapping.load) {\n failOn(run.ctx.report, \"E_SOURCE_PARAM\", \"the cursor is not this mapping's\", {\n name: \"cursor\",\n reason: \"stale-cursor\",\n });\n }\n const state = newState();\n const groups: { records: unknown[]; entity: string }[] = [];\n if (cursor === null && mapping.seed !== undefined) {\n const seed = await run.read(mapping.seed, values, undefined);\n groups.push({ records: seed.records, entity: mapping.requests[mapping.seed].entity });\n }\n const { entity } = mapping.requests[mapping.load];\n let position: PagePosition | undefined = cursor === null ? undefined : (cursor.at as PagePosition);\n let first = true;\n for (;;) {\n const page = await run.read(mapping.load, values, position);\n if (first && cursor === null) {\n run.noteValidators(page.headers);\n }\n const out = toRecords(mapping, [...groups.splice(0), { records: page.records, entity }], state);\n run.finish(state);\n const next = page.next === null ? null : { r: mapping.load, at: page.next };\n yield { nodes: out.nodes, edges: out.edges, next, meta: first ? run.meta() : undefined };\n if (page.next === null) {\n return;\n }\n first = false;\n position = page.next;\n }\n}\n\n/**\n * Write one page into a sink.\n * @param out - the page\n * @param sink - the sink\n * @param ctx - the context\n * @param types - the relationship types to keep, if any\n */\nfunction writePage(out: PageRecords, sink: GraphSink, ctx: SourceContext, types?: ReadonlySet<string>): void {\n const { report } = ctx;\n let n = 0;\n for (const { id, ...attrs } of out.nodes) {\n if (n++ % 64 === 0) {\n throwIfAborted(ctx.signal);\n }\n try {\n sink.addNodeRecord(id, attrs);\n report.counts.nodes++;\n } catch (err) {\n report.recordError(err, { element: String(id) });\n report.counts.skippedNodes++;\n }\n }\n for (const { source, target, ...attrs } of out.edges) {\n if (n++ % 64 === 0) {\n throwIfAborted(ctx.signal);\n }\n if (types !== undefined && !types.has(String(attrs.type))) {\n continue;\n }\n try {\n sink.addEdgeRecord(source, target, attrs);\n report.counts.edges++;\n } catch (err) {\n report.recordError(err, { element: `${String(source)} -> ${String(target)}` });\n report.counts.skippedEdges++;\n }\n }\n}\n\n/**\n * The requests an expansion runs for a direction; depth 0 hydrates.\n * @param mapping - the mapping\n * @param request - the expansion\n * @returns the request names\n */\nfunction expandRequests(mapping: RestMapping, request: ExpandRequest<unknown>): string[] {\n if (request.depth === 0) {\n return mapping.hydrate === undefined ? [] : [mapping.hydrate];\n }\n const { expand } = mapping;\n if (typeof expand === \"string\" || expand === undefined) {\n return expand === undefined ? [] : [expand];\n }\n const direction = request.direction ?? \"both\";\n const names = [direction !== \"out\" ? expand.in : undefined, direction !== \"in\" ? expand.out : undefined];\n return [...new Set(names.filter((n): n is string => n !== undefined))];\n}\n\n/**\n * Split ids into a request's batches.\n * @param ids - the ids\n * @param max - the batch size\n * @returns the batches\n */\nfunction batches(ids: readonly string[], max: number): string[][] {\n const out: string[][] = [];\n for (let i = 0; i < ids.length; i += max) {\n out.push(ids.slice(i, i + max));\n }\n return out;\n}\n\n/**\n * Breadth-first expansion: each hop runs the direction's requests with the frontier's ids in\n * `{ids}` batches; the nodes it adds are the next frontier. A capped first hop records where it\n * stopped, so expanding again continues from there.\n * @param run - the call\n * @param request - the seeds and how far to go\n * @param sink - where to write\n * @returns the report\n */\nasync function expandInto(run: RestRun, request: ExpandRequest<unknown>, sink: GraphSink): Promise<ImportReport> {\n return new Expansion(run, request, sink).expand();\n}\n\n/** Which batch of which request of which hop is being read. */\ninterface BatchAt {\n readonly hop: number;\n readonly x: number;\n readonly b: number;\n}\n\n/** One expansion's running state. */\nclass Expansion {\n private readonly mapping: RestMapping;\n private readonly names: string[];\n private readonly state: RecordState;\n private readonly types: ReadonlySet<string> | undefined;\n private added = 0;\n private wrote = false;\n\n /**\n * Check the expansion and set the sink's direction.\n * @param run - the call\n * @param request - the seeds and how far to go\n * @param sink - where to write\n */\n constructor(\n private readonly run: RestRun,\n private readonly request: ExpandRequest<unknown>,\n private readonly sink: GraphSink,\n ) {\n const { ctx } = run;\n this.mapping = run.plan.mapping;\n this.names = expandRequests(this.mapping, request);\n if (this.names.length === 0) {\n failOn(ctx.report, \"E_SOURCE_UNSUPPORTED\", \"the mapping has no request for this expansion\", {\n feature: request.depth === 0 ? \"hydrate\" : \"expand\",\n });\n }\n if (request.ids.length === 0) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"an expansion needs seed ids\", { name: \"ids\", reason: \"required\" });\n }\n this.state = newState([...request.ids.map(String), ...(request.exclude ?? []).map(String)]);\n this.types = request.relationshipTypes === undefined ? undefined : new Set(request.relationshipTypes);\n if (this.mapping.directed !== undefined && sink.edgeCount === 0) {\n sink.setDirected(this.mapping.directed);\n }\n }\n\n /**\n * Run every hop.\n * @returns the report\n */\n async expand(): Promise<ImportReport> {\n let frontier = this.request.ids.map(String);\n const depth = Math.max(1, this.request.depth ?? 1);\n for (let hop = 1; hop <= depth && frontier.length > 0; hop++) {\n const reached: string[] = [];\n const stop = await this.hop(hop, frontier, reached);\n if (stop !== null) {\n return stop;\n }\n frontier = [...new Set(reached)];\n }\n return this.run.finish(this.state, null);\n }\n\n /**\n * Run one hop: every request over every batch of the frontier.\n * @param hop - the hop, from 1\n * @param frontier - the ids this hop starts from\n * @param reached - collects the ids this hop adds\n * @returns the report when the expansion stopped, else null\n */\n private async hop(hop: number, frontier: readonly string[], reached: string[]): Promise<ImportReport | null> {\n for (const [x, name] of this.names.entries()) {\n const max = this.mapping.requests[name].batch?.max ?? 1;\n for (const [b, batch] of batches(frontier, max).entries()) {\n if (this.skipped({ hop, x, b })) {\n continue;\n }\n const stop = await this.readBatch({ hop, x, b }, name, batch, frontier, reached);\n if (stop !== null) {\n return stop;\n }\n }\n }\n return null;\n }\n\n /**\n * Whether a resumed first hop already read this batch.\n * @param at - the batch\n * @returns true to skip it\n */\n private skipped(at: BatchAt): boolean {\n const { hop, x, b } = at;\n const resume = this.run.ctx.cursor;\n if (hop !== 1 || resume === null) {\n return false;\n }\n const rx = Number(resume.x);\n return x < rx || (x === rx && b < Number(resume.b));\n }\n\n /**\n * Where a batch starts: the recorded position for the batch a first hop stopped in.\n * @param at - the batch\n * @returns the position, or undefined for the first page\n */\n private startPosition(at: BatchAt): PagePosition | undefined {\n const { hop, x, b } = at;\n const resume = this.run.ctx.cursor;\n return hop === 1 && resume !== null && x === Number(resume.x) && b === Number(resume.b)\n ? ((resume.at as PagePosition) ?? undefined)\n : undefined;\n }\n\n /**\n * Read one batch page by page.\n * @param at - the batch\n * @param name - the request\n * @param batch - its ids\n * @param frontier - the hop's ids\n * @param reached - collects the ids it adds\n * @returns the report when the expansion stopped, else null\n */\n private async readBatch(\n at: BatchAt,\n name: string,\n batch: readonly string[],\n frontier: readonly string[],\n reached: string[],\n ): Promise<ImportReport | null> {\n const r = this.mapping.requests[name];\n const own = { ...this.run.plan.values, id: batch[0], ids: batch.join(r.batch?.join ?? \",\") };\n let position = this.startPosition(at);\n for (;;) {\n let page: Page;\n try {\n page = await this.run.read(name, own, position);\n } catch (err) {\n return this.authStop(err, at.hop === 1 ? { x: at.x, b: at.b, at: position ?? null } : null);\n }\n this.writeNew(page, r.entity, reached);\n const stop = this.capStop(at, page, frontier);\n if (stop !== null || page.next === null) {\n return stop;\n }\n position = page.next;\n }\n }\n\n /**\n * Keep what was written when a later page needs a credential; rethrow anything else.\n * @param err - what the page threw\n * @param cursor - where to resume\n * @returns the report\n */\n private authStop(err: unknown, cursor: SourceCursor | null): ImportReport {\n if (!this.wrote || !(err instanceof ImportError) || !AUTH_CODES.has(String(err.issue?.code))) {\n throw err;\n }\n const p = err.issue?.params ?? {};\n warnOn(this.run.ctx.report, \"W_SOURCE_AUTH\", \"a later page needs a credential; the pages before it are kept\", {\n origin: typeof p.origin === \"string\" ? p.origin : this.run.endpoint.origin,\n status: typeof p.status === \"number\" ? p.status : null,\n });\n return this.run.finish(this.state, cursor);\n }\n\n /**\n * Write a page and collect the nodes it added.\n * @param page - the page\n * @param entity - its records' entity\n * @param reached - collects the ids it adds\n */\n private writeNew(page: Page, entity: string, reached: string[]): void {\n const { state } = this;\n const before = new Set([...state.full, ...state.stubs]);\n const out = toRecords(this.mapping, [{ records: page.records, entity }], state);\n writePage(out, this.sink, this.run.ctx, this.types);\n this.wrote = true;\n for (const node of out.nodes) {\n const id = String(node.id);\n if (!before.has(id) && !state.known.has(id)) {\n reached.push(id);\n this.added++;\n }\n }\n }\n\n /**\n * Stop at the expansion's limit or the load's caps.\n * @param at - the batch\n * @param page - the page just written\n * @param frontier - the hop's ids\n * @returns the report when a cap was reached, else null\n */\n private capStop(at: BatchAt, page: Page, frontier: readonly string[]): ImportReport | null {\n const { hop, x, b } = at;\n const { ctx } = this.run;\n const limited = this.request.limit !== undefined && this.added >= this.request.limit;\n if (limited) {\n warnOn(ctx.report, \"W_SOURCE_LIMIT\", \"the expansion reached its limit\", {\n limit: \"limit\",\n value: this.added,\n });\n }\n if (!limited && !ctx.limits.reached()) {\n return null;\n }\n const more = page.next === null ? null : { x, b, at: page.next };\n // ponytail: only a capped first hop can resume; a deeper hop's frontier is not recorded\n return this.run.finish(\n this.state,\n hop === 1 ? (more ?? nextBatch(x, b, this.names, frontier, this.mapping)) : null,\n );\n }\n}\n\n/**\n * Where a first hop continues after a batch that ended on a cap.\n * @param x - the request index\n * @param b - the batch index\n * @param names - the requests\n * @param frontier - the seeds\n * @param mapping - the mapping\n * @returns the cursor, or null when nothing is left\n */\nfunction nextBatch(\n x: number,\n b: number,\n names: readonly string[],\n frontier: readonly string[],\n mapping: RestMapping,\n): SourceCursor | null {\n const count = Math.ceil(frontier.length / (mapping.requests[names[x]].batch?.max ?? 1));\n if (b + 1 < count) {\n return { x, b: b + 1, at: null };\n }\n return x + 1 < names.length ? { x: x + 1, b: 0, at: null } : null;\n}\n\n/**\n * Whether data loaded earlier changed: the load's first page (with the seed), sent with the\n * recorded HTTP validators; a 304 or an equal ETag is current, else the newest modification time\n * is compared.\n * @param run - the call\n * @param seen - the validators recorded then\n * @returns the freshness\n */\nasync function validateRun(run: RestRun, seen: SourceValidators): Promise<SourceFreshness> {\n const { mapping, values } = run.plan;\n const headers: Record<string, string> = {};\n if (seen.etag !== undefined) {\n headers[\"if-none-match\"] = seen.etag;\n }\n if (seen.lastModified !== undefined) {\n headers[\"if-modified-since\"] = seen.lastModified;\n }\n const state = newState();\n const groups: { records: unknown[]; entity: string }[] = [];\n if (mapping.seed !== undefined) {\n const seed = await run.read(mapping.seed, values, undefined);\n groups.push({ records: seed.records, entity: mapping.requests[mapping.seed].entity });\n }\n const page = await run.read(mapping.load, values, undefined, headers);\n if (page.status === 304) {\n return { status: \"current\", via: seen.etag === undefined ? \"modified\" : \"etag\", validators: seen };\n }\n toRecords(mapping, [...groups, { records: page.records, entity: mapping.requests[mapping.load].entity }], state);\n run.noteValidators(page.headers);\n const now: SourceValidators = {\n ...run.facts.validators,\n ...(state.modified === null ? {} : { modified: state.modified }),\n };\n if (seen.etag !== undefined && now.etag !== undefined) {\n return { status: seen.etag === now.etag ? \"current\" : \"changed\", via: \"etag\", validators: now };\n }\n if (seen.modified !== undefined && now.modified !== undefined) {\n return now.modified > seen.modified\n ? { status: \"changed\", via: \"modified\", changedAt: now.modified, validators: now }\n : { status: \"current\", via: \"modified\", validators: now };\n }\n return { status: \"unverifiable\", validators: now };\n}\n\n/**\n * The methods of a source that runs plans.\n * @param plan - turns params into the plan\n * @param paced - whether the run paces itself\n * @returns records, expand, probe and validate\n */\nexport function restMethods<P>(\n plan: RestPlanner<P>,\n paced: boolean,\n): Pick<Required<GraphSource<P>>, \"expand\" | \"probe\" | \"validate\"> & {\n records: (params: P, ctx: SourceContext) => AsyncIterable<RecordBatch>;\n} {\n return {\n records: (params, ctx) => loadPages(new RestRun(plan(params, ctx, \"load\"), ctx, paced)),\n expand: (request, sink, ctx) =>\n expandInto(new RestRun(plan(request.params, ctx, \"expand\"), ctx, paced), request, sink),\n async probe(params, ctx): Promise<SourceProbe> {\n const run = new RestRun(plan(params, ctx, \"probe\"), ctx, paced);\n const page = await run.read(run.plan.mapping.load, run.plan.values, undefined);\n if (page.records.length === 0 && page.status !== 304) {\n failOn(ctx.report, \"E_SOURCE_NOT_FOUND\", \"the load request found no records\", {\n what: \"records\",\n value: run.plan.mapping.load,\n });\n }\n return { ok: true };\n },\n validate: (params, seen, ctx) => validateRun(new RestRun(plan(params, ctx, \"validate\"), ctx, paced), seen),\n };\n}\n\n/**\n * The plan of a mapping given as data, after it is checked.\n * @param mapping - the mapping\n * @param ctx - the context\n * @returns the mapping, checked\n */\nfunction checkedMapping(mapping: unknown, ctx: SourceContext): RestMapping {\n const [issue] = checkRestMapping(mapping);\n if (issue !== undefined) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", `the mapping is invalid at ${issue.at}`, {\n name: \"mapping\",\n reason: issue.code,\n at: issue.at,\n });\n }\n return mapping as RestMapping;\n}\n\n/**\n * What `restSource` needs beside the mapping: the source id and any descriptor fields to set.\n * Experimental.\n * @category Network sources\n */\nexport type RestSourceInfo = {\n /** The source id: lowercase letters, digits and dashes. */\n readonly id: string;\n} & Partial<SourceDescriptor>;\n\n/**\n * Where a mapping's API key goes, as a descriptor says it.\n * @param auth - the mapping's auth\n * @returns `{ apiKey }`, or nothing when the mapping takes no key or does not say where\n */\nfunction apiKeyOf(auth: RestMapping[\"auth\"]): Pick<SourceDescriptor, \"apiKey\"> {\n if (auth?.kind !== \"api-key\") {\n return {};\n }\n if (auth.header !== undefined) {\n return { apiKey: { header: auth.header } };\n }\n return auth.query === undefined ? {} : { apiKey: { query: auth.query } };\n}\n\n/**\n * Turn a REST mapping into a source: a `records` source that loads the mapping's `load` request\n * page by page, with `expand` (breadth-first over the `expand` requests, `{ids}` batched; depth 0\n * fetches the seeds' own records through `hydrate`), `probe` and `validate`. The descriptor is\n * derived from the mapping (its endpoint, params, auth and rate limit), and `info` may set any of\n * its fields. A mapping with a problem is refused: E_SOURCE_INVALID with `reason: \"mapping\"`.\n * Experimental.\n * @param mapping - the mapping\n * @param info - the id and descriptor fields\n * @returns the source\n * @example\n * ```ts\n * const people = restSource(mapping, { id: \"people\", plainName: \"People\" });\n * registerSource(people);\n * const { snapshot } = await loadFromSource(\"people\", { team: \"core\" });\n * ```\n * @category Network sources\n */\nexport function restSource(mapping: RestMapping, info: RestSourceInfo): GraphSource<Readonly<Record<string, unknown>>> {\n const [issue] = checkRestMapping(mapping);\n if (issue !== undefined) {\n failAlone(\"E_SOURCE_INVALID\", `the mapping of ${info.id} is invalid at ${issue.at}`, {\n id: info.id,\n reason: \"mapping\",\n at: issue.at,\n });\n }\n const { id, ...fields } = info;\n const auth = mapping.auth === undefined ? [] : [mapping.auth.kind];\n const descriptor: SourceDescriptor = Object.freeze({\n plainName: id,\n kind: \"rest\",\n params: mapping.params ?? [],\n defaultEndpoint: mapping.endpoint,\n auth,\n authRequired: auth.length === 0 ? \"none\" : \"optional\",\n ...apiKeyOf(mapping.auth),\n ...(mapping.rateLimit === undefined ? {} : { rateLimit: mapping.rateLimit }),\n ...fields,\n });\n return defineSource<Readonly<Record<string, unknown>>>({\n id,\n descriptor,\n ...restMethods((params) => ({ mapping, values: stringValues(params) }), false),\n });\n}\n\n/**\n * The generic REST mapping source: `params.mapping` says how to read the API, and the other params\n * fill its templates. The mapping is checked before any request (E_SOURCE_PARAM, `name:\n * \"mapping\"`, `reason` the problem's code, `at` where it is). With a credential, pass the mapping's\n * endpoint as `endpoint`, so the credential is bound to it. Experimental.\n * @category Network sources\n */\nexport const restMappingSource: GraphSource<RestParams> = defineSource<RestParams>({\n id: REST_SOURCE_ID,\n descriptor: REST_DESCRIPTOR,\n ...restMethods<RestParams>(\n (params, ctx) => ({ mapping: checkedMapping(params.mapping, ctx), values: stringValues(params, \"mapping\") }),\n true,\n ),\n});\n","/**\n * The `openalex` preset of the REST mapping (design section 13.3): OpenAlex's citation graph\n * around a work, or its co-authorship graph around an author, as a mapping the generic engine runs.\n * The seed's own record comes first; citing works page by cursor; referenced works are stubs until\n * hydrated or expanded. Freshness is the newest `updated_date`.\n */\n\nimport { defineSource } from \"../define.js\";\nimport { failOn } from \"../fail.js\";\nimport { OPENALEX_SOURCE_ID } from \"../ids.js\";\nimport { type GraphSource, type SourceContext } from \"../types.js\";\nimport { OPENALEX_DESCRIPTOR } from \"./descriptor.js\";\nimport { type OpenAlexParams, type RestEntity, type RestMapping } from \"./params.js\";\nimport { restMethods, type RestPlan, type RestPurpose } from \"./source.js\";\n\n/** OpenAlex ids are URLs under this prefix. */\nconst PREFIX = \"https://openalex.org/\";\n\n/** The work fields every citation load selects. */\nconst WORK_FIELDS = \"id,display_name,publication_year,cited_by_count,updated_date,referenced_works\";\n\n/**\n * A list request over works, `{ids}` batched 50 at a time and joined by `|`.\n * @param filter - the filter template\n * @param perPage - the page size\n * @param paged - whether it pages by cursor\n * @returns the request\n */\nfunction works(filter: string, perPage: string, paged: boolean): RestMapping[\"requests\"][string] {\n return {\n path: \"/works\",\n query: { filter, \"per-page\": perPage, select: \"{select}\" },\n batch: { max: 50, join: \"|\" },\n records: \"results\",\n entity: \"work\",\n ...(paged ? { paging: { style: \"cursor\", param: \"cursor\", first: \"*\", next: \"meta.next_cursor\" } } : {}),\n };\n}\n\n/** An entity known by its OpenAlex id and display name. */\nconst named: RestEntity = { id: \"id\", stripPrefix: PREFIX, fields: { name: \"display_name\" } };\n\n/**\n * OpenAlex's citation graph as a mapping: the seed work (`{ids}`), the works citing it page by page,\n * each work's references as `cites` edges, and, when `{select}` asks for `authorships` and\n * `topics`, the authors, their institutions and the topics as nodes. Fill `{ids}` with work ids\n * and `{select}` with the fields to read. The `openalex` source chooses both from its params and\n * leaves out the rules for what is not included. Experimental.\n * @category Network sources\n */\nexport const OPENALEX_MAPPING: RestMapping = Object.freeze<RestMapping>({\n version: 1,\n endpoint: \"https://api.openalex.org\",\n load: \"citing\",\n seed: \"by-id\",\n expand: { in: \"citing\", out: \"by-id\" },\n hydrate: \"by-id\",\n directed: true,\n modified: \"updated_date\",\n auth: { kind: \"api-key\", query: \"api_key\" },\n rateLimit: { requests: 10, perMs: 1000 },\n budgetHeaders: { remaining: \"x-ratelimit-remaining\", reset: \"x-ratelimit-reset\" },\n requests: {\n citing: works(\"cites:{ids}\", \"200\", true),\n \"by-id\": works(\"openalex:{ids}\", \"50\", false),\n authored: works(\"authorships.author.id:{ids}\", \"200\", true),\n \"authors-by-id\": {\n path: \"/authors\",\n query: { filter: \"openalex:{ids}\", \"per-page\": \"50\", select: \"id,display_name\" },\n batch: { max: 50, join: \"|\" },\n records: \"results\",\n entity: \"author\",\n },\n },\n entities: {\n work: {\n id: \"id\",\n stripPrefix: PREFIX,\n fields: {\n title: \"display_name\",\n year: \"publication_year\",\n citedBy: \"cited_by_count\",\n updated: \"updated_date\",\n },\n edges: [\n { to: \"referenced_works[]\", type: \"cites\", entity: \"work\" },\n { to: \"authorships[].author.id\", type: \"authored_by\", entity: \"author\" },\n {\n each: \"authorships[]\",\n from: \"author.id\",\n to: \"institutions[].id\",\n type: \"affiliated_with\",\n entity: \"institution\",\n },\n { to: \"topics[].id\", type: \"has_topic\", entity: \"topic\" },\n ],\n embedded: [\n { at: \"authorships[].author\", entity: \"author\" },\n { at: \"authorships[].institutions[]\", entity: \"institution\" },\n { at: \"topics[]\", entity: \"topic\" },\n ],\n },\n author: named,\n institution: named,\n topic: named,\n },\n});\n\n/** What `include` may hold. */\ntype Include = \"authors\" | \"institutions\" | \"topics\";\n\n/**\n * The included kinds, from an array or a comma-separated string.\n * @param include - the param\n * @returns the set\n */\nfunction includes(include: unknown): Set<Include> {\n const list: unknown[] = typeof include === \"string\" ? include.split(\",\") : [];\n if (Array.isArray(include)) {\n list.push(...(include as unknown[]));\n }\n const out = new Set(list.map((v) => String(v).trim()).filter((v) => v !== \"\") as Include[]);\n if (out.has(\"institutions\")) {\n // an institution hangs off an author, so it brings its authors\n out.add(\"authors\");\n }\n return out;\n}\n\n/**\n * The citation mapping without the rules for what is not included.\n * @param include - what is included\n * @returns the mapping\n */\nfunction citationMapping(include: ReadonlySet<Include>): RestMapping {\n const { work } = OPENALEX_MAPPING.entities;\n const keepEdge = (type: string): boolean =>\n type === \"cites\" ||\n (type === \"authored_by\" && include.has(\"authors\")) ||\n (type === \"affiliated_with\" && include.has(\"institutions\")) ||\n (type === \"has_topic\" && include.has(\"topics\"));\n const keepEmbedded = (entity: string): boolean => include.has(`${entity}s` as Include);\n return {\n ...OPENALEX_MAPPING,\n entities: {\n ...OPENALEX_MAPPING.entities,\n work: {\n ...work,\n edges: work.edges?.filter((e) => keepEdge(e.type)),\n embedded: work.embedded?.filter((e) => keepEmbedded(e.entity)),\n },\n },\n };\n}\n\n/**\n * The co-authorship mapping: works are containers, every two authors of one work are joined by a\n * `coauthor` edge, and an author expands through the works they wrote.\n * @param include - what is included\n * @param seedIsWork - whether the load starts from a work\n * @returns the mapping\n */\nfunction coauthorshipMapping(include: ReadonlySet<Include>, seedIsWork: boolean): RestMapping {\n const institutions = include.has(\"institutions\");\n return {\n ...OPENALEX_MAPPING,\n load: seedIsWork ? \"by-id\" : \"authored\",\n seed: undefined,\n expand: \"authored\",\n hydrate: \"authors-by-id\",\n directed: false,\n entities: {\n ...OPENALEX_MAPPING.entities,\n work: {\n id: \"id\",\n // a rule's `from` is read with the record's own prefix\n stripPrefix: PREFIX,\n node: false,\n edges: [\n { pairs: \"authorships[].author.id\", type: \"coauthor\", entity: \"author\" },\n ...(institutions\n ? [\n {\n each: \"authorships[]\",\n from: \"author.id\",\n to: \"institutions[].id\",\n type: \"affiliated_with\",\n entity: \"institution\",\n },\n ]\n : []),\n ],\n embedded: [\n { at: \"authorships[].author\", entity: \"author\" },\n ...(institutions ? [{ at: \"authorships[].institutions[]\", entity: \"institution\" }] : []),\n ],\n },\n },\n };\n}\n\n/**\n * An OpenAlex id param: `W123` or its URL form, checked so a value cannot add a filter.\n * @param value - the param\n * @param name - its name\n * @param letter - the id's kind letter\n * @param ctx - the context\n * @returns the bare id\n */\nfunction openalexId(value: unknown, name: string, letter: string, ctx: SourceContext): string {\n const text = typeof value === \"string\" ? value.trim().replace(PREFIX, \"\") : \"\";\n if (!new RegExp(String.raw`^${letter}\\d+$`, \"i\").test(text)) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", `${name} is not an OpenAlex id`, { name, reason: \"format\" });\n }\n return text.toUpperCase();\n}\n\n/**\n * The plan of an OpenAlex call.\n * @param params - the params\n * @param ctx - the context\n * @param purpose - what the plan is for\n * @returns the mapping and values\n */\nfunction plan(params: OpenAlexParams, ctx: SourceContext, purpose: RestPurpose): RestPlan {\n const graph = params.graph ?? \"citation\";\n const include = includes(params.include);\n const hasWork = params.work !== undefined && params.work !== \"\";\n const hasAuthor = params.author !== undefined && params.author !== \"\";\n if (purpose !== \"expand\" && hasWork === hasAuthor) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"give exactly one of work and author\", {\n name: \"work\",\n reason: hasWork ? \"exclusive\" : \"required\",\n });\n }\n let seed = \"\";\n if (hasWork) {\n seed = openalexId(params.work, \"work\", \"W\", ctx);\n } else if (hasAuthor) {\n seed = openalexId(params.author, \"author\", \"A\", ctx);\n }\n if (graph === \"coauthorship\") {\n return {\n mapping: coauthorshipMapping(include, hasWork),\n values: { ids: seed, select: purpose === \"validate\" ? \"id,updated_date\" : \"id,updated_date,authorships\" },\n };\n }\n let select =\n WORK_FIELDS + (include.has(\"authors\") ? \",authorships\" : \"\") + (include.has(\"topics\") ? \",topics\" : \"\");\n if (purpose === \"validate\") {\n select = \"id,updated_date\";\n }\n const mapping = citationMapping(include);\n return {\n mapping: hasWork ? mapping : { ...mapping, load: \"authored\", seed: undefined },\n values: { ids: seed, select },\n };\n}\n\n/** OpenAlex's own ids: a kind letter and digits. */\nconst ANY_ID = /^[WAIT]\\d+$/;\n\nconst methods = restMethods<OpenAlexParams>(plan, false);\n\n/**\n * The OpenAlex preset (https://openalex.org): `work` (the citation graph around a work, default)\n * or `author` (the works they wrote), `graph: \"coauthorship\"` for authors joined by shared works,\n * and `include` (`\"authors\"`, `\"institutions\"`, `\"topics\"`) for more node kinds. Without a key,\n * the first page loads and a later one warns W_SOURCE_AUTH with `report.source.next`; pass\n * `credentials.apiKey({ query: \"api_key\" }, key)` and continue with the cursor. Experimental.\n * @category Network sources\n */\nexport const openalexSource: GraphSource<OpenAlexParams> = defineSource<OpenAlexParams>({\n id: OPENALEX_SOURCE_ID,\n descriptor: OPENALEX_DESCRIPTOR,\n ...methods,\n expand(request, sink, ctx) {\n for (const id of request.ids) {\n if (!ANY_ID.test(String(id))) {\n failOn(ctx.report, \"E_SOURCE_PARAM\", \"an expansion seed is not an OpenAlex id\", {\n name: \"ids\",\n reason: \"format\",\n });\n }\n }\n return methods.expand(request, sink, ctx);\n },\n});\n"],"names":["plan","select"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from "./src/sources/sparql/index.js";