@graphty/graph-io 0.3.48 → 0.3.50
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.
- package/dist/chunks/{approximations-C2riR4NT.js → approximations-BRXsll0T.js} +2 -2
- package/dist/chunks/{approximations-C2riR4NT.js.map → approximations-BRXsll0T.js.map} +1 -1
- package/dist/chunks/bends-BGXjv_U4.js +129 -0
- package/dist/chunks/bends-BGXjv_U4.js.map +1 -0
- package/dist/chunks/{block-Cu22ewuS.js → block-yl0f_qLO.js} +931 -164
- package/dist/chunks/block-yl0f_qLO.js.map +1 -0
- package/dist/chunks/choose-CczZJaX_.js +717 -0
- package/dist/chunks/choose-CczZJaX_.js.map +1 -0
- package/dist/chunks/{codes-CV_Bhcyi.js → codes-BE2xir2k.js} +6 -2
- package/dist/chunks/codes-BE2xir2k.js.map +1 -0
- package/dist/chunks/{constants-D0LqcsLJ.js → constants-CKkYLPtt.js} +2 -2
- package/dist/chunks/{constants-D0LqcsLJ.js.map → constants-CKkYLPtt.js.map} +1 -1
- package/dist/chunks/{context-cgmmOxZ2.js → context-DizmppHy.js} +5 -4
- package/dist/chunks/{context-cgmmOxZ2.js.map → context-DizmppHy.js.map} +1 -1
- package/dist/chunks/{convert-BcQ8_jMo.js → convert-Ct2zelbQ.js} +7 -2
- package/dist/chunks/convert-Ct2zelbQ.js.map +1 -0
- package/dist/chunks/{credentials-BiQsnMTb.js → credentials-CmvJXYeH.js} +67 -16
- package/dist/chunks/credentials-CmvJXYeH.js.map +1 -0
- package/dist/chunks/{cx-export-BEeF6ymo.js → cx-export-Bt6NoqTQ.js} +3 -3
- package/dist/chunks/{cx-export-BEeF6ymo.js.map → cx-export-Bt6NoqTQ.js.map} +1 -1
- package/dist/chunks/descriptor-B28U25x4.js +60 -0
- package/dist/chunks/descriptor-B28U25x4.js.map +1 -0
- package/dist/chunks/{descriptor-BJ-W0Jd-.js → descriptor-Dhez_Cew.js} +11 -2
- package/dist/chunks/descriptor-Dhez_Cew.js.map +1 -0
- package/dist/chunks/{emit-CD8xnY8s.js → emit-7Jkpg0yd.js} +1788 -133
- package/dist/chunks/emit-7Jkpg0yd.js.map +1 -0
- package/dist/chunks/{escape-DH2Egt-l.js → escape-CuCIzNMB.js} +8 -8
- package/dist/chunks/{escape-DH2Egt-l.js.map → escape-CuCIzNMB.js.map} +1 -1
- package/dist/chunks/{export-CZ7VRm4I.js → export-Cha4dRFz.js} +45 -387
- package/dist/chunks/export-Cha4dRFz.js.map +1 -0
- package/dist/chunks/{exporter-ChjL5fmP.js → exporter-1Ajud15J.js} +9 -8
- package/dist/chunks/{exporter-ChjL5fmP.js.map → exporter-1Ajud15J.js.map} +1 -1
- package/dist/chunks/{exporter-BIdaoIgh.js → exporter-B6yvL3wy.js} +7 -7
- package/dist/chunks/{exporter-BIdaoIgh.js.map → exporter-B6yvL3wy.js.map} +1 -1
- package/dist/chunks/{exporter-Dcw7Ldtq.js → exporter-BP6otMO6.js} +6 -6
- package/dist/chunks/{exporter-Dcw7Ldtq.js.map → exporter-BP6otMO6.js.map} +1 -1
- package/dist/chunks/{exporter-DtVU80Fa.js → exporter-CA5q8ROP.js} +9 -8
- package/dist/chunks/{exporter-DtVU80Fa.js.map → exporter-CA5q8ROP.js.map} +1 -1
- package/dist/chunks/{exporter-bxxjOrDZ.js → exporter-CQQZFJ2v.js} +1284 -156
- package/dist/chunks/exporter-CQQZFJ2v.js.map +1 -0
- package/dist/chunks/format-BXiAb-1h.js +408 -0
- package/dist/chunks/format-BXiAb-1h.js.map +1 -0
- package/dist/chunks/{generic-CP6YD34u.js → generic-Dc21MAdg.js} +387 -31
- package/dist/chunks/generic-Dc21MAdg.js.map +1 -0
- package/dist/chunks/{importer-B87_fmVx.js → importer-C6NVpCXp.js} +327 -84
- package/dist/chunks/importer-C6NVpCXp.js.map +1 -0
- package/dist/chunks/{importer-DPZDN40-.js → importer-CKFe4q54.js} +25 -17
- package/dist/chunks/importer-CKFe4q54.js.map +1 -0
- package/dist/chunks/{importer-Bji2MeWr.js → importer-CKbUbsJA.js} +13 -10
- package/dist/chunks/{importer-Bji2MeWr.js.map → importer-CKbUbsJA.js.map} +1 -1
- package/dist/chunks/{importer-CB_zV5_L.js → importer-ClCsdgTJ.js} +208 -1104
- package/dist/chunks/importer-ClCsdgTJ.js.map +1 -0
- package/dist/chunks/{importer-e3huMZbm.js → importer-CyVZTrf0.js} +14 -10
- package/dist/chunks/importer-CyVZTrf0.js.map +1 -0
- package/dist/chunks/{importer-CVT-JyDE.js → importer-DgG4v1Ms.js} +1537 -355
- package/dist/chunks/importer-DgG4v1Ms.js.map +1 -0
- package/dist/chunks/{importer-Cyy6UseH.js → importer-asFUrIsj.js} +66 -13
- package/dist/chunks/importer-asFUrIsj.js.map +1 -0
- package/dist/chunks/{input-Ccg9I22A.js → input-CAxt_aV-.js} +4 -4
- package/dist/chunks/{input-Ccg9I22A.js.map → input-CAxt_aV-.js.map} +1 -1
- package/dist/chunks/{json-elements-By172SVq.js → json-elements-Cq76WjnZ.js} +4 -4
- package/dist/chunks/{json-elements-By172SVq.js.map → json-elements-Cq76WjnZ.js.map} +1 -1
- package/dist/chunks/{lexicon-u2SI5xcx.js → lexicon-IVRq2Uoo.js} +282 -74
- package/dist/chunks/lexicon-IVRq2Uoo.js.map +1 -0
- package/dist/chunks/{ontology-export-BwgMyuF0.js → ontology-export-OMo91mb0.js} +4 -4
- package/dist/chunks/{ontology-export-BwgMyuF0.js.map → ontology-export-OMo91mb0.js.map} +1 -1
- package/dist/chunks/{records-Cgvxz-Vx.js → records-NJiYvekn.js} +2 -2
- package/dist/chunks/{records-Cgvxz-Vx.js.map → records-NJiYvekn.js.map} +1 -1
- package/dist/chunks/{report-CgdsL9Hb.js → report-CwMfYa9J.js} +23 -23
- package/dist/chunks/{report-CgdsL9Hb.js.map → report-CwMfYa9J.js.map} +1 -1
- package/dist/chunks/round-trip-Cy3_SHRZ.js +79 -0
- package/dist/chunks/round-trip-Cy3_SHRZ.js.map +1 -0
- package/dist/chunks/{sigv4-LkAzsLAu.js → sigv4-BXwVbza3.js} +5 -5
- package/dist/chunks/sigv4-BXwVbza3.js.map +1 -0
- package/dist/chunks/{styles-CaABMoO1.js → styles-CAVmBLgp.js} +1237 -138
- package/dist/chunks/styles-CAVmBLgp.js.map +1 -0
- package/dist/chunks/styles-CPczw1Jz.js +1928 -0
- package/dist/chunks/styles-CPczw1Jz.js.map +1 -0
- package/dist/chunks/styles-boK6Ln54.js +2847 -0
- package/dist/chunks/styles-boK6Ln54.js.map +1 -0
- package/dist/chunks/{styles-yed-Cs1nmrjn.js → styles-yed-XeFBQ6VS.js} +506 -175
- package/dist/chunks/styles-yed-XeFBQ6VS.js.map +1 -0
- package/dist/chunks/{text-BuKQVMz2.js → text-ystE2bYi.js} +2 -2
- package/dist/chunks/{text-BuKQVMz2.js.map → text-ystE2bYi.js.map} +1 -1
- package/dist/csv.js +7 -7
- package/dist/cx.js +2 -2
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +8 -4
- package/dist/dot.js.map +1 -1
- package/dist/gexf.js +42 -12
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +848 -194
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +230 -193
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +3 -3
- package/dist/json.js +3 -2
- package/dist/neo4j.js +6 -6
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/positions.js +45 -3
- package/dist/positions.js.map +1 -1
- package/dist/sources-cypher.js +141 -23
- package/dist/sources-cypher.js.map +1 -1
- package/dist/sources-ndex.js +2 -2
- package/dist/sources-rest.js +32 -6
- package/dist/sources-rest.js.map +1 -1
- package/dist/sources-sparql.d.ts +1 -0
- package/dist/sources-sparql.js +439 -0
- package/dist/sources-sparql.js.map +1 -0
- package/dist/src/formats/cx/importer.d.ts.map +1 -1
- package/dist/src/formats/cx/importer.js +5 -1
- package/dist/src/formats/cx/importer.js.map +1 -1
- package/dist/src/formats/cx/styles.d.ts +24 -1
- package/dist/src/formats/cx/styles.d.ts.map +1 -1
- package/dist/src/formats/cx/styles.js +117 -11
- package/dist/src/formats/cx/styles.js.map +1 -1
- package/dist/src/formats/cx2/importer.d.ts.map +1 -1
- package/dist/src/formats/cx2/importer.js +1 -0
- package/dist/src/formats/cx2/importer.js.map +1 -1
- package/dist/src/formats/cx2/styles.d.ts.map +1 -1
- package/dist/src/formats/cx2/styles.js +3 -1
- package/dist/src/formats/cx2/styles.js.map +1 -1
- package/dist/src/formats/cys/importer.d.ts.map +1 -1
- package/dist/src/formats/cys/importer.js +1 -0
- package/dist/src/formats/cys/importer.js.map +1 -1
- package/dist/src/formats/cys/styles.d.ts +2 -0
- package/dist/src/formats/cys/styles.d.ts.map +1 -1
- package/dist/src/formats/cys/styles.js +15 -7
- package/dist/src/formats/cys/styles.js.map +1 -1
- package/dist/src/formats/dot/drawing.d.ts +98 -0
- package/dist/src/formats/dot/drawing.d.ts.map +1 -0
- package/dist/src/formats/dot/drawing.js +734 -0
- package/dist/src/formats/dot/drawing.js.map +1 -0
- package/dist/src/formats/dot/exporter.d.ts.map +1 -1
- package/dist/src/formats/dot/exporter.js +34 -2
- package/dist/src/formats/dot/exporter.js.map +1 -1
- package/dist/src/formats/dot/importer.d.ts +6 -1
- package/dist/src/formats/dot/importer.d.ts.map +1 -1
- package/dist/src/formats/dot/importer.js +170 -33
- package/dist/src/formats/dot/importer.js.map +1 -1
- package/dist/src/formats/dot/index.d.ts +3 -1
- package/dist/src/formats/dot/index.d.ts.map +1 -1
- package/dist/src/formats/dot/index.js +2 -1
- package/dist/src/formats/dot/index.js.map +1 -1
- package/dist/src/formats/dot/label-places.d.ts +41 -0
- package/dist/src/formats/dot/label-places.d.ts.map +1 -0
- package/dist/src/formats/dot/label-places.js +185 -0
- package/dist/src/formats/dot/label-places.js.map +1 -0
- package/dist/src/formats/dot/names.d.ts +13 -0
- package/dist/src/formats/dot/names.d.ts.map +1 -1
- package/dist/src/formats/dot/names.js +13 -0
- package/dist/src/formats/dot/names.js.map +1 -1
- package/dist/src/formats/dot/record.d.ts +50 -0
- package/dist/src/formats/dot/record.d.ts.map +1 -0
- package/dist/src/formats/dot/record.js +275 -0
- package/dist/src/formats/dot/record.js.map +1 -0
- package/dist/src/formats/dot/styles.d.ts +72 -2
- package/dist/src/formats/dot/styles.d.ts.map +1 -1
- package/dist/src/formats/dot/styles.js +1500 -119
- package/dist/src/formats/dot/styles.js.map +1 -1
- package/dist/src/formats/gexf/dialog-metrics.d.ts +15 -0
- package/dist/src/formats/gexf/dialog-metrics.d.ts.map +1 -0
- package/dist/src/formats/gexf/dialog-metrics.js +59 -0
- package/dist/src/formats/gexf/dialog-metrics.js.map +1 -0
- package/dist/src/formats/gexf/importer.d.ts +7 -0
- package/dist/src/formats/gexf/importer.d.ts.map +1 -1
- package/dist/src/formats/gexf/importer.js +41 -5
- package/dist/src/formats/gexf/importer.js.map +1 -1
- package/dist/src/formats/gexf/preview.d.ts +77 -0
- package/dist/src/formats/gexf/preview.d.ts.map +1 -0
- package/dist/src/formats/gexf/preview.js +191 -0
- package/dist/src/formats/gexf/preview.js.map +1 -0
- package/dist/src/formats/gexf/schema.d.ts.map +1 -1
- package/dist/src/formats/gexf/schema.js +2 -1
- package/dist/src/formats/gexf/schema.js.map +1 -1
- package/dist/src/formats/gexf/styles.d.ts +58 -31
- package/dist/src/formats/gexf/styles.d.ts.map +1 -1
- package/dist/src/formats/gexf/styles.js +848 -225
- package/dist/src/formats/gexf/styles.js.map +1 -1
- package/dist/src/formats/gml/importer.d.ts +5 -2
- package/dist/src/formats/gml/importer.d.ts.map +1 -1
- package/dist/src/formats/gml/importer.js +258 -71
- package/dist/src/formats/gml/importer.js.map +1 -1
- package/dist/src/formats/gml/index.d.ts +1 -1
- package/dist/src/formats/gml/index.d.ts.map +1 -1
- package/dist/src/formats/gml/index.js +1 -1
- package/dist/src/formats/gml/index.js.map +1 -1
- package/dist/src/formats/gml/positions.d.ts +7 -0
- package/dist/src/formats/gml/positions.d.ts.map +1 -1
- package/dist/src/formats/gml/positions.js +29 -7
- package/dist/src/formats/gml/positions.js.map +1 -1
- package/dist/src/formats/gml/styles.d.ts.map +1 -1
- package/dist/src/formats/gml/styles.js +754 -102
- package/dist/src/formats/gml/styles.js.map +1 -1
- package/dist/src/formats/graphml/styles-plain.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-plain.js +6 -10
- package/dist/src/formats/graphml/styles-plain.js.map +1 -1
- package/dist/src/formats/graphml/styles-yed.d.ts +21 -15
- package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yed.js +695 -164
- package/dist/src/formats/graphml/styles-yed.js.map +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.d.ts +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yfiles3.js +431 -64
- package/dist/src/formats/graphml/styles-yfiles3.js.map +1 -1
- package/dist/src/formats/graphml/yfiles.d.ts +3 -3
- package/dist/src/formats/graphml/yfiles.d.ts.map +1 -1
- package/dist/src/formats/graphml/yfiles.js +16 -6
- package/dist/src/formats/graphml/yfiles.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts +3 -2
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +39 -5
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts +13 -2
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +42 -6
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/src/formats/json/index.d.ts +1 -1
- package/dist/src/formats/json/index.d.ts.map +1 -1
- package/dist/src/formats/json/index.js +1 -1
- package/dist/src/formats/json/index.js.map +1 -1
- package/dist/src/formats/json/positions.d.ts +5 -2
- package/dist/src/formats/json/positions.d.ts.map +1 -1
- package/dist/src/formats/json/positions.js +20 -4
- package/dist/src/formats/json/positions.js.map +1 -1
- package/dist/src/formats/json/styles.d.ts +12 -1
- package/dist/src/formats/json/styles.d.ts.map +1 -1
- package/dist/src/formats/json/styles.js +1843 -136
- package/dist/src/formats/json/styles.js.map +1 -1
- package/dist/src/formats/pajek/draw.d.ts +104 -0
- package/dist/src/formats/pajek/draw.d.ts.map +1 -0
- package/dist/src/formats/pajek/draw.js +382 -0
- package/dist/src/formats/pajek/draw.js.map +1 -0
- package/dist/src/formats/pajek/exporter.d.ts.map +1 -1
- package/dist/src/formats/pajek/exporter.js +70 -51
- package/dist/src/formats/pajek/exporter.js.map +1 -1
- package/dist/src/formats/pajek/importer.d.ts +9 -0
- package/dist/src/formats/pajek/importer.d.ts.map +1 -1
- package/dist/src/formats/pajek/importer.js +233 -102
- package/dist/src/formats/pajek/importer.js.map +1 -1
- package/dist/src/formats/pajek/index.d.ts +1 -0
- package/dist/src/formats/pajek/index.d.ts.map +1 -1
- package/dist/src/formats/pajek/index.js.map +1 -1
- package/dist/src/formats/pajek/styles.d.ts +15 -7
- package/dist/src/formats/pajek/styles.d.ts.map +1 -1
- package/dist/src/formats/pajek/styles.js +1395 -114
- package/dist/src/formats/pajek/styles.js.map +1 -1
- package/dist/src/formats/pajek/syntax.d.ts +10 -1
- package/dist/src/formats/pajek/syntax.d.ts.map +1 -1
- package/dist/src/formats/pajek/syntax.js +26 -2
- package/dist/src/formats/pajek/syntax.js.map +1 -1
- package/dist/src/formats/xgmml/emit.d.ts +1 -0
- package/dist/src/formats/xgmml/emit.d.ts.map +1 -1
- package/dist/src/formats/xgmml/emit.js +65 -5
- package/dist/src/formats/xgmml/emit.js.map +1 -1
- package/dist/src/formats/xgmml/styles.d.ts +23 -3
- package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
- package/dist/src/formats/xgmml/styles.js +277 -60
- package/dist/src/formats/xgmml/styles.js.map +1 -1
- package/dist/src/index.d.ts +6 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/positions/convert.d.ts.map +1 -1
- package/dist/src/positions/convert.js +11 -1
- package/dist/src/positions/convert.js.map +1 -1
- package/dist/src/positions/extract.d.ts.map +1 -1
- package/dist/src/positions/extract.js +53 -1
- package/dist/src/positions/extract.js.map +1 -1
- package/dist/src/positions/index.d.ts +1 -1
- package/dist/src/positions/index.d.ts.map +1 -1
- package/dist/src/positions/types.d.ts +59 -0
- package/dist/src/positions/types.d.ts.map +1 -1
- package/dist/src/sources/builtins.d.ts +1 -1
- package/dist/src/sources/builtins.d.ts.map +1 -1
- package/dist/src/sources/builtins.js +8 -2
- package/dist/src/sources/builtins.js.map +1 -1
- package/dist/src/sources/context.d.ts.map +1 -1
- package/dist/src/sources/context.js +1 -0
- package/dist/src/sources/context.js.map +1 -1
- package/dist/src/sources/credentials.d.ts +50 -1
- package/dist/src/sources/credentials.d.ts.map +1 -1
- package/dist/src/sources/credentials.js +69 -0
- package/dist/src/sources/credentials.js.map +1 -1
- package/dist/src/sources/cypher/descriptor.d.ts.map +1 -1
- package/dist/src/sources/cypher/descriptor.js +5 -0
- package/dist/src/sources/cypher/descriptor.js.map +1 -1
- package/dist/src/sources/cypher/index.d.ts.map +1 -1
- package/dist/src/sources/cypher/index.js +125 -18
- package/dist/src/sources/cypher/index.js.map +1 -1
- package/dist/src/sources/cypher/params.d.ts +1 -1
- package/dist/src/sources/cypher/params.d.ts.map +1 -1
- package/dist/src/sources/cypher/query-builder.d.ts +17 -0
- package/dist/src/sources/cypher/query-builder.d.ts.map +1 -1
- package/dist/src/sources/cypher/query-builder.js +31 -0
- package/dist/src/sources/cypher/query-builder.js.map +1 -1
- package/dist/src/sources/ids.d.ts +5 -0
- package/dist/src/sources/ids.d.ts.map +1 -1
- package/dist/src/sources/ids.js +5 -0
- package/dist/src/sources/ids.js.map +1 -1
- package/dist/src/sources/params.d.ts +3 -0
- package/dist/src/sources/params.d.ts.map +1 -1
- package/dist/src/sources/rest/descriptor.d.ts.map +1 -1
- package/dist/src/sources/rest/descriptor.js +9 -0
- package/dist/src/sources/rest/descriptor.js.map +1 -1
- package/dist/src/sources/rest/openalex.d.ts +4 -2
- package/dist/src/sources/rest/openalex.d.ts.map +1 -1
- package/dist/src/sources/rest/openalex.js +4 -2
- package/dist/src/sources/rest/openalex.js.map +1 -1
- package/dist/src/sources/rest/source.d.ts.map +1 -1
- package/dist/src/sources/rest/source.js +38 -0
- package/dist/src/sources/rest/source.js.map +1 -1
- package/dist/src/sources/run.d.ts +2 -0
- package/dist/src/sources/run.d.ts.map +1 -1
- package/dist/src/sources/run.js +30 -3
- package/dist/src/sources/run.js.map +1 -1
- package/dist/src/sources/sigv4.d.ts +5 -3
- package/dist/src/sources/sigv4.d.ts.map +1 -1
- package/dist/src/sources/sigv4.js +6 -4
- package/dist/src/sources/sigv4.js.map +1 -1
- package/dist/src/sources/sparql/descriptor.d.ts +10 -0
- package/dist/src/sources/sparql/descriptor.d.ts.map +1 -0
- package/dist/src/sources/sparql/descriptor.js +64 -0
- package/dist/src/sources/sparql/descriptor.js.map +1 -0
- package/dist/src/sources/sparql/index.d.ts +28 -0
- package/dist/src/sources/sparql/index.d.ts.map +1 -0
- package/dist/src/sources/sparql/index.js +327 -0
- package/dist/src/sources/sparql/index.js.map +1 -0
- package/dist/src/sources/sparql/ntriples.d.ts +69 -0
- package/dist/src/sources/sparql/ntriples.d.ts.map +1 -0
- package/dist/src/sources/sparql/ntriples.js +180 -0
- package/dist/src/sources/sparql/ntriples.js.map +1 -0
- package/dist/src/sources/sparql/params.d.ts +27 -0
- package/dist/src/sources/sparql/params.d.ts.map +1 -0
- package/dist/src/sources/sparql/params.js +5 -0
- package/dist/src/sources/sparql/params.js.map +1 -0
- package/dist/src/sources/sparql/query.d.ts +73 -0
- package/dist/src/sources/sparql/query.d.ts.map +1 -0
- package/dist/src/sources/sparql/query.js +164 -0
- package/dist/src/sources/sparql/query.js.map +1 -0
- package/dist/src/sources/types.d.ts +60 -0
- package/dist/src/sources/types.d.ts.map +1 -1
- package/dist/src/styles/annotations.d.ts +61 -5
- package/dist/src/styles/annotations.d.ts.map +1 -1
- package/dist/src/styles/annotations.js +130 -22
- package/dist/src/styles/annotations.js.map +1 -1
- package/dist/src/styles/canon/bends.d.ts +46 -0
- package/dist/src/styles/canon/bends.d.ts.map +1 -1
- package/dist/src/styles/canon/bends.js +123 -0
- package/dist/src/styles/canon/bends.js.map +1 -1
- package/dist/src/styles/canon/color-tables.d.ts +6 -1
- package/dist/src/styles/canon/color-tables.d.ts.map +1 -1
- package/dist/src/styles/canon/color-tables.js +10 -4
- package/dist/src/styles/canon/color-tables.js.map +1 -1
- package/dist/src/styles/canon/color.d.ts +3 -1
- package/dist/src/styles/canon/color.d.ts.map +1 -1
- package/dist/src/styles/canon/color.js +103 -3
- package/dist/src/styles/canon/color.js.map +1 -1
- package/dist/src/styles/canon/enums.d.ts +2 -2
- package/dist/src/styles/canon/enums.d.ts.map +1 -1
- package/dist/src/styles/canon/enums.js +89 -7
- package/dist/src/styles/canon/enums.js.map +1 -1
- package/dist/src/styles/canon/graphviz.d.ts +12 -3
- package/dist/src/styles/canon/graphviz.d.ts.map +1 -1
- package/dist/src/styles/canon/graphviz.js +57 -9
- package/dist/src/styles/canon/graphviz.js.map +1 -1
- package/dist/src/styles/canon/number.d.ts +8 -0
- package/dist/src/styles/canon/number.d.ts.map +1 -1
- package/dist/src/styles/canon/number.js +18 -0
- package/dist/src/styles/canon/number.js.map +1 -1
- package/dist/src/styles/canon/text.d.ts +29 -2
- package/dist/src/styles/canon/text.d.ts.map +1 -1
- package/dist/src/styles/canon/text.js +156 -16
- package/dist/src/styles/canon/text.js.map +1 -1
- package/dist/src/styles/codes.d.ts +2 -0
- package/dist/src/styles/codes.d.ts.map +1 -1
- package/dist/src/styles/codes.js +2 -0
- package/dist/src/styles/codes.js.map +1 -1
- package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
- package/dist/src/styles/cyjs/cascade.js +1139 -79
- package/dist/src/styles/cyjs/cascade.js.map +1 -1
- package/dist/src/styles/cyjs/defaults-table.d.ts.map +1 -1
- package/dist/src/styles/cyjs/defaults-table.js +4 -0
- package/dist/src/styles/cyjs/defaults-table.js.map +1 -1
- package/dist/src/styles/cyjs/emit.d.ts.map +1 -1
- package/dist/src/styles/cyjs/emit.js +232 -10
- package/dist/src/styles/cyjs/emit.js.map +1 -1
- package/dist/src/styles/cyjs/face.d.ts +20 -0
- package/dist/src/styles/cyjs/face.d.ts.map +1 -0
- package/dist/src/styles/cyjs/face.js +332 -0
- package/dist/src/styles/cyjs/face.js.map +1 -0
- package/dist/src/styles/cyjs/mappers.d.ts +44 -1
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
- package/dist/src/styles/cyjs/mappers.js +475 -26
- package/dist/src/styles/cyjs/mappers.js.map +1 -1
- package/dist/src/styles/cyjs/routes.d.ts +53 -0
- package/dist/src/styles/cyjs/routes.d.ts.map +1 -0
- package/dist/src/styles/cyjs/routes.js +360 -0
- package/dist/src/styles/cyjs/routes.js.map +1 -0
- package/dist/src/styles/cytoscape/charts.d.ts +23 -0
- package/dist/src/styles/cytoscape/charts.d.ts.map +1 -0
- package/dist/src/styles/cytoscape/charts.js +560 -0
- package/dist/src/styles/cytoscape/charts.js.map +1 -0
- package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/emit.js +156 -48
- package/dist/src/styles/cytoscape/emit.js.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.d.ts +91 -3
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.js +387 -77
- package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
- package/dist/src/styles/cytoscape/mappings.d.ts +30 -0
- package/dist/src/styles/cytoscape/mappings.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/mappings.js +92 -0
- package/dist/src/styles/cytoscape/mappings.js.map +1 -1
- package/dist/src/styles/cytoscape/resolve.d.ts +42 -2
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/resolve.js +623 -17
- package/dist/src/styles/cytoscape/resolve.js.map +1 -1
- package/dist/src/styles/defaults.d.ts +46 -26
- package/dist/src/styles/defaults.d.ts.map +1 -1
- package/dist/src/styles/defaults.js +308 -71
- package/dist/src/styles/defaults.js.map +1 -1
- package/dist/src/styles/index.d.ts +4 -3
- package/dist/src/styles/index.d.ts.map +1 -1
- package/dist/src/styles/index.js +3 -2
- package/dist/src/styles/index.js.map +1 -1
- package/dist/src/styles/internal.d.ts +1 -0
- package/dist/src/styles/internal.d.ts.map +1 -1
- package/dist/src/styles/internal.js +1 -0
- package/dist/src/styles/internal.js.map +1 -1
- package/dist/src/styles/io/generic.d.ts.map +1 -1
- package/dist/src/styles/io/generic.js +56 -16
- package/dist/src/styles/io/generic.js.map +1 -1
- package/dist/src/styles/io/round-trip.d.ts +56 -0
- package/dist/src/styles/io/round-trip.d.ts.map +1 -0
- package/dist/src/styles/io/round-trip.js +138 -0
- package/dist/src/styles/io/round-trip.js.map +1 -0
- package/dist/src/styles/io/writer.d.ts.map +1 -1
- package/dist/src/styles/io/writer.js +6 -1
- package/dist/src/styles/io/writer.js.map +1 -1
- package/dist/src/styles/notes.d.ts.map +1 -1
- package/dist/src/styles/notes.js +1 -0
- package/dist/src/styles/notes.js.map +1 -1
- package/dist/src/styles/plan/features.d.ts +1 -1
- package/dist/src/styles/plan/features.d.ts.map +1 -1
- package/dist/src/styles/plan/features.js +22 -2
- package/dist/src/styles/plan/features.js.map +1 -1
- package/dist/src/styles/plan/index.d.ts +1 -1
- package/dist/src/styles/plan/index.d.ts.map +1 -1
- package/dist/src/styles/plan/index.js +1 -1
- package/dist/src/styles/plan/index.js.map +1 -1
- package/dist/src/styles/plan/plan.d.ts.map +1 -1
- package/dist/src/styles/plan/plan.js +61 -4
- package/dist/src/styles/plan/plan.js.map +1 -1
- package/dist/src/styles/plan/resolve.d.ts +11 -0
- package/dist/src/styles/plan/resolve.d.ts.map +1 -1
- package/dist/src/styles/plan/resolve.js +40 -4
- package/dist/src/styles/plan/resolve.js.map +1 -1
- package/dist/src/styles/slots.d.ts +14 -0
- package/dist/src/styles/slots.d.ts.map +1 -0
- package/dist/src/styles/slots.js +20 -0
- package/dist/src/styles/slots.js.map +1 -0
- package/dist/src/styles/types.d.ts +687 -6
- package/dist/src/styles/types.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.d.ts +3 -2
- package/dist/src/styles/vocabulary.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.js +224 -0
- package/dist/src/styles/vocabulary.js.map +1 -1
- package/dist/styles.js +30 -239
- package/dist/styles.js.map +1 -1
- package/dist/xgmml.js +3 -3
- package/package.json +27 -7
- package/src/formats/cx/importer.ts +6 -1
- package/src/formats/cx/styles.ts +143 -9
- package/src/formats/cx2/importer.ts +1 -0
- package/src/formats/cx2/styles.ts +3 -1
- package/src/formats/cys/importer.ts +1 -0
- package/src/formats/cys/styles.ts +27 -5
- package/src/formats/dot/drawing.ts +799 -0
- package/src/formats/dot/exporter.ts +37 -1
- package/src/formats/dot/importer.ts +192 -36
- package/src/formats/dot/index.ts +3 -1
- package/src/formats/dot/label-places.ts +241 -0
- package/src/formats/dot/names.ts +15 -0
- package/src/formats/dot/record.ts +336 -0
- package/src/formats/dot/styles.ts +1702 -149
- package/src/formats/gexf/dialog-metrics.ts +61 -0
- package/src/formats/gexf/importer.ts +50 -5
- package/src/formats/gexf/preview.ts +217 -0
- package/src/formats/gexf/schema.ts +2 -1
- package/src/formats/gexf/styles.ts +1099 -245
- package/src/formats/gml/importer.ts +291 -76
- package/src/formats/gml/index.ts +1 -1
- package/src/formats/gml/positions.ts +29 -7
- package/src/formats/gml/styles.ts +852 -110
- package/src/formats/graphml/styles-plain.ts +6 -15
- package/src/formats/graphml/styles-yed.ts +765 -176
- package/src/formats/graphml/styles-yfiles3.ts +487 -63
- package/src/formats/graphml/yfiles.ts +19 -6
- package/src/formats/json/dialect.ts +41 -5
- package/src/formats/json/importer.ts +59 -7
- package/src/formats/json/index.ts +1 -0
- package/src/formats/json/positions.ts +22 -5
- package/src/formats/json/styles.ts +2123 -171
- package/src/formats/pajek/draw.ts +469 -0
- package/src/formats/pajek/exporter.ts +81 -49
- package/src/formats/pajek/importer.ts +278 -103
- package/src/formats/pajek/index.ts +1 -0
- package/src/formats/pajek/styles.ts +1506 -133
- package/src/formats/pajek/syntax.ts +27 -2
- package/src/formats/xgmml/emit.ts +73 -5
- package/src/formats/xgmml/styles.ts +330 -71
- package/src/index.ts +12 -1
- package/src/positions/convert.ts +12 -1
- package/src/positions/extract.ts +55 -1
- package/src/positions/index.ts +1 -0
- package/src/positions/types.ts +60 -0
- package/src/sources/builtins.ts +8 -1
- package/src/sources/context.ts +1 -0
- package/src/sources/credentials.ts +90 -1
- package/src/sources/cypher/descriptor.ts +7 -1
- package/src/sources/cypher/index.ts +149 -18
- package/src/sources/cypher/params.ts +1 -1
- package/src/sources/cypher/query-builder.ts +33 -0
- package/src/sources/ids.ts +6 -0
- package/src/sources/params.ts +3 -0
- package/src/sources/rest/descriptor.ts +9 -0
- package/src/sources/rest/openalex.ts +4 -2
- package/src/sources/rest/source.ts +41 -0
- package/src/sources/run.ts +35 -3
- package/src/sources/sigv4.ts +6 -4
- package/src/sources/sparql/descriptor.ts +67 -0
- package/src/sources/sparql/index.ts +371 -0
- package/src/sources/sparql/ntriples.ts +219 -0
- package/src/sources/sparql/params.ts +28 -0
- package/src/sources/sparql/query.ts +216 -0
- package/src/sources/types.ts +68 -0
- package/src/styles/annotations.ts +201 -27
- package/src/styles/canon/bends.ts +137 -0
- package/src/styles/canon/color-tables.ts +10 -4
- package/src/styles/canon/color.ts +105 -3
- package/src/styles/canon/enums.ts +107 -8
- package/src/styles/canon/graphviz.ts +71 -10
- package/src/styles/canon/number.ts +19 -0
- package/src/styles/canon/text.ts +187 -16
- package/src/styles/codes.ts +2 -0
- package/src/styles/cyjs/cascade.ts +1303 -84
- package/src/styles/cyjs/defaults-table.ts +4 -0
- package/src/styles/cyjs/emit.ts +268 -14
- package/src/styles/cyjs/face.ts +372 -0
- package/src/styles/cyjs/mappers.ts +506 -27
- package/src/styles/cyjs/routes.ts +432 -0
- package/src/styles/cytoscape/charts.ts +684 -0
- package/src/styles/cytoscape/emit.ts +170 -48
- package/src/styles/cytoscape/lexicon.ts +431 -78
- package/src/styles/cytoscape/mappings.ts +108 -0
- package/src/styles/cytoscape/resolve.ts +741 -17
- package/src/styles/defaults.ts +417 -108
- package/src/styles/index.ts +5 -0
- package/src/styles/internal.ts +1 -0
- package/src/styles/io/generic.ts +79 -23
- package/src/styles/io/round-trip.ts +202 -0
- package/src/styles/io/writer.ts +6 -1
- package/src/styles/notes.ts +1 -0
- package/src/styles/plan/features.ts +23 -2
- package/src/styles/plan/index.ts +1 -1
- package/src/styles/plan/plan.ts +69 -5
- package/src/styles/plan/resolve.ts +47 -4
- package/src/styles/slots.ts +25 -0
- package/src/styles/types.ts +698 -5
- package/src/styles/vocabulary.ts +232 -2
- package/dist/chunks/block-Cu22ewuS.js.map +0 -1
- package/dist/chunks/choose-Cdx6Enl2.js +0 -57
- package/dist/chunks/choose-Cdx6Enl2.js.map +0 -1
- package/dist/chunks/codes-CV_Bhcyi.js.map +0 -1
- package/dist/chunks/convert-BcQ8_jMo.js.map +0 -1
- package/dist/chunks/credentials-BiQsnMTb.js.map +0 -1
- package/dist/chunks/descriptor-BJ-W0Jd-.js.map +0 -1
- package/dist/chunks/emit-CD8xnY8s.js.map +0 -1
- package/dist/chunks/export-CZ7VRm4I.js.map +0 -1
- package/dist/chunks/exporter-bxxjOrDZ.js.map +0 -1
- package/dist/chunks/format-BMS-1Nxb.js +0 -64
- package/dist/chunks/format-BMS-1Nxb.js.map +0 -1
- package/dist/chunks/generic-CP6YD34u.js.map +0 -1
- package/dist/chunks/importer-B87_fmVx.js.map +0 -1
- package/dist/chunks/importer-CB_zV5_L.js.map +0 -1
- package/dist/chunks/importer-CVT-JyDE.js.map +0 -1
- package/dist/chunks/importer-Cyy6UseH.js.map +0 -1
- package/dist/chunks/importer-DPZDN40-.js.map +0 -1
- package/dist/chunks/importer-e3huMZbm.js.map +0 -1
- package/dist/chunks/lexicon-u2SI5xcx.js.map +0 -1
- package/dist/chunks/sigv4-LkAzsLAu.js.map +0 -1
- package/dist/chunks/styles-CaABMoO1.js.map +0 -1
- package/dist/chunks/styles-P_gmFAOi.js +0 -770
- package/dist/chunks/styles-P_gmFAOi.js.map +0 -1
- package/dist/chunks/styles-yed-Cs1nmrjn.js.map +0 -1
- package/dist/chunks/writer-DvHTl36J.js +0 -449
- package/dist/chunks/writer-DvHTl36J.js.map +0 -1
|
@@ -25,10 +25,11 @@ import {
|
|
|
25
25
|
type SourceDescriptor,
|
|
26
26
|
type SourceFreshness,
|
|
27
27
|
type SourceProbe,
|
|
28
|
+
type SourceTotal,
|
|
28
29
|
type SourceValidators,
|
|
29
30
|
} from "../types.js";
|
|
30
31
|
import { CYPHER_DESCRIPTOR, NEO4J_DESCRIPTOR, NEPTUNE_DESCRIPTOR } from "./descriptor.js";
|
|
31
|
-
import { canonicalRows, Collector, compareText, requireGraph, writeCollected } from "./flatten.js";
|
|
32
|
+
import { canonicalRows, Collector, compareText, type QueryResult, requireGraph, writeCollected } from "./flatten.js";
|
|
32
33
|
import { type CypherParams } from "./params.js";
|
|
33
34
|
import { type CypherProfile, neo4jProfile, neptuneProfile, serverFacts } from "./profiles.js";
|
|
34
35
|
import {
|
|
@@ -36,12 +37,14 @@ import {
|
|
|
36
37
|
counts,
|
|
37
38
|
DEFAULT_PAGE_SIZE,
|
|
38
39
|
edgePage,
|
|
40
|
+
edgesAmong,
|
|
39
41
|
MAX_DEPTH,
|
|
40
42
|
MAX_PAGE_SIZE,
|
|
41
43
|
neighborhood,
|
|
42
44
|
nodePage,
|
|
43
45
|
type QueryFilters,
|
|
44
46
|
quoted,
|
|
47
|
+
storeCount,
|
|
45
48
|
} from "./query-builder.js";
|
|
46
49
|
import { boltTransport } from "./transports/bolt.js";
|
|
47
50
|
import { neptuneAnalyticsTransport } from "./transports/neptune-analytics.js";
|
|
@@ -77,6 +80,20 @@ interface Page {
|
|
|
77
80
|
/** The directions an expansion may follow. */
|
|
78
81
|
const DIRECTIONS: ReadonlySet<string> = new Set(["out", "in", "both"]);
|
|
79
82
|
|
|
83
|
+
/**
|
|
84
|
+
* A query without the semicolons it ends with, so it can sit inside `CALL { }`. A loop, not
|
|
85
|
+
* `/;+$/`, which backtracks over every run of semicolons that is not at the end.
|
|
86
|
+
* @param query - the trimmed query
|
|
87
|
+
* @returns the query
|
|
88
|
+
*/
|
|
89
|
+
function withoutTrailingSemicolons(query: string): string {
|
|
90
|
+
let end = query.length;
|
|
91
|
+
while (end > 0 && query[end - 1] === ";") {
|
|
92
|
+
end--;
|
|
93
|
+
}
|
|
94
|
+
return query.slice(0, end);
|
|
95
|
+
}
|
|
96
|
+
|
|
80
97
|
/**
|
|
81
98
|
* A list parameter: an array, or one value. A string is one item, never split, since an id or a
|
|
82
99
|
* label may hold any character.
|
|
@@ -124,6 +141,8 @@ class Reader {
|
|
|
124
141
|
private known: CypherProfile | null = null;
|
|
125
142
|
private degree = true;
|
|
126
143
|
readonly filters: QueryFilters;
|
|
144
|
+
/** What the source holds for this load, when a count ran. */
|
|
145
|
+
counted: SourceTotal | undefined;
|
|
127
146
|
/** The raw id property, for the node ids. */
|
|
128
147
|
readonly idProperty: string | null;
|
|
129
148
|
|
|
@@ -195,9 +214,10 @@ class Reader {
|
|
|
195
214
|
/**
|
|
196
215
|
* The pages of a read, as `mode` asks.
|
|
197
216
|
* @param cursor - where to resume
|
|
217
|
+
* @param counting - whether a first page of mode "all" may count what the source holds
|
|
198
218
|
* @yields one page at a time
|
|
199
219
|
*/
|
|
200
|
-
async *pages(cursor: SourceCursor | null): AsyncGenerator<Page> {
|
|
220
|
+
async *pages(cursor: SourceCursor | null, counting = true): AsyncGenerator<Page> {
|
|
201
221
|
const { params, ctx } = this;
|
|
202
222
|
const { report } = ctx;
|
|
203
223
|
const mode = params.mode ?? (typeof params.query === "string" && params.query !== "" ? "query" : "all");
|
|
@@ -205,11 +225,7 @@ class Reader {
|
|
|
205
225
|
if (typeof params.query !== "string" || params.query.trim() === "") {
|
|
206
226
|
failOn(report, "E_SOURCE_PARAM", "mode query needs a query", { name: "query", reason: "required" });
|
|
207
227
|
}
|
|
208
|
-
|
|
209
|
-
const collected = new Collector();
|
|
210
|
-
collected.add(result, false);
|
|
211
|
-
requireGraph(result, collected, report);
|
|
212
|
-
yield { collected, next: null };
|
|
228
|
+
yield await this.userQuery(params.query, cursor);
|
|
213
229
|
return;
|
|
214
230
|
}
|
|
215
231
|
const profile = await this.profile();
|
|
@@ -230,7 +246,49 @@ class Reader {
|
|
|
230
246
|
yield { collected, next: null };
|
|
231
247
|
return;
|
|
232
248
|
}
|
|
233
|
-
yield* this.everything(profile, cursor);
|
|
249
|
+
yield* this.everything(profile, cursor, counting);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Mode "query": the reader's own query, as written. With a node cap (or a cursor from a capped
|
|
254
|
+
* run) the server returns at most that many rows (`CALL { query } RETURN * LIMIT n`), and a full
|
|
255
|
+
* result hands back a cursor that runs the query again with twice the rows, for the caller to
|
|
256
|
+
* merge. A server that refuses the wrapper fails the load with `E_SOURCE_PARAM` (`name:
|
|
257
|
+
* "maxNodes"`, `reason: "uncappable"`): the query is never run past the cap the caller set.
|
|
258
|
+
* @param query - the query
|
|
259
|
+
* @param cursor - where to resume: `{ rows }` from an earlier capped run
|
|
260
|
+
* @returns the one page
|
|
261
|
+
*/
|
|
262
|
+
private async userQuery(query: string, cursor: SourceCursor | null): Promise<Page> {
|
|
263
|
+
const { params, ctx } = this;
|
|
264
|
+
const parameters = params.parameters ?? {};
|
|
265
|
+
const asked = cursor?.rows ?? ctx.limits.maxNodes;
|
|
266
|
+
const rows =
|
|
267
|
+
asked === undefined || asked === null
|
|
268
|
+
? null
|
|
269
|
+
: Number(checkedInteger(asked, "maxNodes", 1, Number.MAX_SAFE_INTEGER, ctx.report));
|
|
270
|
+
let result: QueryResult;
|
|
271
|
+
try {
|
|
272
|
+
result = await this.transport.run(
|
|
273
|
+
rows === null
|
|
274
|
+
? query
|
|
275
|
+
: `CALL {\n${withoutTrailingSemicolons(query.trim())}\n}\nRETURN * LIMIT ${String(rows)}`,
|
|
276
|
+
parameters,
|
|
277
|
+
);
|
|
278
|
+
} catch (err) {
|
|
279
|
+
if (rows === null || !(err instanceof ImportError) || err.issue?.code !== SOURCE_ISSUE.E_SOURCE_QUERY) {
|
|
280
|
+
throw err;
|
|
281
|
+
}
|
|
282
|
+
return failOn(ctx.report, "E_SOURCE_PARAM", "the server cannot cap this query; load it without maxNodes", {
|
|
283
|
+
name: "maxNodes",
|
|
284
|
+
reason: "uncappable",
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
const collected = new Collector();
|
|
288
|
+
collected.add(result, false);
|
|
289
|
+
requireGraph(result, collected, ctx.report);
|
|
290
|
+
const full = rows !== null && result.rows.length >= rows;
|
|
291
|
+
return { collected, next: full ? { rows: rows * 2 } : null };
|
|
234
292
|
}
|
|
235
293
|
|
|
236
294
|
/**
|
|
@@ -238,14 +296,33 @@ class Reader {
|
|
|
238
296
|
* id expression (never SKIP), so a page is stable under unrelated writes.
|
|
239
297
|
* @param profile - the server's profile
|
|
240
298
|
* @param cursor - where to resume
|
|
299
|
+
* @param counting - whether a first page may count what the source holds
|
|
241
300
|
* @yields one page at a time
|
|
242
301
|
*/
|
|
243
|
-
private async *everything(
|
|
302
|
+
private async *everything(
|
|
303
|
+
profile: CypherProfile,
|
|
304
|
+
cursor: SourceCursor | null,
|
|
305
|
+
counting: boolean,
|
|
306
|
+
): AsyncGenerator<Page> {
|
|
244
307
|
const { params, ctx } = this;
|
|
245
308
|
const size = checkedInteger(params.pageSize ?? DEFAULT_PAGE_SIZE, "pageSize", 1, MAX_PAGE_SIZE, ctx.report);
|
|
309
|
+
if (cursor === null && counting) {
|
|
310
|
+
this.counted = await this.count(profile);
|
|
311
|
+
}
|
|
312
|
+
const cap = ctx.limits.maxNodes;
|
|
313
|
+
if (cap !== undefined && cursor?.phase !== "edges") {
|
|
314
|
+
const capped = Number(checkedInteger(cap, "maxNodes", 1, Number.MAX_SAFE_INTEGER, ctx.report));
|
|
315
|
+
yield* this.cappedNodes(profile, cursor, Math.min(Number(size), capped));
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
246
319
|
let phase: "nodes" | "edges" = cursor?.phase === "edges" ? "edges" : "nodes";
|
|
247
320
|
let after: string | number | boolean | null = cursor?.after ?? null;
|
|
248
|
-
const
|
|
321
|
+
const { counted } = this;
|
|
322
|
+
const total =
|
|
323
|
+
params.countFirst === true && counted !== undefined
|
|
324
|
+
? (counted.nodes ?? 0) + (counted.edges ?? 0)
|
|
325
|
+
: undefined;
|
|
249
326
|
for (;;) {
|
|
250
327
|
const nodes = phase === "nodes";
|
|
251
328
|
const { collected, rows, fields } = await this.generated(
|
|
@@ -268,13 +345,66 @@ class Reader {
|
|
|
268
345
|
}
|
|
269
346
|
|
|
270
347
|
/**
|
|
271
|
-
*
|
|
272
|
-
*
|
|
348
|
+
* Mode "all" under a node cap: pages of at most the cap's nodes, each with the relationships
|
|
349
|
+
* among the nodes loaded so far, so a capped load stops at its cap with its edges, and its
|
|
350
|
+
* next page (`data.more`) continues by key.
|
|
351
|
+
* @param profile - the server's profile
|
|
352
|
+
* @param cursor - where to resume
|
|
353
|
+
* @param size - the page size
|
|
354
|
+
* @yields one page at a time
|
|
355
|
+
*/
|
|
356
|
+
private async *cappedNodes(
|
|
357
|
+
profile: CypherProfile,
|
|
358
|
+
cursor: SourceCursor | null,
|
|
359
|
+
size: number,
|
|
360
|
+
): AsyncGenerator<Page> {
|
|
361
|
+
let after: string | number | boolean | null = cursor?.after ?? null;
|
|
362
|
+
for (;;) {
|
|
363
|
+
const { collected, rows, fields } = await this.generated(
|
|
364
|
+
(d) => nodePage(profile, this.filters, String(size), after !== null, d),
|
|
365
|
+
after === null ? {} : { after },
|
|
366
|
+
);
|
|
367
|
+
const at = fields.indexOf("key");
|
|
368
|
+
const last = rows.at(-1)?.[at];
|
|
369
|
+
const key = typeof last === "string" || typeof last === "number" ? last : null;
|
|
370
|
+
if (key !== null) {
|
|
371
|
+
const keys = rows.map((row) => row[at]);
|
|
372
|
+
const among = await this.transport.run(edgesAmong(profile, this.filters), { keys, last: key });
|
|
373
|
+
collected.add(among, false);
|
|
374
|
+
}
|
|
375
|
+
const next = rows.length >= size && key !== null ? { phase: "nodes", after: key } : null;
|
|
376
|
+
yield { collected, next };
|
|
377
|
+
if (next === null) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
after = key;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* What a first page of mode "all" counts: with `countFirst`, the nodes and relationships the
|
|
386
|
+
* filters match (for progress too); else, on Neo4j with at most one label and the server's
|
|
387
|
+
* ids, the nodes from the count store; else nothing.
|
|
388
|
+
* @param profile - the server's profile
|
|
389
|
+
* @returns the count, or undefined
|
|
273
390
|
*/
|
|
274
|
-
private async
|
|
275
|
-
|
|
276
|
-
const
|
|
277
|
-
|
|
391
|
+
private async count(profile: CypherProfile): Promise<SourceTotal | undefined> {
|
|
392
|
+
// A count is a non-negative integer; anything else a server answers is no count.
|
|
393
|
+
const first = async (statement: string): Promise<number | undefined> => {
|
|
394
|
+
const c = Number((await this.transport.run(statement, {})).rows[0]?.[0]);
|
|
395
|
+
return Number.isSafeInteger(c) && c >= 0 ? c : undefined;
|
|
396
|
+
};
|
|
397
|
+
const { labels, idProperty } = this.filters;
|
|
398
|
+
if (this.params.countFirst === true) {
|
|
399
|
+
const [n, r] = counts(this.filters);
|
|
400
|
+
const [nodes, edges] = await Promise.all([first(n), first(r)]);
|
|
401
|
+
return { ...(nodes === undefined ? {} : { nodes }), ...(edges === undefined ? {} : { edges }) };
|
|
402
|
+
}
|
|
403
|
+
if (profile.name !== "neo4j" || labels.length > 1 || idProperty !== null) {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
const nodes = await first(storeCount(labels[0]));
|
|
407
|
+
return nodes === undefined ? undefined : { nodes };
|
|
278
408
|
}
|
|
279
409
|
|
|
280
410
|
/**
|
|
@@ -392,7 +522,8 @@ function cypher(preset: Preset): GraphSource<CypherParams> {
|
|
|
392
522
|
break;
|
|
393
523
|
}
|
|
394
524
|
}
|
|
395
|
-
|
|
525
|
+
const total = reader.counted === undefined ? {} : { total: reader.counted };
|
|
526
|
+
return ctx.finish({ next, ...total, ...(await reader.facts(lines)) });
|
|
396
527
|
}),
|
|
397
528
|
expand: (request, sink, ctx) =>
|
|
398
529
|
withReader(request.params, ctx, preset, (reader) => expand(reader, request, sink)),
|
|
@@ -404,7 +535,7 @@ function cypher(preset: Preset): GraphSource<CypherParams> {
|
|
|
404
535
|
validate: (params, seen, ctx) =>
|
|
405
536
|
withReader(params, ctx, preset, async (reader): Promise<SourceFreshness> => {
|
|
406
537
|
const lines: string[] = [];
|
|
407
|
-
for await (const page of reader.pages(null)) {
|
|
538
|
+
for await (const page of reader.pages(null, false)) {
|
|
408
539
|
lines.push(...canonicalRows(page.collected, reader.idProperty));
|
|
409
540
|
}
|
|
410
541
|
const { validators } = await reader.facts(lines);
|
|
@@ -36,6 +36,6 @@ export interface CypherParams {
|
|
|
36
36
|
readonly long?: "f64" | "string" | undefined;
|
|
37
37
|
/** Run a count first, for a progress total. @defaultValue false */
|
|
38
38
|
readonly countFirst?: boolean | undefined;
|
|
39
|
-
/** Rows per page of mode "all", 1 to 100000.
|
|
39
|
+
/** Rows per page of mode "all", 1 to 100000. Under a node cap a page holds at most the cap's nodes, with the relationships among the nodes loaded so far. @defaultValue 1000 */
|
|
40
40
|
readonly pageSize?: number | undefined;
|
|
41
41
|
}
|
|
@@ -215,6 +215,28 @@ export function edgePage(profile: CypherProfile, filters: QueryFilters, pageSize
|
|
|
215
215
|
.join(" ");
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
/**
|
|
219
|
+
* The relationships among the nodes a capped mode "all" has loaded that touch one node page: each
|
|
220
|
+
* starts from the page's own nodes `$keys` (an id or index lookup, never a scan of every
|
|
221
|
+
* relationship), with its other end on this page or an earlier one (at or before `$last`), so each
|
|
222
|
+
* relationship arrives once, with the page that loads its later end.
|
|
223
|
+
* @param profile - the server's profile
|
|
224
|
+
* @param filters - the filters
|
|
225
|
+
* @returns the statement; it reads `$keys` and `$last`
|
|
226
|
+
*/
|
|
227
|
+
export function edgesAmong(profile: CypherProfile, filters: QueryFilters): string {
|
|
228
|
+
const ka = idExpression("a", profile, filters);
|
|
229
|
+
const kb = idExpression("b", profile, filters);
|
|
230
|
+
const ends = [nodePredicate("a", filters), nodePredicate("b", filters)].filter((p) => p !== null);
|
|
231
|
+
const rest = ends.length === 0 ? "" : ` AND ${ends.join(" AND ")}`;
|
|
232
|
+
const pattern = `MATCH (a)-[r${typesPattern(filters)}]->(b)`;
|
|
233
|
+
return [
|
|
234
|
+
`${pattern} WHERE ${ka} IN $keys AND ${kb} <= $last${rest} RETURN a, r, b`,
|
|
235
|
+
"UNION ALL",
|
|
236
|
+
`${pattern} WHERE ${kb} IN $keys AND ${ka} <= $last AND NOT ${ka} IN $keys${rest} RETURN a, r, b`,
|
|
237
|
+
].join(" ");
|
|
238
|
+
}
|
|
239
|
+
|
|
218
240
|
/** How far a neighborhood reaches. */
|
|
219
241
|
interface NeighborhoodShape {
|
|
220
242
|
/** The checked depth, as text. */
|
|
@@ -292,3 +314,14 @@ export function counts(filters: QueryFilters): readonly [string, string] {
|
|
|
292
314
|
`MATCH (a)-[r${typesPattern(filters)}]->(b)${whereClause(where.length === 0 ? null : where.join(" AND "))} RETURN count(r) AS c`,
|
|
293
315
|
];
|
|
294
316
|
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* The node count of a mode "all" load with at most one label and the server's ids: a pattern
|
|
320
|
+
* Neo4j answers from its count store in one cheap lookup, whatever the graph's size.
|
|
321
|
+
* @param label - the quoted label, or undefined for every node
|
|
322
|
+
* @returns the statement
|
|
323
|
+
*/
|
|
324
|
+
export function storeCount(label: string | undefined): string {
|
|
325
|
+
const pattern = label === undefined ? "n" : `n:${label}`;
|
|
326
|
+
return `MATCH (${pattern}) RETURN count(n) AS c`;
|
|
327
|
+
}
|
package/src/sources/ids.ts
CHANGED
|
@@ -42,6 +42,12 @@ export const REST_SOURCE_ID = "rest";
|
|
|
42
42
|
*/
|
|
43
43
|
export const OPENALEX_SOURCE_ID = "openalex";
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The SPARQL source, for any SPARQL 1.1 endpoint. Experimental.
|
|
47
|
+
* @category Network sources
|
|
48
|
+
*/
|
|
49
|
+
export const SPARQL_SOURCE_ID = "sparql";
|
|
50
|
+
|
|
45
51
|
/**
|
|
46
52
|
* The prefix of the reserved attribute namespace sources and graphty-element write facts under.
|
|
47
53
|
* @category Network sources
|
package/src/sources/params.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { type CypherParams } from "./cypher/params.js";
|
|
7
7
|
import { type NdexParams } from "./ndex/params.js";
|
|
8
8
|
import { type OpenAlexParams, type RestParams } from "./rest/params.js";
|
|
9
|
+
import { type SparqlParams } from "./sparql/params.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Parameter types by source id; extend it by declaration merging:
|
|
@@ -26,4 +27,6 @@ export interface SourceParamsMap {
|
|
|
26
27
|
rest: RestParams;
|
|
27
28
|
/** OpenAlex. */
|
|
28
29
|
openalex: OpenAlexParams;
|
|
30
|
+
/** Any SPARQL 1.1 endpoint. */
|
|
31
|
+
sparql: SparqlParams;
|
|
29
32
|
}
|
|
@@ -17,6 +17,8 @@ export const REST_DESCRIPTOR: SourceDescriptor = Object.freeze({
|
|
|
17
17
|
version: 1,
|
|
18
18
|
auth: ["bearer", "api-key"],
|
|
19
19
|
authRequired: "optional",
|
|
20
|
+
// ponytail: a mapping without `expand` or paging cannot do either; per-mapping features when a form needs them
|
|
21
|
+
features: ["expand", "probe", "validate", "page"],
|
|
20
22
|
params: [{ name: "mapping", plainName: "Mapping", type: "text", required: true }],
|
|
21
23
|
samples: [
|
|
22
24
|
{
|
|
@@ -47,7 +49,13 @@ export const OPENALEX_DESCRIPTOR: SourceDescriptor = Object.freeze({
|
|
|
47
49
|
defaultEndpoint: "https://api.openalex.org",
|
|
48
50
|
auth: ["api-key"],
|
|
49
51
|
authRequired: "optional",
|
|
52
|
+
// OpenAlex documents its key as the api_key query parameter
|
|
53
|
+
credentials: [
|
|
54
|
+
{ name: "api_key", kind: "api-key", required: false, plainName: "API key", send: { query: "api_key" } },
|
|
55
|
+
],
|
|
56
|
+
apiKey: { query: "api_key" },
|
|
50
57
|
rateLimit: { requests: 10, perMs: 1000 },
|
|
58
|
+
features: ["expand", "probe", "validate", "page"],
|
|
51
59
|
params: [
|
|
52
60
|
{ name: "work", plainName: "Work", type: "string" },
|
|
53
61
|
{ name: "author", plainName: "Author", type: "string" },
|
|
@@ -69,6 +77,7 @@ export const OPENALEX_DESCRIPTOR: SourceDescriptor = Object.freeze({
|
|
|
69
77
|
plainName: "Watts-Strogatz paper's citations",
|
|
70
78
|
params: { work: "W2112090702" },
|
|
71
79
|
whole: false,
|
|
80
|
+
firstPage: 200,
|
|
72
81
|
},
|
|
73
82
|
],
|
|
74
83
|
});
|
|
@@ -266,8 +266,10 @@ const methods = restMethods<OpenAlexParams>(plan, false);
|
|
|
266
266
|
* The OpenAlex preset (https://openalex.org): `work` (the citation graph around a work, default)
|
|
267
267
|
* or `author` (the works they wrote), `graph: "coauthorship"` for authors joined by shared works,
|
|
268
268
|
* and `include` (`"authors"`, `"institutions"`, `"topics"`) for more node kinds. Without a key,
|
|
269
|
-
* the first page loads and a later one warns W_SOURCE_AUTH with `report.source.next
|
|
270
|
-
*
|
|
269
|
+
* the first page loads and a later one warns W_SOURCE_AUTH with `report.source.next`. Its one
|
|
270
|
+
* optional credential slot, `api_key`, is sent as the `api_key` query parameter: pass
|
|
271
|
+
* `credentials.forSlot(slot, key)` (or `credentials.apiKey({ query: "api_key" }, key)`) and
|
|
272
|
+
* continue with the cursor. Experimental.
|
|
271
273
|
* @category Network sources
|
|
272
274
|
*/
|
|
273
275
|
export const openalexSource: GraphSource<OpenAlexParams> = defineSource<OpenAlexParams>({
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type GraphSource,
|
|
20
20
|
type RecordBatch,
|
|
21
21
|
type SourceContext,
|
|
22
|
+
type SourceCredentialSlot,
|
|
22
23
|
type SourceCursor,
|
|
23
24
|
type SourceDescriptor,
|
|
24
25
|
type SourceFinish,
|
|
@@ -697,6 +698,44 @@ export type RestSourceInfo = {
|
|
|
697
698
|
readonly id: string;
|
|
698
699
|
} & Partial<SourceDescriptor>;
|
|
699
700
|
|
|
701
|
+
/**
|
|
702
|
+
* The credential slot a mapping's `auth` describes: an API key's slot is named by the query
|
|
703
|
+
* parameter or header it is sent in (`{ query: "api_key" }` is the slot `api_key`), a bearer
|
|
704
|
+
* token's is `default`. Optional, as a mapping cannot say a key is required.
|
|
705
|
+
* @param mapping - the mapping
|
|
706
|
+
* @returns the slots
|
|
707
|
+
*/
|
|
708
|
+
function mappingSlots(mapping: RestMapping): readonly SourceCredentialSlot[] {
|
|
709
|
+
const { auth } = mapping;
|
|
710
|
+
if (auth === undefined) {
|
|
711
|
+
return [];
|
|
712
|
+
}
|
|
713
|
+
if (auth.kind === "bearer") {
|
|
714
|
+
return [{ name: "default", kind: "bearer", required: false }];
|
|
715
|
+
}
|
|
716
|
+
const { header } = auth;
|
|
717
|
+
if (header !== undefined) {
|
|
718
|
+
return [{ name: header.toLowerCase(), kind: "api-key", required: false, send: { header } }];
|
|
719
|
+
}
|
|
720
|
+
const query = auth.query ?? "api_key";
|
|
721
|
+
return [{ name: query, kind: "api-key", required: false, send: { query } }];
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Where a mapping's API key goes, as a descriptor says it.
|
|
726
|
+
* @param auth - the mapping's auth
|
|
727
|
+
* @returns `{ apiKey }`, or nothing when the mapping takes no key or does not say where
|
|
728
|
+
*/
|
|
729
|
+
function apiKeyOf(auth: RestMapping["auth"]): Pick<SourceDescriptor, "apiKey"> {
|
|
730
|
+
if (auth?.kind !== "api-key") {
|
|
731
|
+
return {};
|
|
732
|
+
}
|
|
733
|
+
if (auth.header !== undefined) {
|
|
734
|
+
return { apiKey: { header: auth.header } };
|
|
735
|
+
}
|
|
736
|
+
return auth.query === undefined ? {} : { apiKey: { query: auth.query } };
|
|
737
|
+
}
|
|
738
|
+
|
|
700
739
|
/**
|
|
701
740
|
* Turn a REST mapping into a source: a `records` source that loads the mapping's `load` request
|
|
702
741
|
* page by page, with `expand` (breadth-first over the `expand` requests, `{ids}` batched; depth 0
|
|
@@ -733,6 +772,8 @@ export function restSource(mapping: RestMapping, info: RestSourceInfo): GraphSou
|
|
|
733
772
|
defaultEndpoint: mapping.endpoint,
|
|
734
773
|
auth,
|
|
735
774
|
authRequired: auth.length === 0 ? "none" : "optional",
|
|
775
|
+
credentials: mappingSlots(mapping),
|
|
776
|
+
...apiKeyOf(mapping.auth),
|
|
736
777
|
...(mapping.rateLimit === undefined ? {} : { rateLimit: mapping.rateLimit }),
|
|
737
778
|
...fields,
|
|
738
779
|
});
|
package/src/sources/run.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { type FormatRegistry } from "../registry.js";
|
|
|
15
15
|
import { SNIFF_HEAD_BYTES } from "../sniff.js";
|
|
16
16
|
import { type CommonImportOptions, ImportError, type ImportInput, type ImportReport } from "../types.js";
|
|
17
17
|
import { type CreatedContext, createSourceContext, detectRuntime, LimitStop } from "./context.js";
|
|
18
|
-
import { originOf } from "./credentials.js";
|
|
18
|
+
import { credentialQuery, originOf } from "./credentials.js";
|
|
19
19
|
import { checkParams } from "./define.js";
|
|
20
20
|
import { failOn, warnOn } from "./fail.js";
|
|
21
21
|
import { SOURCE_FORMAT_PREFIX } from "./ids.js";
|
|
@@ -60,6 +60,8 @@ interface Prepared {
|
|
|
60
60
|
readonly params: Record<string, unknown>;
|
|
61
61
|
/** The sink wrapper's counters, set once the sink is known. */
|
|
62
62
|
readonly counts: { nodes: Set<number>; edgesAtStart: number; sink: GraphSink | null };
|
|
63
|
+
/** The query parameter the call's credential is sent in, which a cursor never keeps; null for none. */
|
|
64
|
+
readonly secretQuery: string | null;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
/**
|
|
@@ -131,7 +133,8 @@ function prepare(
|
|
|
131
133
|
edges: counts.sink === null ? 0 : counts.sink.edgeCount - counts.edgesAtStart,
|
|
132
134
|
}),
|
|
133
135
|
});
|
|
134
|
-
|
|
136
|
+
const secretQuery = options.credential === undefined ? null : credentialQuery(options.credential);
|
|
137
|
+
return { report, created, params, counts, secretQuery };
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
/**
|
|
@@ -721,6 +724,7 @@ export async function runMethod<T>(
|
|
|
721
724
|
*/
|
|
722
725
|
export function withSource(report: ImportReport, prepared: Prepared, next: SourceCursor | null): ImportReport {
|
|
723
726
|
const own = prepared.report.finish();
|
|
727
|
+
const cursor = prepared.secretQuery === null || next === null ? next : withoutParam(next, prepared.secretQuery);
|
|
724
728
|
// issues the context recorded (retries, limits) that a source's own report does not hold
|
|
725
729
|
const missing = own.issues.filter((i) => !report.issues.includes(i));
|
|
726
730
|
return Object.freeze({
|
|
@@ -728,10 +732,38 @@ export function withSource(report: ImportReport, prepared: Prepared, next: Sourc
|
|
|
728
732
|
issues: missing.length === 0 ? report.issues : Object.freeze([...report.issues, ...missing]),
|
|
729
733
|
warningCount: report.warningCount + missing.filter((i) => i.severity === "warning").length,
|
|
730
734
|
errorCount: report.errorCount + missing.filter((i) => i.severity === "error").length,
|
|
731
|
-
source: prepared.created.info(
|
|
735
|
+
source: prepared.created.info(cursor),
|
|
732
736
|
});
|
|
733
737
|
}
|
|
734
738
|
|
|
739
|
+
/**
|
|
740
|
+
* A cursor without a query parameter in any URL it holds: a next-page link a service returns
|
|
741
|
+
* repeats the API key the request carried, and a cursor is saved where a credential never is.
|
|
742
|
+
* The credential is sent again with every request, so the next page does not need it there.
|
|
743
|
+
* @param value - the cursor, or a value inside it
|
|
744
|
+
* @param name - the parameter
|
|
745
|
+
* @returns the value without it
|
|
746
|
+
*/
|
|
747
|
+
function withoutParam<T>(value: T, name: string): T {
|
|
748
|
+
if (typeof value === "string" && /^https?:\/\//i.test(value)) {
|
|
749
|
+
const url = new URL(value);
|
|
750
|
+
if (!url.searchParams.has(name)) {
|
|
751
|
+
return value;
|
|
752
|
+
}
|
|
753
|
+
url.searchParams.delete(name);
|
|
754
|
+
return url.href as T;
|
|
755
|
+
}
|
|
756
|
+
if (Array.isArray(value)) {
|
|
757
|
+
return Object.freeze(value.map((each: unknown) => withoutParam(each, name))) as T;
|
|
758
|
+
}
|
|
759
|
+
if (typeof value === "object" && value !== null) {
|
|
760
|
+
return Object.freeze(
|
|
761
|
+
Object.fromEntries(Object.entries(value).map(([key, each]) => [key, withoutParam(each, name)])),
|
|
762
|
+
) as T;
|
|
763
|
+
}
|
|
764
|
+
return value;
|
|
765
|
+
}
|
|
766
|
+
|
|
735
767
|
/**
|
|
736
768
|
* What a failed call throws: the signal's reason when it aborted, an ImportError with the source
|
|
737
769
|
* info attached, or the error itself.
|
package/src/sources/sigv4.ts
CHANGED
|
@@ -75,12 +75,14 @@ async function sha256(data: Uint8Array | ArrayBuffer): Promise<string> {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
* SHA-256
|
|
79
|
-
*
|
|
78
|
+
* SHA-256 as 64 lowercase hexadecimal digits: of bytes exactly as given, or of a text's UTF-8 bytes
|
|
79
|
+
* (the Cypher source's content hash, a project file's record of a file it loaded). Web Crypto where
|
|
80
|
+
* there is one, else plain JavaScript (a page that is not a secure context). Experimental.
|
|
81
|
+
* @param data - the bytes or the text
|
|
80
82
|
* @returns the digest
|
|
81
83
|
*/
|
|
82
|
-
export function sha256Hex(
|
|
83
|
-
return sha256(utf8(
|
|
84
|
+
export function sha256Hex(data: string | Uint8Array): Promise<string> {
|
|
85
|
+
return sha256(typeof data === "string" ? utf8(data) : data);
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
/**
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SPARQL source's descriptor: catalog data, available without loading the source's code.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { type SourceDescriptor } from "../types.js";
|
|
6
|
+
|
|
7
|
+
/** A small Wikidata query: physics Nobel laureates and their doctoral advisors. */
|
|
8
|
+
const WIKIDATA_ADVISORS = `PREFIX wd: <http://www.wikidata.org/entity/>
|
|
9
|
+
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
|
|
10
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
11
|
+
CONSTRUCT { ?person wdt:P184 ?advisor . ?person rdfs:label ?name . ?advisor rdfs:label ?advisorName . }
|
|
12
|
+
WHERE {
|
|
13
|
+
?person wdt:P166 wd:Q38104 ; wdt:P184 ?advisor ; rdfs:label ?name .
|
|
14
|
+
?advisor rdfs:label ?advisorName .
|
|
15
|
+
FILTER(lang(?name) = "en" && lang(?advisorName) = "en")
|
|
16
|
+
}`;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The descriptor of the `sparql` source. Experimental.
|
|
20
|
+
* @category Network sources
|
|
21
|
+
*/
|
|
22
|
+
export const SPARQL_DESCRIPTOR: SourceDescriptor = Object.freeze({
|
|
23
|
+
plainName: "SPARQL endpoint",
|
|
24
|
+
kind: "sparql",
|
|
25
|
+
version: 1,
|
|
26
|
+
auth: ["basic", "bearer"],
|
|
27
|
+
authRequired: "optional",
|
|
28
|
+
features: ["expand", "probe", "validate", "page"],
|
|
29
|
+
params: [
|
|
30
|
+
{ name: "query", plainName: "Query", type: "query", language: "sparql" },
|
|
31
|
+
{
|
|
32
|
+
name: "mode",
|
|
33
|
+
plainName: "Mode",
|
|
34
|
+
type: "enum",
|
|
35
|
+
values: [
|
|
36
|
+
{ value: "query", label: "Query" },
|
|
37
|
+
{ value: "all", label: "Everything" },
|
|
38
|
+
{ value: "neighborhood", label: "Seed nodes" },
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
{ name: "ids", plainName: "Seed IRIs", type: "node-id" },
|
|
42
|
+
{ name: "language", plainName: "Language", type: "string", advanced: true },
|
|
43
|
+
{ name: "predicates", plainName: "Follow predicates", type: "string", advanced: true },
|
|
44
|
+
{
|
|
45
|
+
name: "pageSize",
|
|
46
|
+
plainName: "Page size",
|
|
47
|
+
type: "integer",
|
|
48
|
+
default: 1000,
|
|
49
|
+
min: 1,
|
|
50
|
+
max: 10000,
|
|
51
|
+
advanced: true,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
samples: [
|
|
55
|
+
{
|
|
56
|
+
id: "wikidata-physics-advisors",
|
|
57
|
+
plainName: "Wikidata: physics Nobel laureates and their advisors",
|
|
58
|
+
endpoint: "https://query.wikidata.org/sparql",
|
|
59
|
+
params: {
|
|
60
|
+
query: WIKIDATA_ADVISORS,
|
|
61
|
+
pageSize: 100,
|
|
62
|
+
language: "en",
|
|
63
|
+
predicates: ["http://www.wikidata.org/prop/direct/"], // NOSONAR(S5332): an RDF namespace IRI, never fetched; Wikidata's IRIs are http
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
});
|