@graphty/graph-io 0.3.46 → 0.3.48
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-wWjCRzKj.js → approximations-C2riR4NT.js} +2 -2
- package/dist/chunks/{approximations-wWjCRzKj.js.map → approximations-C2riR4NT.js.map} +1 -1
- package/dist/chunks/{block-DiGq58c3.js → block-Cu22ewuS.js} +92 -21
- package/dist/chunks/block-Cu22ewuS.js.map +1 -0
- package/dist/chunks/{choose--jM0yYCo.js → choose-Cdx6Enl2.js} +3 -3
- package/dist/chunks/{choose--jM0yYCo.js.map → choose-Cdx6Enl2.js.map} +1 -1
- package/dist/chunks/codes-CV_Bhcyi.js +153 -0
- package/dist/chunks/codes-CV_Bhcyi.js.map +1 -0
- package/dist/chunks/{constants-BKwqelYD.js → constants-D0LqcsLJ.js} +2 -2
- package/dist/chunks/{constants-BKwqelYD.js.map → constants-D0LqcsLJ.js.map} +1 -1
- package/dist/chunks/context-cgmmOxZ2.js +663 -0
- package/dist/chunks/context-cgmmOxZ2.js.map +1 -0
- package/dist/chunks/credentials-BiQsnMTb.js +347 -0
- package/dist/chunks/credentials-BiQsnMTb.js.map +1 -0
- package/dist/chunks/cx-export-BEeF6ymo.js +259 -0
- package/dist/chunks/cx-export-BEeF6ymo.js.map +1 -0
- package/dist/chunks/descriptor-BJ-W0Jd-.js +137 -0
- package/dist/chunks/descriptor-BJ-W0Jd-.js.map +1 -0
- package/dist/chunks/descriptor-C-YDhtsn.js +48 -0
- package/dist/chunks/descriptor-C-YDhtsn.js.map +1 -0
- package/dist/chunks/{emit-CwU8cUmG.js → emit-CD8xnY8s.js} +70 -10
- package/dist/chunks/emit-CD8xnY8s.js.map +1 -0
- package/dist/chunks/{escape-CgzxiYPg.js → escape-DH2Egt-l.js} +12 -12
- package/dist/chunks/{escape-CgzxiYPg.js.map → escape-DH2Egt-l.js.map} +1 -1
- package/dist/chunks/{export-BvqAXCKh.js → export-CZ7VRm4I.js} +53 -1443
- package/dist/chunks/export-CZ7VRm4I.js.map +1 -0
- package/dist/chunks/{exporter-DndFlGSa.js → exporter-BIdaoIgh.js} +7 -6
- package/dist/chunks/{exporter-DndFlGSa.js.map → exporter-BIdaoIgh.js.map} +1 -1
- package/dist/chunks/{exporter-CJgfhF-l.js → exporter-ChjL5fmP.js} +8 -7
- package/dist/chunks/{exporter-CJgfhF-l.js.map → exporter-ChjL5fmP.js.map} +1 -1
- package/dist/chunks/{exporter--Mk9gXCJ.js → exporter-Dcw7Ldtq.js} +6 -4
- package/dist/chunks/{exporter--Mk9gXCJ.js.map → exporter-Dcw7Ldtq.js.map} +1 -1
- package/dist/chunks/exporter-DtVU80Fa.js +1008 -0
- package/dist/chunks/exporter-DtVU80Fa.js.map +1 -0
- package/dist/chunks/{exporter-CrDWIyiq.js → exporter-bxxjOrDZ.js} +11 -9
- package/dist/chunks/{exporter-CrDWIyiq.js.map → exporter-bxxjOrDZ.js.map} +1 -1
- package/dist/chunks/format-BMS-1Nxb.js +64 -0
- package/dist/chunks/format-BMS-1Nxb.js.map +1 -0
- package/dist/chunks/{generic-Dq1ntt9q.js → generic-CP6YD34u.js} +4 -4
- package/dist/chunks/{generic-Dq1ntt9q.js.map → generic-CP6YD34u.js.map} +1 -1
- package/dist/chunks/{importer-DiZRmOQG.js → importer-B87_fmVx.js} +13 -17
- package/dist/chunks/importer-B87_fmVx.js.map +1 -0
- package/dist/chunks/{importer-BSvfrX_h.js → importer-Bji2MeWr.js} +18 -1014
- package/dist/chunks/importer-Bji2MeWr.js.map +1 -0
- package/dist/chunks/{importer-COTK9Tsl.js → importer-CB_zV5_L.js} +14 -11
- package/dist/chunks/importer-CB_zV5_L.js.map +1 -0
- package/dist/chunks/{importer-e6LGpqHB.js → importer-CVT-JyDE.js} +12 -9
- package/dist/chunks/importer-CVT-JyDE.js.map +1 -0
- package/dist/chunks/{importer-yh_aBCU6.js → importer-Cyy6UseH.js} +7 -6
- package/dist/chunks/{importer-yh_aBCU6.js.map → importer-Cyy6UseH.js.map} +1 -1
- package/dist/chunks/{importer-iFYPEKaJ.js → importer-DPZDN40-.js} +14 -10
- package/dist/chunks/{importer-iFYPEKaJ.js.map → importer-DPZDN40-.js.map} +1 -1
- package/dist/chunks/{importer-CMmeMWlC.js → importer-e3huMZbm.js} +8 -260
- package/dist/chunks/importer-e3huMZbm.js.map +1 -0
- package/dist/chunks/input-Ccg9I22A.js +1397 -0
- package/dist/chunks/input-Ccg9I22A.js.map +1 -0
- package/dist/chunks/{json-elements-DJZRZ6jd.js → json-elements-By172SVq.js} +4 -4
- package/dist/chunks/{json-elements-DJZRZ6jd.js.map → json-elements-By172SVq.js.map} +1 -1
- package/dist/chunks/{lexicon-CT69Kd87.js → lexicon-u2SI5xcx.js} +19 -5
- package/dist/chunks/lexicon-u2SI5xcx.js.map +1 -0
- package/dist/chunks/{ontology-export-G4MqRdux.js → ontology-export-BwgMyuF0.js} +4 -3
- package/dist/chunks/{ontology-export-G4MqRdux.js.map → ontology-export-BwgMyuF0.js.map} +1 -1
- package/dist/chunks/{records-CiaWZrFH.js → records-Cgvxz-Vx.js} +2 -2
- package/dist/chunks/{records-CiaWZrFH.js.map → records-Cgvxz-Vx.js.map} +1 -1
- package/dist/chunks/{format-BpQBx8MZ.js → report-CgdsL9Hb.js} +72 -129
- package/dist/chunks/report-CgdsL9Hb.js.map +1 -0
- package/dist/chunks/sigv4-LkAzsLAu.js +247 -0
- package/dist/chunks/sigv4-LkAzsLAu.js.map +1 -0
- package/dist/chunks/{styles-BQnsga7p.js → styles-CaABMoO1.js} +76 -43
- package/dist/chunks/styles-CaABMoO1.js.map +1 -0
- package/dist/chunks/{styles-D3fRphrO.js → styles-P_gmFAOi.js} +101 -21
- package/dist/chunks/styles-P_gmFAOi.js.map +1 -0
- package/dist/chunks/{styles-yed-BF5x3_Y5.js → styles-yed-Cs1nmrjn.js} +60 -20
- package/dist/chunks/styles-yed-Cs1nmrjn.js.map +1 -0
- package/dist/chunks/{text-CzJNFOS9.js → text-BuKQVMz2.js} +2 -2
- package/dist/chunks/{text-CzJNFOS9.js.map → text-BuKQVMz2.js.map} +1 -1
- package/dist/chunks/{writer-DMKvthQE.js → writer-DvHTl36J.js} +5 -4
- package/dist/chunks/writer-DvHTl36J.js.map +1 -0
- package/dist/csv.js +7 -5
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +5 -4
- package/dist/cx.js.map +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +2 -2
- package/dist/gexf.js +7 -5
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +16 -13
- package/dist/gml.js.map +1 -1
- package/dist/graph-io.js +1181 -224
- package/dist/graph-io.js.map +1 -1
- package/dist/graphml.js +3 -3
- package/dist/json.js +1 -1
- package/dist/neo4j.js +6 -4
- package/dist/neo4j.js.map +1 -1
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/sources-cypher.d.ts +1 -0
- package/dist/sources-cypher.js +1236 -0
- package/dist/sources-cypher.js.map +1 -0
- package/dist/sources-ndex.d.ts +1 -0
- package/dist/sources-ndex.js +278 -0
- package/dist/sources-ndex.js.map +1 -0
- package/dist/sources-rest.d.ts +1 -0
- package/dist/sources-rest.js +1367 -0
- package/dist/sources-rest.js.map +1 -0
- package/dist/src/common/report.d.ts +6 -3
- package/dist/src/common/report.d.ts.map +1 -1
- package/dist/src/common/report.js +15 -9
- package/dist/src/common/report.js.map +1 -1
- package/dist/src/formats/cx/styles.d.ts.map +1 -1
- package/dist/src/formats/cx/styles.js +1 -0
- package/dist/src/formats/cx/styles.js.map +1 -1
- package/dist/src/formats/dot/styles.d.ts.map +1 -1
- package/dist/src/formats/dot/styles.js +3 -1
- package/dist/src/formats/dot/styles.js.map +1 -1
- package/dist/src/formats/gexf/styles.d.ts +29 -12
- package/dist/src/formats/gexf/styles.d.ts.map +1 -1
- package/dist/src/formats/gexf/styles.js +160 -31
- package/dist/src/formats/gexf/styles.js.map +1 -1
- package/dist/src/formats/gml/styles.d.ts.map +1 -1
- package/dist/src/formats/gml/styles.js +5 -4
- 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 +3 -3
- package/dist/src/formats/graphml/styles-plain.js.map +1 -1
- package/dist/src/formats/graphml/styles-yed.d.ts.map +1 -1
- package/dist/src/formats/graphml/styles-yed.js +89 -19
- package/dist/src/formats/graphml/styles-yed.js.map +1 -1
- package/dist/src/formats/pajek/styles.d.ts.map +1 -1
- package/dist/src/formats/pajek/styles.js +1 -0
- package/dist/src/formats/pajek/styles.js.map +1 -1
- package/dist/src/formats/xgmml/styles.d.ts.map +1 -1
- package/dist/src/formats/xgmml/styles.js +1 -0
- package/dist/src/formats/xgmml/styles.js.map +1 -1
- package/dist/src/index.d.ts +8 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/registry.d.ts +173 -1
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +196 -1
- package/dist/src/registry.js.map +1 -1
- package/dist/src/sources/builtins.d.ts +11 -0
- package/dist/src/sources/builtins.d.ts.map +1 -0
- package/dist/src/sources/builtins.js +47 -0
- package/dist/src/sources/builtins.js.map +1 -0
- package/dist/src/sources/codes.d.ts +230 -0
- package/dist/src/sources/codes.d.ts.map +1 -0
- package/dist/src/sources/codes.js +58 -0
- package/dist/src/sources/codes.js.map +1 -0
- package/dist/src/sources/context.d.ts +112 -0
- package/dist/src/sources/context.d.ts.map +1 -0
- package/dist/src/sources/context.js +739 -0
- package/dist/src/sources/context.js.map +1 -0
- package/dist/src/sources/credentials.d.ts +179 -0
- package/dist/src/sources/credentials.d.ts.map +1 -0
- package/dist/src/sources/credentials.js +301 -0
- package/dist/src/sources/credentials.js.map +1 -0
- package/dist/src/sources/cypher/descriptor.d.ts +21 -0
- package/dist/src/sources/cypher/descriptor.d.ts.map +1 -0
- package/dist/src/sources/cypher/descriptor.js +119 -0
- package/dist/src/sources/cypher/descriptor.js.map +1 -0
- package/dist/src/sources/cypher/flatten.d.ts +72 -0
- package/dist/src/sources/cypher/flatten.d.ts.map +1 -0
- package/dist/src/sources/cypher/flatten.js +279 -0
- package/dist/src/sources/cypher/flatten.js.map +1 -0
- package/dist/src/sources/cypher/index.d.ts +33 -0
- package/dist/src/sources/cypher/index.d.ts.map +1 -0
- package/dist/src/sources/cypher/index.js +405 -0
- package/dist/src/sources/cypher/index.js.map +1 -0
- package/dist/src/sources/cypher/params.d.ts +40 -0
- package/dist/src/sources/cypher/params.d.ts.map +1 -0
- package/dist/src/sources/cypher/params.js +6 -0
- package/dist/src/sources/cypher/params.js.map +1 -0
- package/dist/src/sources/cypher/profiles.d.ts +44 -0
- package/dist/src/sources/cypher/profiles.d.ts.map +1 -0
- package/dist/src/sources/cypher/profiles.js +61 -0
- package/dist/src/sources/cypher/profiles.js.map +1 -0
- package/dist/src/sources/cypher/query-builder.d.ts +106 -0
- package/dist/src/sources/cypher/query-builder.d.ts.map +1 -0
- package/dist/src/sources/cypher/query-builder.js +236 -0
- package/dist/src/sources/cypher/query-builder.js.map +1 -0
- package/dist/src/sources/cypher/transports/bolt.d.ts +21 -0
- package/dist/src/sources/cypher/transports/bolt.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/bolt.js +185 -0
- package/dist/src/sources/cypher/transports/bolt.js.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.d.ts +15 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.js +38 -0
- package/dist/src/sources/cypher/transports/neptune-analytics.js.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-https.d.ts +31 -0
- package/dist/src/sources/cypher/transports/neptune-https.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/neptune-https.js +104 -0
- package/dist/src/sources/cypher/transports/neptune-https.js.map +1 -0
- package/dist/src/sources/cypher/transports/query-api.d.ts +14 -0
- package/dist/src/sources/cypher/transports/query-api.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/query-api.js +80 -0
- package/dist/src/sources/cypher/transports/query-api.js.map +1 -0
- package/dist/src/sources/cypher/transports/transport.d.ts +78 -0
- package/dist/src/sources/cypher/transports/transport.d.ts.map +1 -0
- package/dist/src/sources/cypher/transports/transport.js +77 -0
- package/dist/src/sources/cypher/transports/transport.js.map +1 -0
- package/dist/src/sources/cypher/types-map.d.ts +91 -0
- package/dist/src/sources/cypher/types-map.d.ts.map +1 -0
- package/dist/src/sources/cypher/types-map.js +306 -0
- package/dist/src/sources/cypher/types-map.js.map +1 -0
- package/dist/src/sources/define.d.ts +47 -0
- package/dist/src/sources/define.d.ts.map +1 -0
- package/dist/src/sources/define.js +173 -0
- package/dist/src/sources/define.js.map +1 -0
- package/dist/src/sources/fail.d.ts +33 -0
- package/dist/src/sources/fail.d.ts.map +1 -0
- package/dist/src/sources/fail.js +49 -0
- package/dist/src/sources/fail.js.map +1 -0
- package/dist/src/sources/ids.d.ts +64 -0
- package/dist/src/sources/ids.d.ts.map +1 -0
- package/dist/src/sources/ids.js +64 -0
- package/dist/src/sources/ids.js.map +1 -0
- package/dist/src/sources/ndex/client.d.ts +31 -0
- package/dist/src/sources/ndex/client.d.ts.map +1 -0
- package/dist/src/sources/ndex/client.js +90 -0
- package/dist/src/sources/ndex/client.js.map +1 -0
- package/dist/src/sources/ndex/descriptor.d.ts +10 -0
- package/dist/src/sources/ndex/descriptor.d.ts.map +1 -0
- package/dist/src/sources/ndex/descriptor.js +55 -0
- package/dist/src/sources/ndex/descriptor.js.map +1 -0
- package/dist/src/sources/ndex/expand.d.ts +20 -0
- package/dist/src/sources/ndex/expand.d.ts.map +1 -0
- package/dist/src/sources/ndex/expand.js +87 -0
- package/dist/src/sources/ndex/expand.js.map +1 -0
- package/dist/src/sources/ndex/index.d.ts +25 -0
- package/dist/src/sources/ndex/index.d.ts.map +1 -0
- package/dist/src/sources/ndex/index.js +191 -0
- package/dist/src/sources/ndex/index.js.map +1 -0
- package/dist/src/sources/ndex/params.d.ts +17 -0
- package/dist/src/sources/ndex/params.d.ts.map +1 -0
- package/dist/src/sources/ndex/params.js +6 -0
- package/dist/src/sources/ndex/params.js.map +1 -0
- package/dist/src/sources/ndex/share-url.d.ts +40 -0
- package/dist/src/sources/ndex/share-url.d.ts.map +1 -0
- package/dist/src/sources/ndex/share-url.js +64 -0
- package/dist/src/sources/ndex/share-url.js.map +1 -0
- package/dist/src/sources/params.d.ts +28 -0
- package/dist/src/sources/params.d.ts.map +1 -0
- package/dist/src/sources/params.js +6 -0
- package/dist/src/sources/params.js.map +1 -0
- package/dist/src/sources/registry.d.ts +118 -0
- package/dist/src/sources/registry.d.ts.map +1 -0
- package/dist/src/sources/registry.js +193 -0
- package/dist/src/sources/registry.js.map +1 -0
- package/dist/src/sources/rest/descriptor.d.ts +16 -0
- package/dist/src/sources/rest/descriptor.d.ts.map +1 -0
- package/dist/src/sources/rest/descriptor.js +71 -0
- package/dist/src/sources/rest/descriptor.js.map +1 -0
- package/dist/src/sources/rest/index.d.ts +14 -0
- package/dist/src/sources/rest/index.d.ts.map +1 -0
- package/dist/src/sources/rest/index.js +13 -0
- package/dist/src/sources/rest/index.js.map +1 -0
- package/dist/src/sources/rest/mapping.d.ts +30 -0
- package/dist/src/sources/rest/mapping.d.ts.map +1 -0
- package/dist/src/sources/rest/mapping.js +362 -0
- package/dist/src/sources/rest/mapping.js.map +1 -0
- package/dist/src/sources/rest/openalex.d.ts +27 -0
- package/dist/src/sources/rest/openalex.d.ts.map +1 -0
- package/dist/src/sources/rest/openalex.js +269 -0
- package/dist/src/sources/rest/openalex.js.map +1 -0
- package/dist/src/sources/rest/paging.d.ts +53 -0
- package/dist/src/sources/rest/paging.d.ts.map +1 -0
- package/dist/src/sources/rest/paging.js +138 -0
- package/dist/src/sources/rest/paging.js.map +1 -0
- package/dist/src/sources/rest/params.d.ts +216 -0
- package/dist/src/sources/rest/params.d.ts.map +1 -0
- package/dist/src/sources/rest/params.js +7 -0
- package/dist/src/sources/rest/params.js.map +1 -0
- package/dist/src/sources/rest/records.d.ts +41 -0
- package/dist/src/sources/rest/records.d.ts.map +1 -0
- package/dist/src/sources/rest/records.js +240 -0
- package/dist/src/sources/rest/records.js.map +1 -0
- package/dist/src/sources/rest/samples/deps-dev.d.ts +10 -0
- package/dist/src/sources/rest/samples/deps-dev.d.ts.map +1 -0
- package/dist/src/sources/rest/samples/deps-dev.js +47 -0
- package/dist/src/sources/rest/samples/deps-dev.js.map +1 -0
- package/dist/src/sources/rest/samples/string.d.ts +9 -0
- package/dist/src/sources/rest/samples/string.d.ts.map +1 -0
- package/dist/src/sources/rest/samples/string.js +42 -0
- package/dist/src/sources/rest/samples/string.js.map +1 -0
- package/dist/src/sources/rest/selectors.d.ts +41 -0
- package/dist/src/sources/rest/selectors.d.ts.map +1 -0
- package/dist/src/sources/rest/selectors.js +81 -0
- package/dist/src/sources/rest/selectors.js.map +1 -0
- package/dist/src/sources/rest/source.d.ts +67 -0
- package/dist/src/sources/rest/source.d.ts.map +1 -0
- package/dist/src/sources/rest/source.js +635 -0
- package/dist/src/sources/rest/source.js.map +1 -0
- package/dist/src/sources/rest/templates.d.ts +38 -0
- package/dist/src/sources/rest/templates.d.ts.map +1 -0
- package/dist/src/sources/rest/templates.js +125 -0
- package/dist/src/sources/rest/templates.js.map +1 -0
- package/dist/src/sources/run.d.ts +93 -0
- package/dist/src/sources/run.d.ts.map +1 -0
- package/dist/src/sources/run.js +673 -0
- package/dist/src/sources/run.js.map +1 -0
- package/dist/src/sources/sha256.d.ts +12 -0
- package/dist/src/sources/sha256.d.ts.map +1 -0
- package/dist/src/sources/sha256.js +95 -0
- package/dist/src/sources/sha256.js.map +1 -0
- package/dist/src/sources/sigv4.d.ts +24 -0
- package/dist/src/sources/sigv4.d.ts.map +1 -0
- package/dist/src/sources/sigv4.js +182 -0
- package/dist/src/sources/sigv4.js.map +1 -0
- package/dist/src/sources/testing.d.ts +96 -0
- package/dist/src/sources/testing.d.ts.map +1 -0
- package/dist/src/sources/testing.js +138 -0
- package/dist/src/sources/testing.js.map +1 -0
- package/dist/src/sources/types.d.ts +665 -0
- package/dist/src/sources/types.d.ts.map +1 -0
- package/dist/src/sources/types.js +10 -0
- package/dist/src/sources/types.js.map +1 -0
- package/dist/src/styles/canon/enums.d.ts.map +1 -1
- package/dist/src/styles/canon/enums.js +1 -0
- package/dist/src/styles/canon/enums.js.map +1 -1
- package/dist/src/styles/cyjs/cascade.d.ts.map +1 -1
- package/dist/src/styles/cyjs/cascade.js +68 -2
- 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 +2 -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 +18 -7
- package/dist/src/styles/cyjs/emit.js.map +1 -1
- package/dist/src/styles/cyjs/mappers.d.ts +4 -1
- package/dist/src/styles/cyjs/mappers.d.ts.map +1 -1
- package/dist/src/styles/cyjs/mappers.js +2 -0
- package/dist/src/styles/cyjs/mappers.js.map +1 -1
- package/dist/src/styles/cytoscape/emit.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/emit.js +59 -7
- package/dist/src/styles/cytoscape/emit.js.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.d.ts +6 -0
- package/dist/src/styles/cytoscape/lexicon.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/lexicon.js +26 -2
- package/dist/src/styles/cytoscape/lexicon.js.map +1 -1
- package/dist/src/styles/cytoscape/resolve.d.ts +4 -1
- package/dist/src/styles/cytoscape/resolve.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/resolve.js +10 -6
- package/dist/src/styles/cytoscape/resolve.js.map +1 -1
- package/dist/src/styles/cytoscape/translate.d.ts.map +1 -1
- package/dist/src/styles/cytoscape/translate.js +10 -10
- package/dist/src/styles/cytoscape/translate.js.map +1 -1
- package/dist/src/styles/defaults.d.ts +30 -0
- package/dist/src/styles/defaults.d.ts.map +1 -1
- package/dist/src/styles/defaults.js +45 -4
- package/dist/src/styles/defaults.js.map +1 -1
- package/dist/src/styles/io/block.d.ts.map +1 -1
- package/dist/src/styles/io/block.js +9 -0
- package/dist/src/styles/io/block.js.map +1 -1
- package/dist/src/styles/io/writer.d.ts.map +1 -1
- package/dist/src/styles/io/writer.js +7 -3
- package/dist/src/styles/io/writer.js.map +1 -1
- package/dist/src/styles/plan/resolve.d.ts +2 -1
- package/dist/src/styles/plan/resolve.d.ts.map +1 -1
- package/dist/src/styles/plan/resolve.js +13 -2
- package/dist/src/styles/plan/resolve.js.map +1 -1
- package/dist/src/styles/types.d.ts +19 -2
- package/dist/src/styles/types.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.d.ts.map +1 -1
- package/dist/src/styles/vocabulary.js +15 -1
- package/dist/src/styles/vocabulary.js.map +1 -1
- package/dist/src/types.d.ts +19 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/styles.js +11 -11
- package/dist/xgmml.js +3 -3
- package/docs/samples/people.json +6 -0
- package/package.json +29 -4
- package/src/common/report.ts +27 -7
- package/src/formats/cx/styles.ts +1 -0
- package/src/formats/dot/styles.ts +3 -1
- package/src/formats/gexf/styles.ts +185 -37
- package/src/formats/gml/styles.ts +5 -4
- package/src/formats/graphml/styles-plain.ts +3 -9
- package/src/formats/graphml/styles-yed.ts +93 -20
- package/src/formats/pajek/styles.ts +1 -0
- package/src/formats/xgmml/styles.ts +1 -0
- package/src/index.ts +90 -0
- package/src/registry.ts +326 -1
- package/src/sources/builtins.ts +56 -0
- package/src/sources/codes.ts +235 -0
- package/src/sources/context.ts +893 -0
- package/src/sources/credentials.ts +409 -0
- package/src/sources/cypher/descriptor.ts +125 -0
- package/src/sources/cypher/flatten.ts +323 -0
- package/src/sources/cypher/index.ts +498 -0
- package/src/sources/cypher/params.ts +41 -0
- package/src/sources/cypher/profiles.ts +78 -0
- package/src/sources/cypher/query-builder.ts +294 -0
- package/src/sources/cypher/transports/bolt.ts +228 -0
- package/src/sources/cypher/transports/neptune-analytics.ts +41 -0
- package/src/sources/cypher/transports/neptune-https.ts +122 -0
- package/src/sources/cypher/transports/query-api.ts +100 -0
- package/src/sources/cypher/transports/transport.ts +139 -0
- package/src/sources/cypher/types-map.ts +418 -0
- package/src/sources/define.ts +195 -0
- package/src/sources/fail.ts +70 -0
- package/src/sources/ids.ts +74 -0
- package/src/sources/ndex/client.ts +102 -0
- package/src/sources/ndex/descriptor.ts +64 -0
- package/src/sources/ndex/expand.ts +100 -0
- package/src/sources/ndex/index.ts +235 -0
- package/src/sources/ndex/params.ts +17 -0
- package/src/sources/ndex/share-url.ts +84 -0
- package/src/sources/params.ts +29 -0
- package/src/sources/registry.ts +325 -0
- package/src/sources/rest/descriptor.ts +74 -0
- package/src/sources/rest/index.ts +22 -0
- package/src/sources/rest/mapping.ts +401 -0
- package/src/sources/rest/openalex.ts +288 -0
- package/src/sources/rest/paging.ts +180 -0
- package/src/sources/rest/params.ts +243 -0
- package/src/sources/rest/records.ts +289 -0
- package/src/sources/rest/samples/deps-dev.ts +49 -0
- package/src/sources/rest/samples/string.ts +44 -0
- package/src/sources/rest/selectors.ts +91 -0
- package/src/sources/rest/source.ts +760 -0
- package/src/sources/rest/templates.ts +151 -0
- package/src/sources/run.ts +793 -0
- package/src/sources/sha256.ts +99 -0
- package/src/sources/sigv4.ts +207 -0
- package/src/sources/testing.ts +210 -0
- package/src/sources/types.ts +741 -0
- package/src/styles/canon/enums.ts +1 -0
- package/src/styles/cyjs/cascade.ts +81 -2
- package/src/styles/cyjs/defaults-table.ts +2 -0
- package/src/styles/cyjs/emit.ts +18 -7
- package/src/styles/cyjs/mappers.ts +6 -1
- package/src/styles/cytoscape/emit.ts +61 -7
- package/src/styles/cytoscape/lexicon.ts +28 -2
- package/src/styles/cytoscape/resolve.ts +22 -6
- package/src/styles/cytoscape/translate.ts +11 -11
- package/src/styles/defaults.ts +93 -4
- package/src/styles/io/block.ts +10 -0
- package/src/styles/io/writer.ts +8 -3
- package/src/styles/plan/resolve.ts +14 -2
- package/src/styles/types.ts +28 -2
- package/src/styles/vocabulary.ts +15 -1
- package/src/types.ts +19 -5
- package/dist/chunks/block-DiGq58c3.js.map +0 -1
- package/dist/chunks/emit-CwU8cUmG.js.map +0 -1
- package/dist/chunks/export-BvqAXCKh.js.map +0 -1
- package/dist/chunks/format-BpQBx8MZ.js.map +0 -1
- package/dist/chunks/importer-BSvfrX_h.js.map +0 -1
- package/dist/chunks/importer-CMmeMWlC.js.map +0 -1
- package/dist/chunks/importer-COTK9Tsl.js.map +0 -1
- package/dist/chunks/importer-DiZRmOQG.js.map +0 -1
- package/dist/chunks/importer-e6LGpqHB.js.map +0 -1
- package/dist/chunks/lexicon-CT69Kd87.js.map +0 -1
- package/dist/chunks/styles-BQnsga7p.js.map +0 -1
- package/dist/chunks/styles-D3fRphrO.js.map +0 -1
- package/dist/chunks/styles-yed-BF5x3_Y5.js.map +0 -1
- package/dist/chunks/writer-DMKvthQE.js.map +0 -1
|
@@ -0,0 +1,1236 @@
|
|
|
1
|
+
import { b as throwIfAborted } from "./chunks/input-Ccg9I22A.js";
|
|
2
|
+
import { P as PRECISION_CODE, ah as ImportError } from "./chunks/report-CgdsL9Hb.js";
|
|
3
|
+
import { C as CYPHER_DESCRIPTOR, N as NEO4J_DESCRIPTOR, a as NEPTUNE_DESCRIPTOR, S as SOURCE_ISSUE } from "./chunks/codes-CV_Bhcyi.js";
|
|
4
|
+
import { w as warnOn, f as failOn, n as SOURCE_DEGREE_ATTR, b as failAlone, o as originOf, u as unwrapCredential, d as defineSource, C as CYPHER_SOURCE_ID, g as NEO4J_SOURCE_ID, h as NEPTUNE_SOURCE_ID } from "./chunks/credentials-BiQsnMTb.js";
|
|
5
|
+
import { sha256Hex } from "./chunks/sigv4-LkAzsLAu.js";
|
|
6
|
+
import { INVALID_INDEX } from "@graphty/graph-format";
|
|
7
|
+
import { t as transportOptions, i as isLoopback } from "./chunks/context-cgmmOxZ2.js";
|
|
8
|
+
class GraphNode {
|
|
9
|
+
/**
|
|
10
|
+
* Create one.
|
|
11
|
+
* @param id - the server's element id
|
|
12
|
+
* @param labels - its labels
|
|
13
|
+
* @param properties - its mapped properties
|
|
14
|
+
*/
|
|
15
|
+
constructor(id, labels, properties) {
|
|
16
|
+
this.id = id;
|
|
17
|
+
this.labels = labels;
|
|
18
|
+
this.properties = properties;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class GraphRel {
|
|
22
|
+
/**
|
|
23
|
+
* Create one.
|
|
24
|
+
* @param id - the server's element id
|
|
25
|
+
* @param start - the start node's element id
|
|
26
|
+
* @param end - the end node's element id
|
|
27
|
+
* @param type - its type
|
|
28
|
+
* @param properties - its mapped properties
|
|
29
|
+
*/
|
|
30
|
+
constructor(id, start, end, type, properties) {
|
|
31
|
+
this.id = id;
|
|
32
|
+
this.start = start;
|
|
33
|
+
this.end = end;
|
|
34
|
+
this.type = type;
|
|
35
|
+
this.properties = properties;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
39
|
+
function integer(digits, column2, m) {
|
|
40
|
+
let big;
|
|
41
|
+
try {
|
|
42
|
+
big = BigInt(digits);
|
|
43
|
+
} catch {
|
|
44
|
+
return Number(digits);
|
|
45
|
+
}
|
|
46
|
+
if (big <= SAFE && big >= -SAFE) {
|
|
47
|
+
return Number(big);
|
|
48
|
+
}
|
|
49
|
+
if (m.long === "string") {
|
|
50
|
+
return big.toString();
|
|
51
|
+
}
|
|
52
|
+
m.report.warnOnce(
|
|
53
|
+
"precision",
|
|
54
|
+
PRECISION_CODE,
|
|
55
|
+
`column ${column2}: an integer beyond 2^53 was stored as the nearest 64-bit float; pass long: "string" to keep every digit`,
|
|
56
|
+
void 0,
|
|
57
|
+
`${PRECISION_CODE}:${column2}`
|
|
58
|
+
);
|
|
59
|
+
return Number(big);
|
|
60
|
+
}
|
|
61
|
+
function epoch(text, type, column2, m) {
|
|
62
|
+
const ms = Date.parse(withoutZoneName(text));
|
|
63
|
+
if (Number.isNaN(ms)) {
|
|
64
|
+
warnOn(m.report, "W_SOURCE_VALUE", `column ${column2}: a ${type} kept as text`, { type, column: column2, as: "string" });
|
|
65
|
+
return text;
|
|
66
|
+
}
|
|
67
|
+
return ms;
|
|
68
|
+
}
|
|
69
|
+
function dropped(type, column2, m) {
|
|
70
|
+
warnOn(m.report, "W_SOURCE_VALUE", `column ${column2}: a ${type} value was dropped`, {
|
|
71
|
+
type,
|
|
72
|
+
column: column2,
|
|
73
|
+
as: "dropped"
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function mapEntries(value, each) {
|
|
77
|
+
const out = {};
|
|
78
|
+
for (const [k, v] of Object.entries(value)) {
|
|
79
|
+
const mapped = each(v, k);
|
|
80
|
+
if (mapped !== void 0) {
|
|
81
|
+
out[k] = mapped;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function wktPoint(text) {
|
|
87
|
+
const match = /^SRID=(\d+);POINT(?: Z)? ?\(([^)]*)\)$/i.exec(text.trim());
|
|
88
|
+
if (match === null) {
|
|
89
|
+
return text;
|
|
90
|
+
}
|
|
91
|
+
const [x = 0, y = 0, z] = match[2].trim().split(/\s+/).map(Number);
|
|
92
|
+
return z === void 0 ? { srid: Number(match[1]), x, y } : { srid: Number(match[1]), x, y, z };
|
|
93
|
+
}
|
|
94
|
+
function fromTypedJson(v, column2, m) {
|
|
95
|
+
if (v === null || typeof v !== "object" || !("$type" in v)) {
|
|
96
|
+
return v ?? null;
|
|
97
|
+
}
|
|
98
|
+
const { $type: type, _value: value } = v;
|
|
99
|
+
switch (type) {
|
|
100
|
+
case "Null":
|
|
101
|
+
return null;
|
|
102
|
+
case "Boolean":
|
|
103
|
+
case "String":
|
|
104
|
+
return value;
|
|
105
|
+
case "Integer":
|
|
106
|
+
return integer(String(value), column2, m);
|
|
107
|
+
case "Float":
|
|
108
|
+
return Number(value);
|
|
109
|
+
case "Date":
|
|
110
|
+
return epoch(`${String(value)}T00:00:00Z`, type, column2, m);
|
|
111
|
+
case "OffsetDateTime":
|
|
112
|
+
case "ZonedDateTime":
|
|
113
|
+
return epoch(String(value), type, column2, m);
|
|
114
|
+
case "LocalDateTime":
|
|
115
|
+
case "LocalTime":
|
|
116
|
+
case "Time":
|
|
117
|
+
case "Duration":
|
|
118
|
+
return String(value);
|
|
119
|
+
case "Point":
|
|
120
|
+
return wktPoint(String(value));
|
|
121
|
+
case "Base64":
|
|
122
|
+
dropped(type, column2, m);
|
|
123
|
+
return void 0;
|
|
124
|
+
case "List":
|
|
125
|
+
return value.map((x) => fromTypedJson(x, column2, m));
|
|
126
|
+
case "Map":
|
|
127
|
+
return mapEntries(value, (x) => fromTypedJson(x, column2, m));
|
|
128
|
+
case "Node": {
|
|
129
|
+
const n = value;
|
|
130
|
+
return new GraphNode(
|
|
131
|
+
n._element_id,
|
|
132
|
+
n._labels,
|
|
133
|
+
mapEntries(n._properties, (x, k) => fromTypedJson(x, k, m))
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
case "Relationship": {
|
|
137
|
+
const r = value;
|
|
138
|
+
return new GraphRel(
|
|
139
|
+
r._element_id,
|
|
140
|
+
r._start_node_element_id,
|
|
141
|
+
r._end_node_element_id,
|
|
142
|
+
r._type,
|
|
143
|
+
mapEntries(r._properties, (x, k) => fromTypedJson(x, k, m))
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
case "Path":
|
|
147
|
+
return value.map((x) => fromTypedJson(x, column2, m));
|
|
148
|
+
default:
|
|
149
|
+
warnOn(m.report, "W_SOURCE_VALUE", `column ${column2}: a ${type} kept as text`, {
|
|
150
|
+
type,
|
|
151
|
+
column: column2,
|
|
152
|
+
as: "string"
|
|
153
|
+
});
|
|
154
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function withoutZoneName(text) {
|
|
158
|
+
const end = text.length - 1;
|
|
159
|
+
if (text[end] !== "]") {
|
|
160
|
+
return text;
|
|
161
|
+
}
|
|
162
|
+
const open2 = text.indexOf("[", text.lastIndexOf("]", end - 1) + 1);
|
|
163
|
+
return open2 === -1 || open2 >= end ? text : text.slice(0, open2);
|
|
164
|
+
}
|
|
165
|
+
function fromEntity(e, node, m, t) {
|
|
166
|
+
const props = mapEntries(e.properties, (x, k) => fromDriver(x, k, m, t));
|
|
167
|
+
const id = e.elementId ?? String(e.identity);
|
|
168
|
+
return node ? new GraphNode(id, [...e.labels ?? []], props) : new GraphRel(
|
|
169
|
+
id,
|
|
170
|
+
e.startNodeElementId ?? String(e.start),
|
|
171
|
+
e.endNodeElementId ?? String(e.end),
|
|
172
|
+
e.type ?? "",
|
|
173
|
+
props
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
function fromPoint(p) {
|
|
177
|
+
const srid = Number(String(p.srid));
|
|
178
|
+
return p.z === void 0 ? { srid, x: p.x, y: p.y } : { srid, x: p.x, y: p.y, z: p.z };
|
|
179
|
+
}
|
|
180
|
+
function fromDriver(v, column2, m, t) {
|
|
181
|
+
if (v === null || v === void 0) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
if (typeof v !== "object") {
|
|
185
|
+
return typeof v === "bigint" ? integer(v.toString(), column2, m) : v;
|
|
186
|
+
}
|
|
187
|
+
const text = () => v.toString();
|
|
188
|
+
if (t.isInt(v)) {
|
|
189
|
+
return integer(text(), column2, m);
|
|
190
|
+
}
|
|
191
|
+
if (t.isNode(v) || t.isRelationship(v)) {
|
|
192
|
+
return fromEntity(v, t.isNode(v), m, t);
|
|
193
|
+
}
|
|
194
|
+
if (t.isPath(v)) {
|
|
195
|
+
const p = v;
|
|
196
|
+
return [p.start, ...p.segments.flatMap((s) => [s.relationship, s.end])].map((x) => fromDriver(x, column2, m, t));
|
|
197
|
+
}
|
|
198
|
+
if (t.isDate(v)) {
|
|
199
|
+
return epoch(`${text()}T00:00:00Z`, "Date", column2, m);
|
|
200
|
+
}
|
|
201
|
+
if (t.isDateTime(v)) {
|
|
202
|
+
return epoch(text(), "DateTime", column2, m);
|
|
203
|
+
}
|
|
204
|
+
if (t.isLocalDateTime(v) || t.isLocalTime(v) || t.isTime(v) || t.isDuration(v)) {
|
|
205
|
+
return text();
|
|
206
|
+
}
|
|
207
|
+
if (t.isPoint(v)) {
|
|
208
|
+
return fromPoint(v);
|
|
209
|
+
}
|
|
210
|
+
if (v instanceof Uint8Array || v instanceof ArrayBuffer) {
|
|
211
|
+
dropped("ByteArray", column2, m);
|
|
212
|
+
return void 0;
|
|
213
|
+
}
|
|
214
|
+
if (Array.isArray(v)) {
|
|
215
|
+
return v.map((x) => fromDriver(x, column2, m, t));
|
|
216
|
+
}
|
|
217
|
+
return mapEntries(v, (x) => fromDriver(x, column2, m, t));
|
|
218
|
+
}
|
|
219
|
+
function fromNeptune(v, column2, m) {
|
|
220
|
+
if (typeof v === "number" && Number.isInteger(v) && !Number.isSafeInteger(v)) {
|
|
221
|
+
return integer(BigInt(v).toString(), column2, m);
|
|
222
|
+
}
|
|
223
|
+
if (v === null || typeof v !== "object") {
|
|
224
|
+
return v ?? null;
|
|
225
|
+
}
|
|
226
|
+
if (Array.isArray(v)) {
|
|
227
|
+
return v.map((x) => fromNeptune(x, column2, m));
|
|
228
|
+
}
|
|
229
|
+
const o = v;
|
|
230
|
+
const props = () => mapEntries(o["~properties"] ?? {}, (x, k) => fromNeptune(x, k, m));
|
|
231
|
+
switch (o["~entityType"]) {
|
|
232
|
+
case "node":
|
|
233
|
+
return new GraphNode(String(o["~id"]), o["~labels"] ?? [], props());
|
|
234
|
+
case "relationship":
|
|
235
|
+
return new GraphRel(String(o["~id"]), String(o["~start"]), String(o["~end"]), String(o["~type"]), props());
|
|
236
|
+
default:
|
|
237
|
+
return mapEntries(o, (x) => fromNeptune(x, column2, m));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const LABELS_COLUMN = "labels";
|
|
241
|
+
const TYPE_COLUMN = "type";
|
|
242
|
+
const LABELS_DECL = {
|
|
243
|
+
name: LABELS_COLUMN,
|
|
244
|
+
dtype: "list",
|
|
245
|
+
itemDtype: "dict",
|
|
246
|
+
nullable: true,
|
|
247
|
+
role: "labels"
|
|
248
|
+
};
|
|
249
|
+
const TYPE_DECL = { name: TYPE_COLUMN, dtype: "dict", nullable: true, role: "kind" };
|
|
250
|
+
const EDGE_ID_DECL = { name: "id", dtype: "string", nullable: true, role: "id" };
|
|
251
|
+
class Collector {
|
|
252
|
+
constructor() {
|
|
253
|
+
this.nodes = /* @__PURE__ */ new Map();
|
|
254
|
+
this.rels = /* @__PURE__ */ new Map();
|
|
255
|
+
this.degrees = /* @__PURE__ */ new Map();
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Collect a result.
|
|
259
|
+
* @param result - the result
|
|
260
|
+
* @param hints - whether its `key` / `degree` / `degrees` columns are the generated queries' hints
|
|
261
|
+
*/
|
|
262
|
+
add(result, hints) {
|
|
263
|
+
const key = hints ? result.fields.indexOf("key") : -1;
|
|
264
|
+
const degree = hints ? result.fields.indexOf("degree") : -1;
|
|
265
|
+
const degrees = hints ? result.fields.indexOf("degrees") : -1;
|
|
266
|
+
for (const row of result.rows) {
|
|
267
|
+
row.forEach((value, i) => {
|
|
268
|
+
if (i === degrees && Array.isArray(value)) {
|
|
269
|
+
for (const pair of value) {
|
|
270
|
+
if (Array.isArray(pair) && typeof pair[1] === "number") {
|
|
271
|
+
this.degrees.set(String(pair[0]), pair[1]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} else if (i !== key && i !== degree) {
|
|
275
|
+
this.visit(value);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
if (key >= 0 && degree >= 0 && typeof row[degree] === "number") {
|
|
279
|
+
this.degrees.set(String(row[key]), row[degree]);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Collect every node and relationship inside a value.
|
|
285
|
+
* @param value - the value
|
|
286
|
+
*/
|
|
287
|
+
visit(value) {
|
|
288
|
+
if (value instanceof GraphNode) {
|
|
289
|
+
this.nodes.set(value.id, value);
|
|
290
|
+
} else if (value instanceof GraphRel) {
|
|
291
|
+
this.rels.set(value.id, value);
|
|
292
|
+
} else if (Array.isArray(value)) {
|
|
293
|
+
value.forEach((v) => {
|
|
294
|
+
this.visit(v);
|
|
295
|
+
});
|
|
296
|
+
} else if (value !== null && typeof value === "object") {
|
|
297
|
+
Object.values(value).forEach((v) => {
|
|
298
|
+
this.visit(v);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Whether nothing was collected.
|
|
304
|
+
* @returns true when no node or relationship was found
|
|
305
|
+
*/
|
|
306
|
+
get empty() {
|
|
307
|
+
return this.nodes.size === 0 && this.rels.size === 0;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function requireGraph(result, collector, report) {
|
|
311
|
+
if (result.rows.length > 0 && collector.empty) {
|
|
312
|
+
failOn(report, "E_SOURCE_NOT_A_GRAPH", "the query returned no node, relationship or path", {
|
|
313
|
+
columns: result.fields
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function nodeIdOf(node, idProperty) {
|
|
318
|
+
const value = idProperty === null ? void 0 : node.properties[idProperty];
|
|
319
|
+
return typeof value === "string" || typeof value === "number" ? value : node.id;
|
|
320
|
+
}
|
|
321
|
+
function column(sink, decl, domain) {
|
|
322
|
+
const existing = domain === "node" ? sink.nodeColumn(decl.name) : sink.edgeColumn(decl.name);
|
|
323
|
+
if (existing !== INVALID_INDEX) {
|
|
324
|
+
return existing;
|
|
325
|
+
}
|
|
326
|
+
return domain === "node" ? sink.declareNodeColumn(decl) : sink.declareEdgeColumn(decl);
|
|
327
|
+
}
|
|
328
|
+
function writeCollected(c, sink, idProperty, report, signal) {
|
|
329
|
+
if (sink.edgeCount === 0 && !sink.directedLocked && !sink.directed) {
|
|
330
|
+
sink.setDirected(true);
|
|
331
|
+
}
|
|
332
|
+
const ids = writeNodes(c, sink, idProperty, report, signal);
|
|
333
|
+
writeRels(c, sink, ids, report, signal, c.nodes.size);
|
|
334
|
+
}
|
|
335
|
+
function writeNodes(c, sink, idProperty, report, signal) {
|
|
336
|
+
const ids = /* @__PURE__ */ new Map();
|
|
337
|
+
let n = 0;
|
|
338
|
+
for (const node of c.nodes.values()) {
|
|
339
|
+
if (n++ % 64 === 0) {
|
|
340
|
+
throwIfAborted(signal);
|
|
341
|
+
}
|
|
342
|
+
const id = nodeIdOf(node, idProperty);
|
|
343
|
+
ids.set(node.id, id);
|
|
344
|
+
const degree = c.degrees.get(String(idProperty === null ? node.id : id));
|
|
345
|
+
try {
|
|
346
|
+
const fresh = sink.indexOf(id) === INVALID_INDEX;
|
|
347
|
+
const index = sink.addNodeRecord(
|
|
348
|
+
id,
|
|
349
|
+
degree === void 0 ? node.properties : { ...node.properties, [SOURCE_DEGREE_ATTR]: degree }
|
|
350
|
+
);
|
|
351
|
+
sink.setNodeValue(column(sink, LABELS_DECL, "node"), index, node.labels);
|
|
352
|
+
if (fresh) {
|
|
353
|
+
report.counts.nodes++;
|
|
354
|
+
}
|
|
355
|
+
} catch (err) {
|
|
356
|
+
report.recordError(err, { element: String(id) });
|
|
357
|
+
report.counts.skippedNodes++;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return ids;
|
|
361
|
+
}
|
|
362
|
+
function writeRels(c, sink, ids, report, signal, written) {
|
|
363
|
+
let n = written;
|
|
364
|
+
for (const rel of c.rels.values()) {
|
|
365
|
+
if (n++ % 64 === 0) {
|
|
366
|
+
throwIfAborted(signal);
|
|
367
|
+
}
|
|
368
|
+
const s = ids.get(rel.start) ?? rel.start;
|
|
369
|
+
const t = ids.get(rel.end) ?? rel.end;
|
|
370
|
+
try {
|
|
371
|
+
for (const end of [s, t]) {
|
|
372
|
+
if (sink.indexOf(end) === INVALID_INDEX) {
|
|
373
|
+
sink.addNode(end);
|
|
374
|
+
report.counts.nodes++;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const e = sink.addEdgeRecord(s, t, rel.properties, null);
|
|
378
|
+
sink.setEdgeValue(column(sink, TYPE_DECL, "edge"), e, rel.type);
|
|
379
|
+
sink.setEdgeValue(column(sink, EDGE_ID_DECL, "edge"), e, rel.id);
|
|
380
|
+
report.counts.edges++;
|
|
381
|
+
} catch (err) {
|
|
382
|
+
report.recordError(err, { element: `${String(s)} -> ${String(t)}` });
|
|
383
|
+
report.counts.skippedEdges++;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
function compareText(a, b) {
|
|
388
|
+
if (a === b) {
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
return a < b ? -1 : 1;
|
|
392
|
+
}
|
|
393
|
+
function member(key, value) {
|
|
394
|
+
return `${JSON.stringify(key)}:${canonical(value)}`;
|
|
395
|
+
}
|
|
396
|
+
function canonical(value) {
|
|
397
|
+
if (Array.isArray(value)) {
|
|
398
|
+
return `[${value.map(canonical).join(",")}]`;
|
|
399
|
+
}
|
|
400
|
+
if (value !== null && typeof value === "object") {
|
|
401
|
+
const entries = Object.entries(value).sort(([a], [b]) => compareText(a, b));
|
|
402
|
+
const members = entries.map(([k, v]) => member(k, v));
|
|
403
|
+
return `{${members.join(",")}}`;
|
|
404
|
+
}
|
|
405
|
+
return JSON.stringify(value) ?? "null";
|
|
406
|
+
}
|
|
407
|
+
function canonicalRows(c, idProperty) {
|
|
408
|
+
const ids = /* @__PURE__ */ new Map();
|
|
409
|
+
const lines = [];
|
|
410
|
+
for (const node of c.nodes.values()) {
|
|
411
|
+
const id = nodeIdOf(node, idProperty);
|
|
412
|
+
ids.set(node.id, id);
|
|
413
|
+
lines.push(canonical(["n", id, [...node.labels].sort(compareText), node.properties]));
|
|
414
|
+
}
|
|
415
|
+
for (const rel of c.rels.values()) {
|
|
416
|
+
lines.push(
|
|
417
|
+
canonical([
|
|
418
|
+
"r",
|
|
419
|
+
rel.id,
|
|
420
|
+
ids.get(rel.start) ?? rel.start,
|
|
421
|
+
ids.get(rel.end) ?? rel.end,
|
|
422
|
+
rel.type,
|
|
423
|
+
rel.properties
|
|
424
|
+
])
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
return lines;
|
|
428
|
+
}
|
|
429
|
+
function neo4jProfile(version, product = "Neo4j") {
|
|
430
|
+
const major = version === null ? Number.NaN : Number.parseInt(version, 10);
|
|
431
|
+
return {
|
|
432
|
+
name: "neo4j",
|
|
433
|
+
elementIds: Number.isNaN(major) || major >= 5,
|
|
434
|
+
product,
|
|
435
|
+
version,
|
|
436
|
+
readOnly: "enforced"
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function profileFromAgent(agent) {
|
|
440
|
+
const [product = "", version = ""] = agent.split("/");
|
|
441
|
+
if (product.toLowerCase() === "neo4j") {
|
|
442
|
+
return neo4jProfile(version === "" ? null : version);
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
name: "neo4j",
|
|
446
|
+
elementIds: false,
|
|
447
|
+
product,
|
|
448
|
+
version: version === "" ? null : version,
|
|
449
|
+
readOnly: "enforced"
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function neptuneProfile(version = null) {
|
|
453
|
+
return { name: "neptune", elementIds: false, product: "Neptune", version, readOnly: "not-enforced" };
|
|
454
|
+
}
|
|
455
|
+
function serverFacts(profile) {
|
|
456
|
+
return {
|
|
457
|
+
product: profile.product,
|
|
458
|
+
profile: profile.name,
|
|
459
|
+
readOnly: profile.readOnly,
|
|
460
|
+
...profile.version === null ? {} : { version: profile.version }
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const MAX_DEPTH = 10;
|
|
464
|
+
const MAX_PAGE_SIZE = 1e5;
|
|
465
|
+
const DEFAULT_PAGE_SIZE = 1e3;
|
|
466
|
+
function identifierProblem(name) {
|
|
467
|
+
return typeof name !== "string" || name === "" || name.includes("\0") ? "identifier" : null;
|
|
468
|
+
}
|
|
469
|
+
function cypherIdentifier(name) {
|
|
470
|
+
if (identifierProblem(name) !== null) {
|
|
471
|
+
failAlone("E_SOURCE_PARAM", "a Cypher identifier must be a non-empty string without NUL", {
|
|
472
|
+
name: "identifier",
|
|
473
|
+
reason: "identifier"
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
return `\`${name.replaceAll("`", "``")}\``;
|
|
477
|
+
}
|
|
478
|
+
function quoted(name, param, report) {
|
|
479
|
+
if (identifierProblem(name) !== null) {
|
|
480
|
+
failOn(report, "E_SOURCE_PARAM", `parameter ${param}: not a Cypher identifier`, {
|
|
481
|
+
name: param,
|
|
482
|
+
reason: "identifier"
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
return cypherIdentifier(name);
|
|
486
|
+
}
|
|
487
|
+
function checkedInteger(value, name, min, max, report) {
|
|
488
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
489
|
+
failOn(report, "E_SOURCE_PARAM", `parameter ${name}: not an integer`, { name, reason: "type" });
|
|
490
|
+
}
|
|
491
|
+
if (value < min || value > max) {
|
|
492
|
+
failOn(report, "E_SOURCE_PARAM", `parameter ${name}: outside ${String(min)} to ${String(max)}`, {
|
|
493
|
+
name,
|
|
494
|
+
reason: "range"
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
return String(value);
|
|
498
|
+
}
|
|
499
|
+
function idExpression(v, profile, filters, node = true) {
|
|
500
|
+
if (node && filters.idProperty !== null) {
|
|
501
|
+
return `${v}.${filters.idProperty}`;
|
|
502
|
+
}
|
|
503
|
+
return profile.elementIds ? `elementId(${v})` : `id(${v})`;
|
|
504
|
+
}
|
|
505
|
+
function nodePredicate(v, filters) {
|
|
506
|
+
const parts = [];
|
|
507
|
+
if (filters.labels.length > 0) {
|
|
508
|
+
const prefix = `${v}:`;
|
|
509
|
+
parts.push(`(${filters.labels.map((l) => prefix + l).join(" OR ")})`);
|
|
510
|
+
}
|
|
511
|
+
if (filters.idProperty !== null) {
|
|
512
|
+
parts.push(`${v}.${filters.idProperty} IS NOT NULL`);
|
|
513
|
+
}
|
|
514
|
+
return parts.length === 0 ? null : parts.join(" AND ");
|
|
515
|
+
}
|
|
516
|
+
function typesPattern(filters) {
|
|
517
|
+
return filters.relationshipTypes.length === 0 ? "" : `:${filters.relationshipTypes.join("|")}`;
|
|
518
|
+
}
|
|
519
|
+
function degreeOf(v) {
|
|
520
|
+
return `size([(${v})--() | 1])`;
|
|
521
|
+
}
|
|
522
|
+
const ARROWS = { out: ["-", "->"], in: ["<-", "-"], both: ["-", "-"] };
|
|
523
|
+
function nodePage(profile, filters, pageSize, after, degree) {
|
|
524
|
+
const where = nodePredicate("n", filters);
|
|
525
|
+
return [
|
|
526
|
+
"MATCH (n)",
|
|
527
|
+
where === null ? null : `WHERE ${where}`,
|
|
528
|
+
`WITH n, ${idExpression("n", profile, filters)} AS key`,
|
|
529
|
+
after ? "WHERE key > $after" : null,
|
|
530
|
+
degree ? `RETURN n, key, ${degreeOf("n")} AS degree` : "RETURN n, key",
|
|
531
|
+
`ORDER BY key LIMIT ${pageSize}`
|
|
532
|
+
].filter((l) => l !== null).join(" ");
|
|
533
|
+
}
|
|
534
|
+
function edgePage(profile, filters, pageSize, after) {
|
|
535
|
+
const a = nodePredicate("a", filters);
|
|
536
|
+
const b = nodePredicate("b", filters);
|
|
537
|
+
const where = [a, b].filter((p) => p !== null);
|
|
538
|
+
return [
|
|
539
|
+
`MATCH (a)-[r${typesPattern(filters)}]->(b)`,
|
|
540
|
+
where.length === 0 ? null : `WHERE ${where.join(" AND ")}`,
|
|
541
|
+
`WITH a, r, b, ${idExpression("r", profile, filters, false)} AS key`,
|
|
542
|
+
after ? "WHERE key > $after" : null,
|
|
543
|
+
"RETURN a, r, b, key",
|
|
544
|
+
`ORDER BY key LIMIT ${pageSize}`
|
|
545
|
+
].filter((l) => l !== null).join(" ");
|
|
546
|
+
}
|
|
547
|
+
function neighborhood(profile, filters, shape, degree) {
|
|
548
|
+
const rel = `[${typesPattern(filters)}*1..${shape.depth}]`;
|
|
549
|
+
const [left, right] = ARROWS[shape.direction];
|
|
550
|
+
const pattern = `${left}${rel}${right}`;
|
|
551
|
+
const x = nodePredicate("x", filters);
|
|
552
|
+
const degrees = degree ? `, [m IN CASE WHEN p IS NULL THEN [s] ELSE nodes(p) END | [${idExpression("m", profile, filters)}, ${degreeOf("m")}]] AS degrees` : "";
|
|
553
|
+
const head = [
|
|
554
|
+
`MATCH (s) WHERE ${idExpression("s", profile, filters)} IN $ids`,
|
|
555
|
+
`OPTIONAL MATCH p = (s)${pattern}(x)${whereClause(x)}`
|
|
556
|
+
];
|
|
557
|
+
if (shape.limit === null) {
|
|
558
|
+
return [...head, "WITH s, p", `RETURN s, p${degrees}`].join(" ");
|
|
559
|
+
}
|
|
560
|
+
return [
|
|
561
|
+
...head,
|
|
562
|
+
`WITH s, p, ${idExpression("x", profile, filters)} AS key`,
|
|
563
|
+
shape.after === true ? "WHERE key > $after" : null,
|
|
564
|
+
`WITH s, p, key ORDER BY key LIMIT ${shape.limit}`,
|
|
565
|
+
`RETURN s, p, key${degrees}`
|
|
566
|
+
].filter((l) => l !== null).join(" ");
|
|
567
|
+
}
|
|
568
|
+
function whereClause(predicate) {
|
|
569
|
+
return predicate === null ? "" : ` WHERE ${predicate}`;
|
|
570
|
+
}
|
|
571
|
+
function counts(filters) {
|
|
572
|
+
const n = nodePredicate("n", filters);
|
|
573
|
+
const where = [nodePredicate("a", filters), nodePredicate("b", filters)].filter((p) => p !== null);
|
|
574
|
+
return [
|
|
575
|
+
`MATCH (n)${whereClause(n)} RETURN count(n) AS c`,
|
|
576
|
+
`MATCH (a)-[r${typesPattern(filters)}]->(b)${whereClause(where.length === 0 ? null : where.join(" AND "))} RETURN count(r) AS c`
|
|
577
|
+
];
|
|
578
|
+
}
|
|
579
|
+
const MAX_SERVER_MESSAGE = 500;
|
|
580
|
+
function serverError(report, err, origin, database) {
|
|
581
|
+
const code = err.code ?? "";
|
|
582
|
+
if (/Security\.Unauthorized|AuthenticationRateLimit|UnauthorizedException/i.test(code)) {
|
|
583
|
+
return failOn(report, "E_SOURCE_AUTH", `${origin} refused the login`, {
|
|
584
|
+
origin,
|
|
585
|
+
status: err.status,
|
|
586
|
+
scheme: null,
|
|
587
|
+
serverCode: err.code
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
if (/Security\.Forbidden|AccessMode|AccessDenied/i.test(code)) {
|
|
591
|
+
return failOn(report, "E_SOURCE_FORBIDDEN", `${origin} refused the statement`, {
|
|
592
|
+
status: err.status,
|
|
593
|
+
serverCode: err.code
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
if (/TimedOut|Timeout|TimeLimitExceeded/i.test(code)) {
|
|
597
|
+
return failOn(report, "E_SOURCE_TIMEOUT", `${origin} timed the statement out`, {
|
|
598
|
+
timeoutMs: null,
|
|
599
|
+
serverSide: true
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
if (/DatabaseNotFound/i.test(code)) {
|
|
603
|
+
return failOn(report, "E_SOURCE_NOT_FOUND", `${origin} has no database ${String(database)}`, {
|
|
604
|
+
what: "database",
|
|
605
|
+
value: database ?? null
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
const where = /line (\d+), column (\d+)/i.exec(err.message);
|
|
609
|
+
return failOn(report, "E_SOURCE_QUERY", `${origin} refused the query: ${code}`, {
|
|
610
|
+
serverCode: err.code,
|
|
611
|
+
line: where === null ? null : Number(where[1]),
|
|
612
|
+
column: where === null ? null : Number(where[2]),
|
|
613
|
+
serverMessage: err.showable && err.message !== "" ? err.message.slice(0, MAX_SERVER_MESSAGE) : null
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
function parseJson(text) {
|
|
617
|
+
try {
|
|
618
|
+
return JSON.parse(text);
|
|
619
|
+
} catch {
|
|
620
|
+
return null;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
function objectRows(results, map) {
|
|
624
|
+
const fields = [...new Set(results.flatMap((r) => Object.keys(r)))];
|
|
625
|
+
return { fields, rows: results.map((r) => fields.map((f) => map(r[f], f))) };
|
|
626
|
+
}
|
|
627
|
+
const DRIVER_PACKAGE = "neo4j-driver";
|
|
628
|
+
const DIRECT_SCHEMES = /* @__PURE__ */ new Set(["bolt:", "bolt+s:", "bolt+ssc:"]);
|
|
629
|
+
async function loadDriver(input) {
|
|
630
|
+
let mod;
|
|
631
|
+
try {
|
|
632
|
+
mod = await import("neo4j-driver");
|
|
633
|
+
} catch {
|
|
634
|
+
return failOn(input.ctx.report, "E_SOURCE_RUNTIME", `the bolt transport needs ${DRIVER_PACKAGE} installed`, {
|
|
635
|
+
runtime: input.ctx.runtime,
|
|
636
|
+
reason: "needs-peer-dependency",
|
|
637
|
+
package: DRIVER_PACKAGE
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
return mod.default ?? mod;
|
|
641
|
+
}
|
|
642
|
+
function refuseMixedContent(ctx, url) {
|
|
643
|
+
const page = globalThis.location;
|
|
644
|
+
if (ctx.runtime === "browser" && page?.protocol === "https:" && url.protocol === "bolt:" && !isLoopback(url.hostname)) {
|
|
645
|
+
failOn(ctx.report, "E_SOURCE_RUNTIME", "an https page cannot open a plain Bolt WebSocket", {
|
|
646
|
+
runtime: ctx.runtime,
|
|
647
|
+
reason: "insecure-endpoint"
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
async function connection(input, neo4j) {
|
|
652
|
+
const { ctx } = input;
|
|
653
|
+
const { report } = ctx;
|
|
654
|
+
const bad = (reason, message) => failOn(report, "E_SOURCE_PARAM", message, { name: "endpoint", reason });
|
|
655
|
+
const url = ctx.endpoint ?? bad("missing", "the bolt transport needs an endpoint");
|
|
656
|
+
if (!DIRECT_SCHEMES.has(url.protocol)) {
|
|
657
|
+
bad(url.protocol.startsWith("neo4j") ? "routing" : "scheme", `${url.protocol} is not a direct Bolt scheme`);
|
|
658
|
+
}
|
|
659
|
+
refuseMixedContent(ctx, url);
|
|
660
|
+
const { credential, allowInsecure } = transportOptions(ctx);
|
|
661
|
+
const origin = originOf(url);
|
|
662
|
+
const bound = credential !== void 0 && (credential.origins.length === 0 || credential.origins.includes(origin));
|
|
663
|
+
if (!bound || credential === void 0) {
|
|
664
|
+
return { url, auth: void 0 };
|
|
665
|
+
}
|
|
666
|
+
if (url.protocol === "bolt+ssc:") {
|
|
667
|
+
bad("unverified-tls", "bolt+ssc accepts any certificate, so no credential is sent over it");
|
|
668
|
+
}
|
|
669
|
+
if (url.protocol === "bolt:" && !isLoopback(url.hostname) && allowInsecure !== true) {
|
|
670
|
+
bad("insecure-endpoint", "a credential is never sent without TLS");
|
|
671
|
+
}
|
|
672
|
+
const secret = unwrapCredential(credential);
|
|
673
|
+
if (secret !== void 0 && "username" in secret) {
|
|
674
|
+
return { url, auth: neo4j.auth.basic(secret.username, secret.password) };
|
|
675
|
+
}
|
|
676
|
+
if (secret !== void 0 && "token" in secret) {
|
|
677
|
+
const token = typeof secret.token === "string" ? secret.token : await secret.token();
|
|
678
|
+
return { url, auth: neo4j.auth.bearer(token) };
|
|
679
|
+
}
|
|
680
|
+
return failOn(report, "E_SOURCE_PARAM", "the bolt transport takes a basic or bearer credential", {
|
|
681
|
+
name: "credential",
|
|
682
|
+
reason: "kind"
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
async function boltTransport(input) {
|
|
686
|
+
const { ctx, params, m } = input;
|
|
687
|
+
throwIfAborted(ctx.signal);
|
|
688
|
+
const neo4j = await loadDriver(input);
|
|
689
|
+
const { url, auth } = await connection(input, neo4j);
|
|
690
|
+
throwIfAborted(ctx.signal);
|
|
691
|
+
const origin = originOf(url);
|
|
692
|
+
const { userAgent } = transportOptions(ctx);
|
|
693
|
+
const driver = neo4j.driver(`${url.protocol}//${url.host}`, auth, userAgent === void 0 ? {} : { userAgent });
|
|
694
|
+
const session = driver.session({
|
|
695
|
+
defaultAccessMode: neo4j.session.READ,
|
|
696
|
+
...params.database === void 0 ? {} : { database: params.database }
|
|
697
|
+
});
|
|
698
|
+
let closed = null;
|
|
699
|
+
const close = () => {
|
|
700
|
+
closed ??= session.close().catch(() => void 0).then(() => driver.close()).catch(() => void 0);
|
|
701
|
+
return closed;
|
|
702
|
+
};
|
|
703
|
+
const onAbort = () => {
|
|
704
|
+
void close();
|
|
705
|
+
};
|
|
706
|
+
ctx.signal.addEventListener("abort", onAbort, { once: true });
|
|
707
|
+
const fail = (err) => {
|
|
708
|
+
throwIfAborted(ctx.signal);
|
|
709
|
+
const e = err;
|
|
710
|
+
const code = typeof e.code === "string" ? e.code : null;
|
|
711
|
+
if (code === null || code === "ServiceUnavailable" || code === "SessionExpired") {
|
|
712
|
+
return ctx.runtime === "browser" ? failOn(ctx.report, "E_SOURCE_BLOCKED", `${origin} could not be reached over Bolt`, {
|
|
713
|
+
url: origin,
|
|
714
|
+
cause: "unknown"
|
|
715
|
+
}) : failOn(ctx.report, "E_FETCH", `${origin} could not be reached over Bolt`, {
|
|
716
|
+
url: origin,
|
|
717
|
+
status: null
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
return serverError(
|
|
721
|
+
ctx.report,
|
|
722
|
+
{
|
|
723
|
+
code,
|
|
724
|
+
message: typeof e.message === "string" ? e.message : "",
|
|
725
|
+
status: null,
|
|
726
|
+
showable: code.startsWith("Neo.ClientError.")
|
|
727
|
+
},
|
|
728
|
+
origin,
|
|
729
|
+
params.database
|
|
730
|
+
);
|
|
731
|
+
};
|
|
732
|
+
let detected = null;
|
|
733
|
+
const profile = async () => {
|
|
734
|
+
if (detected === null) {
|
|
735
|
+
const info = await driver.getServerInfo().catch(fail);
|
|
736
|
+
detected = profileFromAgent(info.agent ?? "");
|
|
737
|
+
}
|
|
738
|
+
return detected;
|
|
739
|
+
};
|
|
740
|
+
const timeout = ctx.limits.timeoutMs;
|
|
741
|
+
return {
|
|
742
|
+
async run(statement, parameters) {
|
|
743
|
+
throwIfAborted(ctx.signal);
|
|
744
|
+
const result = await session.run(statement, parameters, timeout === void 0 ? void 0 : { timeout }).catch(fail);
|
|
745
|
+
const fields = (result.records[0]?.keys ?? []).map(String);
|
|
746
|
+
return {
|
|
747
|
+
fields,
|
|
748
|
+
rows: result.records.map((r) => fields.map((k) => fromDriver(r.get(k), k, m, neo4j)))
|
|
749
|
+
};
|
|
750
|
+
},
|
|
751
|
+
profile,
|
|
752
|
+
probe: profile,
|
|
753
|
+
close: async () => {
|
|
754
|
+
ctx.signal.removeEventListener("abort", onAbort);
|
|
755
|
+
await close();
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
function nodeOnly(ctx, transport) {
|
|
760
|
+
if (ctx.runtime === "browser" || ctx.runtime === "worker") {
|
|
761
|
+
failOn(ctx.report, "E_SOURCE_RUNTIME", `the ${transport} transport cannot run in a browser`, {
|
|
762
|
+
runtime: ctx.runtime,
|
|
763
|
+
reason: "cors"
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
function trailingError(text) {
|
|
768
|
+
for (let at = text.lastIndexOf("{"); at > 0; at = text.lastIndexOf("{", at - 1)) {
|
|
769
|
+
const tail = parseJson(text.slice(at));
|
|
770
|
+
if (tail !== null && typeof tail.code === "string") {
|
|
771
|
+
return tail;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
return null;
|
|
775
|
+
}
|
|
776
|
+
async function neptuneResult(input, response) {
|
|
777
|
+
const { ctx, m } = input;
|
|
778
|
+
const origin = ctx.endpoint === null ? "" : originOf(ctx.endpoint);
|
|
779
|
+
const text = await response.text();
|
|
780
|
+
const body = parseJson(text);
|
|
781
|
+
let error = typeof body?.code === "string" ? body : null;
|
|
782
|
+
if (body === null) {
|
|
783
|
+
error = trailingError(text);
|
|
784
|
+
}
|
|
785
|
+
if (error !== null) {
|
|
786
|
+
serverError(
|
|
787
|
+
ctx.report,
|
|
788
|
+
{
|
|
789
|
+
code: error.code ?? null,
|
|
790
|
+
message: error.detailedMessage ?? error.message ?? "",
|
|
791
|
+
status: response.status,
|
|
792
|
+
showable: body !== null && response.status >= 400 && response.status < 500
|
|
793
|
+
},
|
|
794
|
+
origin,
|
|
795
|
+
void 0
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
if (!response.ok) {
|
|
799
|
+
failOn(ctx.report, "E_FETCH", `${origin} answered ${String(response.status)}`, {
|
|
800
|
+
url: origin,
|
|
801
|
+
status: response.status
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
if (body === null || !Array.isArray(body.results)) {
|
|
805
|
+
failOn(ctx.report, "E_SOURCE_RESPONSE", "the Neptune answer has no results", {
|
|
806
|
+
expected: "json",
|
|
807
|
+
contentType: response.headers.get("content-type")
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
return objectRows(body.results, (v, column2) => fromNeptune(v, column2, m));
|
|
811
|
+
}
|
|
812
|
+
function neptuneHttpsTransport(input) {
|
|
813
|
+
const { ctx } = input;
|
|
814
|
+
nodeOnly(ctx, "neptune-https");
|
|
815
|
+
return {
|
|
816
|
+
async run(statement, parameters) {
|
|
817
|
+
const response = await ctx.fetch("openCypher", {
|
|
818
|
+
method: "POST",
|
|
819
|
+
idempotent: true,
|
|
820
|
+
allowStatus: [400, 500],
|
|
821
|
+
body: new URLSearchParams({ query: statement, parameters: JSON.stringify(parameters) })
|
|
822
|
+
});
|
|
823
|
+
return neptuneResult(input, response);
|
|
824
|
+
},
|
|
825
|
+
profile: () => Promise.resolve(neptuneProfile()),
|
|
826
|
+
probe: async () => {
|
|
827
|
+
const status = await ctx.fetchJson("status");
|
|
828
|
+
return neptuneProfile(typeof status.dbEngineVersion === "string" ? status.dbEngineVersion : null);
|
|
829
|
+
},
|
|
830
|
+
close: () => Promise.resolve()
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
function neptuneAnalyticsTransport(input) {
|
|
834
|
+
const { ctx } = input;
|
|
835
|
+
nodeOnly(ctx, "neptune-analytics");
|
|
836
|
+
const run = async (statement, parameters) => {
|
|
837
|
+
const response = await ctx.fetch("queries", {
|
|
838
|
+
method: "POST",
|
|
839
|
+
idempotent: true,
|
|
840
|
+
allowStatus: [400, 500],
|
|
841
|
+
headers: { "Content-Type": "application/json" },
|
|
842
|
+
body: JSON.stringify({ query: statement, language: "OPEN_CYPHER", parameters })
|
|
843
|
+
});
|
|
844
|
+
return neptuneResult(input, response);
|
|
845
|
+
};
|
|
846
|
+
return {
|
|
847
|
+
run,
|
|
848
|
+
profile: () => Promise.resolve(neptuneProfile()),
|
|
849
|
+
probe: async () => {
|
|
850
|
+
await run("RETURN 1 AS ok", {});
|
|
851
|
+
return neptuneProfile();
|
|
852
|
+
},
|
|
853
|
+
close: () => Promise.resolve()
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
const TYPED_JSON = "application/vnd.neo4j.query.v1.1";
|
|
857
|
+
const ERROR_STATUSES = [400, 404, 500];
|
|
858
|
+
function queryApiTransport(input) {
|
|
859
|
+
const { ctx, params, m } = input;
|
|
860
|
+
const database = params.database ?? "neo4j";
|
|
861
|
+
const path = `db/${encodeURIComponent(database)}/query/v2`;
|
|
862
|
+
const origin = ctx.endpoint === null ? "" : originOf(ctx.endpoint);
|
|
863
|
+
const run = async (statement, parameters) => {
|
|
864
|
+
const response = await ctx.fetch(path, {
|
|
865
|
+
method: "POST",
|
|
866
|
+
idempotent: true,
|
|
867
|
+
allowStatus: ERROR_STATUSES,
|
|
868
|
+
headers: { "Content-Type": "application/json", Accept: TYPED_JSON },
|
|
869
|
+
body: JSON.stringify({ statement, parameters, accessMode: "Read" })
|
|
870
|
+
});
|
|
871
|
+
const body = parseJson(await response.text());
|
|
872
|
+
const first = body?.errors?.[0];
|
|
873
|
+
if (first !== void 0) {
|
|
874
|
+
serverError(
|
|
875
|
+
ctx.report,
|
|
876
|
+
{
|
|
877
|
+
code: first.code ?? null,
|
|
878
|
+
message: first.message ?? "",
|
|
879
|
+
status: response.status,
|
|
880
|
+
showable: response.status >= 400 && response.status < 500
|
|
881
|
+
},
|
|
882
|
+
origin,
|
|
883
|
+
params.database
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
if (response.status === 404) {
|
|
887
|
+
failOn(ctx.report, "E_SOURCE_NOT_FOUND", `${origin} has no Query API at ${path}`, {
|
|
888
|
+
what: "url",
|
|
889
|
+
value: `${origin}/${path}`
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
if (!response.ok) {
|
|
893
|
+
failOn(ctx.report, "E_FETCH", `${origin} answered ${String(response.status)}`, {
|
|
894
|
+
url: `${origin}/${path}`,
|
|
895
|
+
status: response.status
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
if (body?.data === void 0) {
|
|
899
|
+
failOn(ctx.report, "E_SOURCE_RESPONSE", "the Query API answer has no data", {
|
|
900
|
+
expected: "json",
|
|
901
|
+
contentType: response.headers.get("content-type")
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
const { fields, values } = body.data;
|
|
905
|
+
return { fields, rows: values.map((row) => row.map((v, i) => fromTypedJson(v, fields[i] ?? "", m))) };
|
|
906
|
+
};
|
|
907
|
+
return {
|
|
908
|
+
run,
|
|
909
|
+
// the Query API exists from Neo4j 5.26, so ids are elementId()
|
|
910
|
+
profile: () => Promise.resolve(neo4jProfile(null)),
|
|
911
|
+
probe: async () => {
|
|
912
|
+
const res = await run(
|
|
913
|
+
"CALL dbms.components() YIELD name, versions, edition RETURN name, versions, edition",
|
|
914
|
+
{}
|
|
915
|
+
);
|
|
916
|
+
const kernel = res.rows.find((r) => r[0] === "Neo4j Kernel") ?? res.rows[0];
|
|
917
|
+
const versions = kernel?.[1];
|
|
918
|
+
const version = Array.isArray(versions) && typeof versions[0] === "string" ? versions[0] : null;
|
|
919
|
+
return neo4jProfile(version);
|
|
920
|
+
},
|
|
921
|
+
close: () => Promise.resolve()
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
const DIRECTIONS = /* @__PURE__ */ new Set(["out", "in", "both"]);
|
|
925
|
+
function listParam(value, name, report) {
|
|
926
|
+
if (value === void 0 || value === null) {
|
|
927
|
+
return [];
|
|
928
|
+
}
|
|
929
|
+
if (Array.isArray(value)) {
|
|
930
|
+
return value;
|
|
931
|
+
}
|
|
932
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
933
|
+
return [value];
|
|
934
|
+
}
|
|
935
|
+
return failOn(report, "E_SOURCE_PARAM", `parameter ${name}: not a list`, { name, reason: "type" });
|
|
936
|
+
}
|
|
937
|
+
function transportName(params, ctx, preset) {
|
|
938
|
+
if (params.transport !== void 0) {
|
|
939
|
+
return params.transport;
|
|
940
|
+
}
|
|
941
|
+
const scheme = ctx.endpoint?.protocol ?? "";
|
|
942
|
+
if (scheme.startsWith("bolt") || scheme.startsWith("neo4j")) {
|
|
943
|
+
return "bolt";
|
|
944
|
+
}
|
|
945
|
+
if (ctx.endpoint?.hostname.endsWith(".neptune-graph.amazonaws.com") === true) {
|
|
946
|
+
return "neptune-analytics";
|
|
947
|
+
}
|
|
948
|
+
return preset.transport;
|
|
949
|
+
}
|
|
950
|
+
class Reader {
|
|
951
|
+
/**
|
|
952
|
+
* Set up a read.
|
|
953
|
+
* @param transport - the transport
|
|
954
|
+
* @param params - the params
|
|
955
|
+
* @param ctx - the context
|
|
956
|
+
*/
|
|
957
|
+
constructor(transport, params, ctx) {
|
|
958
|
+
this.transport = transport;
|
|
959
|
+
this.params = params;
|
|
960
|
+
this.ctx = ctx;
|
|
961
|
+
this.known = null;
|
|
962
|
+
this.degree = true;
|
|
963
|
+
const { report } = ctx;
|
|
964
|
+
this.idProperty = params.idProperty ?? null;
|
|
965
|
+
this.filters = {
|
|
966
|
+
labels: listParam(params.labels, "labels", report).map((l) => quoted(l, "labels", report)),
|
|
967
|
+
relationshipTypes: listParam(params.relationshipTypes, "relationshipTypes", report).map(
|
|
968
|
+
(t) => quoted(t, "relationshipTypes", report)
|
|
969
|
+
),
|
|
970
|
+
idProperty: this.idProperty === null ? null : quoted(this.idProperty, "idProperty", report)
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* The server's profile: the params' choice, else the transport's detection.
|
|
975
|
+
* @returns the profile
|
|
976
|
+
*/
|
|
977
|
+
async profile() {
|
|
978
|
+
if (this.known === null) {
|
|
979
|
+
const detected = await this.transport.profile();
|
|
980
|
+
this.known = detected;
|
|
981
|
+
if (this.params.profile === "neptune") {
|
|
982
|
+
this.known = neptuneProfile(detected.version);
|
|
983
|
+
} else if (this.params.profile === "neo4j" && detected.name !== "neo4j") {
|
|
984
|
+
this.known = neo4jProfile(detected.version);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
return this.known;
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Run a generated statement with the degree hint, and without it once if the server refuses it.
|
|
991
|
+
* @param build - builds the statement, with or without the hint
|
|
992
|
+
* @param parameters - its parameters
|
|
993
|
+
* @returns the result, collected
|
|
994
|
+
*/
|
|
995
|
+
async generated(build, parameters) {
|
|
996
|
+
let result;
|
|
997
|
+
try {
|
|
998
|
+
result = await this.transport.run(build(this.degree), parameters);
|
|
999
|
+
} catch (err) {
|
|
1000
|
+
if (!this.degree || !(err instanceof ImportError) || err.issue?.code !== SOURCE_ISSUE.E_SOURCE_QUERY) {
|
|
1001
|
+
throw err;
|
|
1002
|
+
}
|
|
1003
|
+
this.degree = false;
|
|
1004
|
+
result = await this.transport.run(build(false), parameters);
|
|
1005
|
+
}
|
|
1006
|
+
const collected = new Collector();
|
|
1007
|
+
collected.add(result, true);
|
|
1008
|
+
return { collected, rows: result.rows, fields: result.fields };
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* The pages of a read, as `mode` asks.
|
|
1012
|
+
* @param cursor - where to resume
|
|
1013
|
+
* @yields one page at a time
|
|
1014
|
+
*/
|
|
1015
|
+
async *pages(cursor) {
|
|
1016
|
+
const { params, ctx } = this;
|
|
1017
|
+
const { report } = ctx;
|
|
1018
|
+
const mode = params.mode ?? (typeof params.query === "string" && params.query !== "" ? "query" : "all");
|
|
1019
|
+
if (mode === "query") {
|
|
1020
|
+
if (typeof params.query !== "string" || params.query.trim() === "") {
|
|
1021
|
+
failOn(report, "E_SOURCE_PARAM", "mode query needs a query", { name: "query", reason: "required" });
|
|
1022
|
+
}
|
|
1023
|
+
const result = await this.transport.run(params.query, params.parameters ?? {});
|
|
1024
|
+
const collected = new Collector();
|
|
1025
|
+
collected.add(result, false);
|
|
1026
|
+
requireGraph(result, collected, report);
|
|
1027
|
+
yield { collected, next: null };
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const profile = await this.profile();
|
|
1031
|
+
if (mode === "neighborhood") {
|
|
1032
|
+
const ids = listParam(params.ids, "ids", report);
|
|
1033
|
+
if (ids.length === 0) {
|
|
1034
|
+
failOn(report, "E_SOURCE_PARAM", "mode neighborhood needs ids", { name: "ids", reason: "required" });
|
|
1035
|
+
}
|
|
1036
|
+
const shape = {
|
|
1037
|
+
depth: checkedInteger(params.depth ?? 1, "depth", 1, MAX_DEPTH, report),
|
|
1038
|
+
direction: "both",
|
|
1039
|
+
limit: ctx.limits.maxNodes === void 0 ? null : checkedInteger(ctx.limits.maxNodes, "maxNodes", 1, Number.MAX_SAFE_INTEGER, report)
|
|
1040
|
+
};
|
|
1041
|
+
const { collected } = await this.generated((d) => neighborhood(profile, this.filters, shape, d), { ids });
|
|
1042
|
+
yield { collected, next: null };
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
yield* this.everything(profile, cursor);
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Mode "all": the nodes, then the relationships with their ends, each paged by keyset on the
|
|
1049
|
+
* id expression (never SKIP), so a page is stable under unrelated writes.
|
|
1050
|
+
* @param profile - the server's profile
|
|
1051
|
+
* @param cursor - where to resume
|
|
1052
|
+
* @yields one page at a time
|
|
1053
|
+
*/
|
|
1054
|
+
async *everything(profile, cursor) {
|
|
1055
|
+
const { params, ctx } = this;
|
|
1056
|
+
const size = checkedInteger(params.pageSize ?? DEFAULT_PAGE_SIZE, "pageSize", 1, MAX_PAGE_SIZE, ctx.report);
|
|
1057
|
+
let phase = cursor?.phase === "edges" ? "edges" : "nodes";
|
|
1058
|
+
let after = cursor?.after ?? null;
|
|
1059
|
+
const total = params.countFirst === true && cursor === null ? await this.total() : void 0;
|
|
1060
|
+
for (; ; ) {
|
|
1061
|
+
const nodes = phase === "nodes";
|
|
1062
|
+
const { collected, rows, fields } = await this.generated(
|
|
1063
|
+
(d) => nodes ? nodePage(profile, this.filters, size, after !== null, d) : edgePage(profile, this.filters, size, after !== null),
|
|
1064
|
+
after === null ? {} : { after }
|
|
1065
|
+
);
|
|
1066
|
+
const next = nextCursor(phase, rows, fields, Number(size));
|
|
1067
|
+
yield { collected, next };
|
|
1068
|
+
const { counts: done } = ctx.report;
|
|
1069
|
+
ctx.progress(done.nodes + done.edges, total, "items");
|
|
1070
|
+
if (next === null) {
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
phase = next.phase === "edges" ? "edges" : "nodes";
|
|
1074
|
+
after = next.after ?? null;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* How many nodes and relationships the filters match, for progress.
|
|
1079
|
+
* @returns the count
|
|
1080
|
+
*/
|
|
1081
|
+
async total() {
|
|
1082
|
+
const [n, r] = counts(this.filters);
|
|
1083
|
+
const [a, b] = await Promise.all([this.transport.run(n, {}), this.transport.run(r, {})]);
|
|
1084
|
+
return Number(a.rows[0]?.[0] ?? 0) + Number(b.rows[0]?.[0] ?? 0);
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* The server facts and validators of what was read.
|
|
1088
|
+
* @param lines - the canonical rows
|
|
1089
|
+
* @returns the server facts and validators
|
|
1090
|
+
*/
|
|
1091
|
+
async facts(lines) {
|
|
1092
|
+
const profile = await this.profile();
|
|
1093
|
+
const contentHash = await sha256Hex([...lines].sort(compareText).join("\n"));
|
|
1094
|
+
return {
|
|
1095
|
+
server: serverFacts(profile),
|
|
1096
|
+
validators: profile.version === null ? { contentHash } : { contentHash, serverVersion: profile.version }
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
function nextCursor(phase, rows, fields, size) {
|
|
1101
|
+
const last = rows.at(-1)?.[fields.indexOf("key")];
|
|
1102
|
+
const key = typeof last === "string" || typeof last === "number" ? last : null;
|
|
1103
|
+
if (rows.length >= size && key !== null) {
|
|
1104
|
+
return { phase, after: key };
|
|
1105
|
+
}
|
|
1106
|
+
return phase === "nodes" ? { phase: "edges", after: null } : null;
|
|
1107
|
+
}
|
|
1108
|
+
async function open(params, ctx, preset) {
|
|
1109
|
+
throwIfAborted(ctx.signal);
|
|
1110
|
+
const input = { ctx, params, m: { long: params.long ?? "f64", report: ctx.report } };
|
|
1111
|
+
const name = transportName(params, ctx, preset);
|
|
1112
|
+
let transport;
|
|
1113
|
+
switch (name) {
|
|
1114
|
+
case "bolt":
|
|
1115
|
+
transport = await boltTransport(input);
|
|
1116
|
+
break;
|
|
1117
|
+
case "neptune-https":
|
|
1118
|
+
transport = neptuneHttpsTransport(input);
|
|
1119
|
+
break;
|
|
1120
|
+
case "neptune-analytics":
|
|
1121
|
+
transport = neptuneAnalyticsTransport(input);
|
|
1122
|
+
break;
|
|
1123
|
+
default:
|
|
1124
|
+
transport = queryApiTransport(input);
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
1127
|
+
try {
|
|
1128
|
+
return new Reader(transport, params, ctx);
|
|
1129
|
+
} catch (err) {
|
|
1130
|
+
await transport.close();
|
|
1131
|
+
throw err;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
async function withReader(params, ctx, preset, body) {
|
|
1135
|
+
const reader = await open(params, ctx, preset);
|
|
1136
|
+
try {
|
|
1137
|
+
return await body(reader);
|
|
1138
|
+
} finally {
|
|
1139
|
+
await reader.transport.close();
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
function cypher(preset) {
|
|
1143
|
+
return defineSource({
|
|
1144
|
+
id: preset.id,
|
|
1145
|
+
descriptor: preset.descriptor,
|
|
1146
|
+
import: (params, sink, ctx) => withReader(params, ctx, preset, async (reader) => {
|
|
1147
|
+
const lines = [];
|
|
1148
|
+
let next = null;
|
|
1149
|
+
for await (const page of reader.pages(ctx.cursor)) {
|
|
1150
|
+
writeCollected(page.collected, sink, reader.idProperty, ctx.report, ctx.signal);
|
|
1151
|
+
lines.push(...canonicalRows(page.collected, reader.idProperty));
|
|
1152
|
+
({ next } = page);
|
|
1153
|
+
if (next !== null && ctx.limits.reached()) {
|
|
1154
|
+
break;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return ctx.finish({ next, ...await reader.facts(lines) });
|
|
1158
|
+
}),
|
|
1159
|
+
expand: (request, sink, ctx) => withReader(request.params, ctx, preset, (reader) => expand(reader, request, sink)),
|
|
1160
|
+
probe: (params, ctx) => withReader(params, ctx, preset, async (reader) => {
|
|
1161
|
+
const profile = await reader.transport.probe();
|
|
1162
|
+
return { ok: true, server: serverFacts(profile) };
|
|
1163
|
+
}),
|
|
1164
|
+
validate: (params, seen, ctx) => withReader(params, ctx, preset, async (reader) => {
|
|
1165
|
+
const lines = [];
|
|
1166
|
+
for await (const page of reader.pages(null)) {
|
|
1167
|
+
lines.push(...canonicalRows(page.collected, reader.idProperty));
|
|
1168
|
+
}
|
|
1169
|
+
const { validators } = await reader.facts(lines);
|
|
1170
|
+
let status = "unverifiable";
|
|
1171
|
+
if (seen.contentHash !== void 0) {
|
|
1172
|
+
status = seen.contentHash === validators.contentHash ? "current" : "changed";
|
|
1173
|
+
}
|
|
1174
|
+
return { status, via: "hash", validators };
|
|
1175
|
+
})
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
async function expand(reader, request, sink) {
|
|
1179
|
+
const { ctx } = reader;
|
|
1180
|
+
const { report } = ctx;
|
|
1181
|
+
if (request.ids.length === 0) {
|
|
1182
|
+
failOn(report, "E_SOURCE_PARAM", "an expansion needs seed ids", { name: "ids", reason: "required" });
|
|
1183
|
+
}
|
|
1184
|
+
const direction = request.direction ?? "both";
|
|
1185
|
+
if (!DIRECTIONS.has(direction)) {
|
|
1186
|
+
failOn(report, "E_SOURCE_PARAM", "direction must be out, in or both", { name: "direction", reason: "enum" });
|
|
1187
|
+
}
|
|
1188
|
+
const limit = request.limit ?? ctx.limits.maxNodes;
|
|
1189
|
+
const after = ctx.cursor?.after ?? null;
|
|
1190
|
+
const shape = {
|
|
1191
|
+
depth: checkedInteger(request.depth ?? 1, "depth", 1, MAX_DEPTH, report),
|
|
1192
|
+
direction,
|
|
1193
|
+
limit: limit === void 0 ? null : checkedInteger(limit, "limit", 1, Number.MAX_SAFE_INTEGER, report),
|
|
1194
|
+
after: after !== null
|
|
1195
|
+
};
|
|
1196
|
+
const filters = request.relationshipTypes === void 0 ? reader.filters : {
|
|
1197
|
+
...reader.filters,
|
|
1198
|
+
relationshipTypes: request.relationshipTypes.map((t) => quoted(t, "relationshipTypes", report))
|
|
1199
|
+
};
|
|
1200
|
+
const profile = await reader.profile();
|
|
1201
|
+
const { collected, rows, fields } = await reader.generated((d) => neighborhood(profile, filters, shape, d), {
|
|
1202
|
+
ids: request.ids,
|
|
1203
|
+
...after === null ? {} : { after }
|
|
1204
|
+
});
|
|
1205
|
+
writeCollected(collected, sink, reader.idProperty, report, ctx.signal);
|
|
1206
|
+
const { server } = await reader.facts([]);
|
|
1207
|
+
const last = rows.at(-1)?.[fields.indexOf("key")];
|
|
1208
|
+
const full = shape.limit !== null && rows.length >= Number(shape.limit);
|
|
1209
|
+
const next = full && (typeof last === "string" || typeof last === "number") ? { after: last } : null;
|
|
1210
|
+
return ctx.finish({ server, next });
|
|
1211
|
+
}
|
|
1212
|
+
const cypherSource = cypher({
|
|
1213
|
+
id: CYPHER_SOURCE_ID,
|
|
1214
|
+
descriptor: CYPHER_DESCRIPTOR,
|
|
1215
|
+
transport: "query-api"
|
|
1216
|
+
});
|
|
1217
|
+
const neo4jSource = cypher({
|
|
1218
|
+
id: NEO4J_SOURCE_ID,
|
|
1219
|
+
descriptor: NEO4J_DESCRIPTOR,
|
|
1220
|
+
transport: "query-api"
|
|
1221
|
+
});
|
|
1222
|
+
const neptuneSource = cypher({
|
|
1223
|
+
id: NEPTUNE_SOURCE_ID,
|
|
1224
|
+
descriptor: NEPTUNE_DESCRIPTOR,
|
|
1225
|
+
transport: "neptune-https"
|
|
1226
|
+
});
|
|
1227
|
+
export {
|
|
1228
|
+
CYPHER_DESCRIPTOR,
|
|
1229
|
+
NEO4J_DESCRIPTOR,
|
|
1230
|
+
NEPTUNE_DESCRIPTOR,
|
|
1231
|
+
cypherIdentifier,
|
|
1232
|
+
cypherSource,
|
|
1233
|
+
neo4jSource,
|
|
1234
|
+
neptuneSource
|
|
1235
|
+
};
|
|
1236
|
+
//# sourceMappingURL=sources-cypher.js.map
|