@graphty/graph-io 0.3.47 → 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,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `openalex` preset of the REST mapping (design section 13.3): OpenAlex's citation graph
|
|
3
|
+
* around a work, or its co-authorship graph around an author, as a mapping the generic engine runs.
|
|
4
|
+
* The seed's own record comes first; citing works page by cursor; referenced works are stubs until
|
|
5
|
+
* hydrated or expanded. Freshness is the newest `updated_date`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineSource } from "../define.js";
|
|
9
|
+
import { failOn } from "../fail.js";
|
|
10
|
+
import { OPENALEX_SOURCE_ID } from "../ids.js";
|
|
11
|
+
import { type GraphSource, type SourceContext } from "../types.js";
|
|
12
|
+
import { OPENALEX_DESCRIPTOR } from "./descriptor.js";
|
|
13
|
+
import { type OpenAlexParams, type RestEntity, type RestMapping } from "./params.js";
|
|
14
|
+
import { restMethods, type RestPlan, type RestPurpose } from "./source.js";
|
|
15
|
+
|
|
16
|
+
/** OpenAlex ids are URLs under this prefix. */
|
|
17
|
+
const PREFIX = "https://openalex.org/";
|
|
18
|
+
|
|
19
|
+
/** The work fields every citation load selects. */
|
|
20
|
+
const WORK_FIELDS = "id,display_name,publication_year,cited_by_count,updated_date,referenced_works";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A list request over works, `{ids}` batched 50 at a time and joined by `|`.
|
|
24
|
+
* @param filter - the filter template
|
|
25
|
+
* @param perPage - the page size
|
|
26
|
+
* @param paged - whether it pages by cursor
|
|
27
|
+
* @returns the request
|
|
28
|
+
*/
|
|
29
|
+
function works(filter: string, perPage: string, paged: boolean): RestMapping["requests"][string] {
|
|
30
|
+
return {
|
|
31
|
+
path: "/works",
|
|
32
|
+
query: { filter, "per-page": perPage, select: "{select}" },
|
|
33
|
+
batch: { max: 50, join: "|" },
|
|
34
|
+
records: "results",
|
|
35
|
+
entity: "work",
|
|
36
|
+
...(paged ? { paging: { style: "cursor", param: "cursor", first: "*", next: "meta.next_cursor" } } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** An entity known by its OpenAlex id and display name. */
|
|
41
|
+
const named: RestEntity = { id: "id", stripPrefix: PREFIX, fields: { name: "display_name" } };
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* OpenAlex's citation graph as a mapping: the seed work (`{ids}`), the works citing it page by page,
|
|
45
|
+
* each work's references as `cites` edges, and, when `{select}` asks for `authorships` and
|
|
46
|
+
* `topics`, the authors, their institutions and the topics as nodes. Fill `{ids}` with work ids
|
|
47
|
+
* and `{select}` with the fields to read. The `openalex` source chooses both from its params and
|
|
48
|
+
* leaves out the rules for what is not included. Experimental.
|
|
49
|
+
* @category Network sources
|
|
50
|
+
*/
|
|
51
|
+
export const OPENALEX_MAPPING: RestMapping = Object.freeze<RestMapping>({
|
|
52
|
+
version: 1,
|
|
53
|
+
endpoint: "https://api.openalex.org",
|
|
54
|
+
load: "citing",
|
|
55
|
+
seed: "by-id",
|
|
56
|
+
expand: { in: "citing", out: "by-id" },
|
|
57
|
+
hydrate: "by-id",
|
|
58
|
+
directed: true,
|
|
59
|
+
modified: "updated_date",
|
|
60
|
+
auth: { kind: "api-key", query: "api_key" },
|
|
61
|
+
rateLimit: { requests: 10, perMs: 1000 },
|
|
62
|
+
budgetHeaders: { remaining: "x-ratelimit-remaining", reset: "x-ratelimit-reset" },
|
|
63
|
+
requests: {
|
|
64
|
+
citing: works("cites:{ids}", "200", true),
|
|
65
|
+
"by-id": works("openalex:{ids}", "50", false),
|
|
66
|
+
authored: works("authorships.author.id:{ids}", "200", true),
|
|
67
|
+
"authors-by-id": {
|
|
68
|
+
path: "/authors",
|
|
69
|
+
query: { filter: "openalex:{ids}", "per-page": "50", select: "id,display_name" },
|
|
70
|
+
batch: { max: 50, join: "|" },
|
|
71
|
+
records: "results",
|
|
72
|
+
entity: "author",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
entities: {
|
|
76
|
+
work: {
|
|
77
|
+
id: "id",
|
|
78
|
+
stripPrefix: PREFIX,
|
|
79
|
+
fields: {
|
|
80
|
+
title: "display_name",
|
|
81
|
+
year: "publication_year",
|
|
82
|
+
citedBy: "cited_by_count",
|
|
83
|
+
updated: "updated_date",
|
|
84
|
+
},
|
|
85
|
+
edges: [
|
|
86
|
+
{ to: "referenced_works[]", type: "cites", entity: "work" },
|
|
87
|
+
{ to: "authorships[].author.id", type: "authored_by", entity: "author" },
|
|
88
|
+
{
|
|
89
|
+
each: "authorships[]",
|
|
90
|
+
from: "author.id",
|
|
91
|
+
to: "institutions[].id",
|
|
92
|
+
type: "affiliated_with",
|
|
93
|
+
entity: "institution",
|
|
94
|
+
},
|
|
95
|
+
{ to: "topics[].id", type: "has_topic", entity: "topic" },
|
|
96
|
+
],
|
|
97
|
+
embedded: [
|
|
98
|
+
{ at: "authorships[].author", entity: "author" },
|
|
99
|
+
{ at: "authorships[].institutions[]", entity: "institution" },
|
|
100
|
+
{ at: "topics[]", entity: "topic" },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
author: named,
|
|
104
|
+
institution: named,
|
|
105
|
+
topic: named,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/** What `include` may hold. */
|
|
110
|
+
type Include = "authors" | "institutions" | "topics";
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The included kinds, from an array or a comma-separated string.
|
|
114
|
+
* @param include - the param
|
|
115
|
+
* @returns the set
|
|
116
|
+
*/
|
|
117
|
+
function includes(include: unknown): Set<Include> {
|
|
118
|
+
const list: unknown[] = typeof include === "string" ? include.split(",") : [];
|
|
119
|
+
if (Array.isArray(include)) {
|
|
120
|
+
list.push(...(include as unknown[]));
|
|
121
|
+
}
|
|
122
|
+
const out = new Set(list.map((v) => String(v).trim()).filter((v) => v !== "") as Include[]);
|
|
123
|
+
if (out.has("institutions")) {
|
|
124
|
+
// an institution hangs off an author, so it brings its authors
|
|
125
|
+
out.add("authors");
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The citation mapping without the rules for what is not included.
|
|
132
|
+
* @param include - what is included
|
|
133
|
+
* @returns the mapping
|
|
134
|
+
*/
|
|
135
|
+
function citationMapping(include: ReadonlySet<Include>): RestMapping {
|
|
136
|
+
const { work } = OPENALEX_MAPPING.entities;
|
|
137
|
+
const keepEdge = (type: string): boolean =>
|
|
138
|
+
type === "cites" ||
|
|
139
|
+
(type === "authored_by" && include.has("authors")) ||
|
|
140
|
+
(type === "affiliated_with" && include.has("institutions")) ||
|
|
141
|
+
(type === "has_topic" && include.has("topics"));
|
|
142
|
+
const keepEmbedded = (entity: string): boolean => include.has(`${entity}s` as Include);
|
|
143
|
+
return {
|
|
144
|
+
...OPENALEX_MAPPING,
|
|
145
|
+
entities: {
|
|
146
|
+
...OPENALEX_MAPPING.entities,
|
|
147
|
+
work: {
|
|
148
|
+
...work,
|
|
149
|
+
edges: work.edges?.filter((e) => keepEdge(e.type)),
|
|
150
|
+
embedded: work.embedded?.filter((e) => keepEmbedded(e.entity)),
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* The co-authorship mapping: works are containers, every two authors of one work are joined by a
|
|
158
|
+
* `coauthor` edge, and an author expands through the works they wrote.
|
|
159
|
+
* @param include - what is included
|
|
160
|
+
* @param seedIsWork - whether the load starts from a work
|
|
161
|
+
* @returns the mapping
|
|
162
|
+
*/
|
|
163
|
+
function coauthorshipMapping(include: ReadonlySet<Include>, seedIsWork: boolean): RestMapping {
|
|
164
|
+
const institutions = include.has("institutions");
|
|
165
|
+
return {
|
|
166
|
+
...OPENALEX_MAPPING,
|
|
167
|
+
load: seedIsWork ? "by-id" : "authored",
|
|
168
|
+
seed: undefined,
|
|
169
|
+
expand: "authored",
|
|
170
|
+
hydrate: "authors-by-id",
|
|
171
|
+
directed: false,
|
|
172
|
+
entities: {
|
|
173
|
+
...OPENALEX_MAPPING.entities,
|
|
174
|
+
work: {
|
|
175
|
+
id: "id",
|
|
176
|
+
// a rule's `from` is read with the record's own prefix
|
|
177
|
+
stripPrefix: PREFIX,
|
|
178
|
+
node: false,
|
|
179
|
+
edges: [
|
|
180
|
+
{ pairs: "authorships[].author.id", type: "coauthor", entity: "author" },
|
|
181
|
+
...(institutions
|
|
182
|
+
? [
|
|
183
|
+
{
|
|
184
|
+
each: "authorships[]",
|
|
185
|
+
from: "author.id",
|
|
186
|
+
to: "institutions[].id",
|
|
187
|
+
type: "affiliated_with",
|
|
188
|
+
entity: "institution",
|
|
189
|
+
},
|
|
190
|
+
]
|
|
191
|
+
: []),
|
|
192
|
+
],
|
|
193
|
+
embedded: [
|
|
194
|
+
{ at: "authorships[].author", entity: "author" },
|
|
195
|
+
...(institutions ? [{ at: "authorships[].institutions[]", entity: "institution" }] : []),
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* An OpenAlex id param: `W123` or its URL form, checked so a value cannot add a filter.
|
|
204
|
+
* @param value - the param
|
|
205
|
+
* @param name - its name
|
|
206
|
+
* @param letter - the id's kind letter
|
|
207
|
+
* @param ctx - the context
|
|
208
|
+
* @returns the bare id
|
|
209
|
+
*/
|
|
210
|
+
function openalexId(value: unknown, name: string, letter: string, ctx: SourceContext): string {
|
|
211
|
+
const text = typeof value === "string" ? value.trim().replace(PREFIX, "") : "";
|
|
212
|
+
if (!new RegExp(String.raw`^${letter}\d+$`, "i").test(text)) {
|
|
213
|
+
failOn(ctx.report, "E_SOURCE_PARAM", `${name} is not an OpenAlex id`, { name, reason: "format" });
|
|
214
|
+
}
|
|
215
|
+
return text.toUpperCase();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* The plan of an OpenAlex call.
|
|
220
|
+
* @param params - the params
|
|
221
|
+
* @param ctx - the context
|
|
222
|
+
* @param purpose - what the plan is for
|
|
223
|
+
* @returns the mapping and values
|
|
224
|
+
*/
|
|
225
|
+
function plan(params: OpenAlexParams, ctx: SourceContext, purpose: RestPurpose): RestPlan {
|
|
226
|
+
const graph = params.graph ?? "citation";
|
|
227
|
+
const include = includes(params.include);
|
|
228
|
+
const hasWork = params.work !== undefined && params.work !== "";
|
|
229
|
+
const hasAuthor = params.author !== undefined && params.author !== "";
|
|
230
|
+
if (purpose !== "expand" && hasWork === hasAuthor) {
|
|
231
|
+
failOn(ctx.report, "E_SOURCE_PARAM", "give exactly one of work and author", {
|
|
232
|
+
name: "work",
|
|
233
|
+
reason: hasWork ? "exclusive" : "required",
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
let seed = "";
|
|
237
|
+
if (hasWork) {
|
|
238
|
+
seed = openalexId(params.work, "work", "W", ctx);
|
|
239
|
+
} else if (hasAuthor) {
|
|
240
|
+
seed = openalexId(params.author, "author", "A", ctx);
|
|
241
|
+
}
|
|
242
|
+
if (graph === "coauthorship") {
|
|
243
|
+
return {
|
|
244
|
+
mapping: coauthorshipMapping(include, hasWork),
|
|
245
|
+
values: { ids: seed, select: purpose === "validate" ? "id,updated_date" : "id,updated_date,authorships" },
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
let select =
|
|
249
|
+
WORK_FIELDS + (include.has("authors") ? ",authorships" : "") + (include.has("topics") ? ",topics" : "");
|
|
250
|
+
if (purpose === "validate") {
|
|
251
|
+
select = "id,updated_date";
|
|
252
|
+
}
|
|
253
|
+
const mapping = citationMapping(include);
|
|
254
|
+
return {
|
|
255
|
+
mapping: hasWork ? mapping : { ...mapping, load: "authored", seed: undefined },
|
|
256
|
+
values: { ids: seed, select },
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** OpenAlex's own ids: a kind letter and digits. */
|
|
261
|
+
const ANY_ID = /^[WAIT]\d+$/;
|
|
262
|
+
|
|
263
|
+
const methods = restMethods<OpenAlexParams>(plan, false);
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* The OpenAlex preset (https://openalex.org): `work` (the citation graph around a work, default)
|
|
267
|
+
* or `author` (the works they wrote), `graph: "coauthorship"` for authors joined by shared works,
|
|
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`; pass
|
|
270
|
+
* `credentials.apiKey({ query: "api_key" }, key)` and continue with the cursor. Experimental.
|
|
271
|
+
* @category Network sources
|
|
272
|
+
*/
|
|
273
|
+
export const openalexSource: GraphSource<OpenAlexParams> = defineSource<OpenAlexParams>({
|
|
274
|
+
id: OPENALEX_SOURCE_ID,
|
|
275
|
+
descriptor: OPENALEX_DESCRIPTOR,
|
|
276
|
+
...methods,
|
|
277
|
+
expand(request, sink, ctx) {
|
|
278
|
+
for (const id of request.ids) {
|
|
279
|
+
if (!ANY_ID.test(String(id))) {
|
|
280
|
+
failOn(ctx.report, "E_SOURCE_PARAM", "an expansion seed is not an OpenAlex id", {
|
|
281
|
+
name: "ids",
|
|
282
|
+
reason: "format",
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return methods.expand(request, sink, ctx);
|
|
287
|
+
},
|
|
288
|
+
});
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paging of the REST mapping (design section 13.2): a cursor in the body, an offset, the `Link`
|
|
3
|
+
* header, or a next URL in the body. A position is a string or a number, so it fits a SourceCursor;
|
|
4
|
+
* a position that is a URL is checked against the mapping's origin before it is followed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { type ImportReportBuilder } from "../../common/report.js";
|
|
8
|
+
import { failOn } from "../fail.js";
|
|
9
|
+
import { type RestPaging } from "./params.js";
|
|
10
|
+
import { selectOne } from "./selectors.js";
|
|
11
|
+
import { checkOrigin } from "./templates.js";
|
|
12
|
+
|
|
13
|
+
/** Where a paged request is: the first page (null), a cursor or offset, or a full URL. */
|
|
14
|
+
export type PagePosition = string | number | null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The position of the first page.
|
|
18
|
+
* @param paging - the request's paging
|
|
19
|
+
* @returns the position
|
|
20
|
+
*/
|
|
21
|
+
function firstPosition(paging: RestPaging | undefined): PagePosition {
|
|
22
|
+
switch (paging?.style) {
|
|
23
|
+
case "cursor":
|
|
24
|
+
return paging.first;
|
|
25
|
+
case "offset":
|
|
26
|
+
return paging.base ?? 0;
|
|
27
|
+
default:
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The URL of a page.
|
|
34
|
+
* @param url - the request's first-page URL
|
|
35
|
+
* @param paging - the request's paging
|
|
36
|
+
* @param position - where to read
|
|
37
|
+
* @param endpoint - the mapping's endpoint, which a full URL must stay on
|
|
38
|
+
* @param report - the load's report
|
|
39
|
+
* @returns the page's URL
|
|
40
|
+
*/
|
|
41
|
+
export function pageUrl(
|
|
42
|
+
url: URL,
|
|
43
|
+
paging: RestPaging | undefined,
|
|
44
|
+
position: PagePosition,
|
|
45
|
+
endpoint: URL,
|
|
46
|
+
report: ImportReportBuilder,
|
|
47
|
+
): URL {
|
|
48
|
+
if (position === null) {
|
|
49
|
+
return url;
|
|
50
|
+
}
|
|
51
|
+
const out = new URL(url);
|
|
52
|
+
switch (paging?.style) {
|
|
53
|
+
case "cursor":
|
|
54
|
+
out.searchParams.set(paging.param, String(position));
|
|
55
|
+
return out;
|
|
56
|
+
case "offset":
|
|
57
|
+
out.searchParams.set(paging.param, String(position));
|
|
58
|
+
out.searchParams.set(paging.size.param, String(paging.size.value));
|
|
59
|
+
return out;
|
|
60
|
+
default:
|
|
61
|
+
// link-header and next-url positions are full URLs from a response (or a recorded cursor)
|
|
62
|
+
return checkOrigin(new URL(String(position), url), endpoint, report);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The first page's URL with its paging parameters, so an offset request carries its size.
|
|
68
|
+
* @param url - the request's URL
|
|
69
|
+
* @param paging - the request's paging
|
|
70
|
+
* @param endpoint - the mapping's endpoint
|
|
71
|
+
* @param report - the load's report
|
|
72
|
+
* @returns the URL
|
|
73
|
+
*/
|
|
74
|
+
export function firstPageUrl(
|
|
75
|
+
url: URL,
|
|
76
|
+
paging: RestPaging | undefined,
|
|
77
|
+
endpoint: URL,
|
|
78
|
+
report: ImportReportBuilder,
|
|
79
|
+
): URL {
|
|
80
|
+
return pageUrl(url, paging, firstPosition(paging), endpoint, report);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The `rel` URL of a Link header.
|
|
85
|
+
* @param header - the header's value
|
|
86
|
+
* @param rel - the relation
|
|
87
|
+
* @returns the URL text, or null
|
|
88
|
+
*/
|
|
89
|
+
function linkOf(header: string, rel: string): string | null {
|
|
90
|
+
for (const part of header.split(/,(?=\s*<)/)) {
|
|
91
|
+
const m = /^\s*<([^>]*)>(.*)$/.exec(part);
|
|
92
|
+
if (m === null) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const rels = /;\s*rel="?([^";]+)"?/i.exec(m[2]);
|
|
96
|
+
if (rels?.[1].split(/\s+/).includes(rel)) {
|
|
97
|
+
return m[1];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** What `nextPosition` reads. */
|
|
104
|
+
interface PageResponse {
|
|
105
|
+
/** The parsed body. */
|
|
106
|
+
readonly body: unknown;
|
|
107
|
+
/** The response headers. */
|
|
108
|
+
readonly headers: Headers;
|
|
109
|
+
/** The URL the page was read from. */
|
|
110
|
+
readonly url: URL;
|
|
111
|
+
/** How many records the page held. */
|
|
112
|
+
readonly records: number;
|
|
113
|
+
/** Where the load runs: a missing Link header in a browser may be one the service hides. */
|
|
114
|
+
readonly runtime: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The next page's URL from the Link header, or null after the last one.
|
|
119
|
+
* @param rel - the relation that names the next page
|
|
120
|
+
* @param page - this page's response
|
|
121
|
+
* @param endpoint - the mapping's endpoint
|
|
122
|
+
* @param report - the load's report
|
|
123
|
+
* @returns the next position
|
|
124
|
+
*/
|
|
125
|
+
function nextLink(rel: string, page: PageResponse, endpoint: URL, report: ImportReportBuilder): PagePosition {
|
|
126
|
+
const header = page.headers.get("link");
|
|
127
|
+
if (header === null) {
|
|
128
|
+
if (page.runtime === "browser") {
|
|
129
|
+
// a browser reads Link only when the service exposes it: never a silent single page
|
|
130
|
+
failOn(report, "E_SOURCE_RESPONSE", "the Link header cannot be read", {
|
|
131
|
+
expected: "link-header",
|
|
132
|
+
contentType: page.headers.get("content-type"),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const next = linkOf(header, rel);
|
|
138
|
+
return next === null ? null : checkOrigin(new URL(next, page.url), endpoint, report).href;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Where the next page is, or null after the last one.
|
|
143
|
+
* @param paging - the request's paging
|
|
144
|
+
* @param position - this page's position
|
|
145
|
+
* @param page - this page's response
|
|
146
|
+
* @param endpoint - the mapping's endpoint
|
|
147
|
+
* @param report - the load's report
|
|
148
|
+
* @returns the next position
|
|
149
|
+
*/
|
|
150
|
+
export function nextPosition(
|
|
151
|
+
paging: RestPaging | undefined,
|
|
152
|
+
position: PagePosition,
|
|
153
|
+
page: PageResponse,
|
|
154
|
+
endpoint: URL,
|
|
155
|
+
report: ImportReportBuilder,
|
|
156
|
+
): PagePosition {
|
|
157
|
+
switch (paging?.style) {
|
|
158
|
+
case "cursor": {
|
|
159
|
+
const next = selectOne(page.body, paging.next);
|
|
160
|
+
return (typeof next === "string" && next !== "") || typeof next === "number" ? next : null;
|
|
161
|
+
}
|
|
162
|
+
case "offset": {
|
|
163
|
+
if (page.records < paging.size.value || page.records === 0) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const step = paging.unit === "pages" ? 1 : paging.size.value;
|
|
167
|
+
return Number(position) + step;
|
|
168
|
+
}
|
|
169
|
+
case "link-header":
|
|
170
|
+
return nextLink(paging.rel ?? "next", page, endpoint, report);
|
|
171
|
+
case "next-url": {
|
|
172
|
+
const next = selectOne(page.body, paging.next);
|
|
173
|
+
return typeof next === "string" && next !== ""
|
|
174
|
+
? checkOrigin(new URL(next, page.url), endpoint, report).href
|
|
175
|
+
: null;
|
|
176
|
+
}
|
|
177
|
+
default:
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|