jupytergis-core 0.4.5__tar.gz → 0.6.0__tar.gz
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.
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/.gitignore +1 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/PKG-INFO +1 -1
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/_version.py +1 -1
- jupytergis_core-0.6.0/jupytergis_core/handler.py +321 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/jgis_ydoc.py +13 -1
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/package.json +7 -5
- jupytergis_core-0.6.0/jupytergis_core/labextension/schemas/@jupytergis/jupytergis-core/jupytergis-settings.json +13 -0
- jupytergis_core-0.6.0/jupytergis_core/labextension/schemas/@jupytergis/jupytergis-core/package.json.orig +123 -0
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/27.aea9e291ba3dd16790fb.js → jupytergis_core-0.6.0/jupytergis_core/labextension/static/27.6ee794baeb00791424c2.js +2 -2
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/397.a6fa5a4d29479f45b270.js +1 -0
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/432.48d67c4273f9195419e3.js +1 -0
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/552.0936beb209d3ea5a1229.js +1 -0
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/634.2747a436e7df0c53f51b.js +8 -0
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/729.6eae404678a803e58788.js.LICENSE.txt → jupytergis_core-0.6.0/jupytergis_core/labextension/static/634.2747a436e7df0c53f51b.js.LICENSE.txt +50 -0
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/671.b8a4f9c5fd02e51ec026.js +1 -0
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/803.5f3759c98814aa602705.js +8 -0
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/991.443bcba88f6a112c4b9e.js → jupytergis_core-0.6.0/jupytergis_core/labextension/static/991.35a1ef3613255bda4218.js +1 -1
- jupytergis_core-0.6.0/jupytergis_core/labextension/static/remoteEntry.0d09a4d6aa378d4b27c2.js +1 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/third-party-licenses.json +303 -9
- jupytergis_core-0.6.0/jupytergis_core/schema/__init__.py +24 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/__init__.py +3 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/export/__init__.py +3 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/export/exportGeoJson.py +18 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/export/exportGeoTiff.py +28 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/geoJsonSource.py +20 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/geojson.py +502 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/__init__.py +3 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/boundingBoxes.py +14 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/buffer.py +23 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/centroids.py +14 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/concaveHull.py +21 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/convexHull.py +14 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/processing/dissolve.py +24 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/__init__.py +3 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/jgis.py +137 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/__init__.py +3 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/heatmapLayer.py +30 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/hillshadeLayer.py +19 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/imageLayer.py +19 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/rasterLayer.py +19 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/stacLayer.py +19 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/vectorLayer.py +57 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/vectorTileLayer.py +22 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/layers/webGlLayer.py +58 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/__init__.py +3 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/geoTiffSource.py +27 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/imageSource.py +29 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/rasterDemSource.py +23 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/rasterSource.py +36 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/shapefileSource.py +31 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/vectorTileSource.py +27 -0
- jupytergis_core-0.6.0/jupytergis_core/schema/interfaces/project/sources/videoSource.py +30 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/factory.js +6 -3
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/index.js +2 -2
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/jgisplugin/modelfactory.d.ts +3 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/jgisplugin/modelfactory.js +5 -2
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/jgisplugin/plugins.js +44 -58
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/plugin.js +9 -9
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/package.json +6 -4
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/pyproject.toml +5 -1
- jupytergis_core-0.6.0/schema/jupytergis-settings.json +13 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/externalcommand.ts +1 -1
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/factory.ts +15 -13
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/index.ts +2 -2
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/jgisplugin/modelfactory.ts +9 -3
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/jgisplugin/plugins.ts +53 -71
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/layerBrowserRegistry.ts +1 -1
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/plugin.ts +12 -12
- jupytergis_core-0.6.0/tsconfig.tsbuildinfo +1 -0
- jupytergis_core-0.4.5/jupytergis_core/handler.py +0 -45
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/31.ab2fa4c30bddf5b8e6b6.js +0 -1
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/432.df2bee6966bdd5a48317.js +0 -1
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/552.3f267df0d8b2c9ef2c40.js +0 -1
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/656.c0f842aa97967d6d91f2.js +0 -1
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/729.6eae404678a803e58788.js +0 -8
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/803.8b9c4e2f8bed9130b6d0.js +0 -8
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/remoteEntry.2155bee6ff3895543404.js +0 -1
- jupytergis_core-0.4.5/tsconfig.tsbuildinfo +0 -1
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/LICENSE +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/README.md +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupyter-config/server-config/jupytergis_core.json +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/__init__.py +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/026680ab0cd1523edc87.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/02ff7d503bbd90b21fc4.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/062a9554f6b4caac9713.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/064f37cecb8130ad66e8.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/08da2741746ddab81d04.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/0c6a0352b82839119f95.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/13c485bb93f5567f02fd.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/1474207a6b3ca1001e78.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/14b98240613d5256c621.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/154.0d16fbe1d1182d138b2c.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/1b97ea0f2b3af717cffa.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/1d440270da19a2f22fee.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/1ed164e010f3c0306d15.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/2218dfba22fc2b08e948.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/234.2f0fc49f516ad354aa18.js +0 -0
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/27.aea9e291ba3dd16790fb.js.LICENSE.txt → jupytergis_core-0.6.0/jupytergis_core/labextension/static/27.6ee794baeb00791424c2.js.LICENSE.txt +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/2ab791b60c4058e664f8.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/2b24b6a745c11511f055.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/2d676bc0a01c2cd2fccb.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/2f02309ea499725612ea.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/32c7a73662cceb5bb1d7.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/350eec4ce9ae4bc10bca.wasm +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/363ca7c5f78deb6fd033.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/376.58a6410b7089dea5b0d5.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/3ae0bf244442de7efc35.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/3d48be10ffea86eb15de.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/407.da5d00862f4879fe3c9c.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/415edc3fa381260cf31e.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/42cbddf5e883673bc4e2.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/472.b2ea9ebc35d5ad4e1fcc.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/527ef171d5df15dc7da5.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/542.477a73b8682de0e8d45e.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/555.be80e60305924af2e139.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/5bb02252f243f8c7494f.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/5d181edc3c046e1454a1.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/5f32ad48aefe00e51312.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/618.86523276f857e0a3362e.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/6e4f6b4d0dfca3bd4450.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/71d436fb44627b6bfbd7.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/7b225dc2d37cd3582156.png +0 -0
- jupytergis_core-0.4.5/jupytergis_core/labextension/static/803.8b9c4e2f8bed9130b6d0.js.LICENSE.txt → jupytergis_core-0.6.0/jupytergis_core/labextension/static/803.5f3759c98814aa602705.js.LICENSE.txt +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/843ab141e62516b9df5c.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/8814e17f6b110e8f3e42.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/88b2ae0d29edb684eae5.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/971a42d174dd17b9451a.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/a3c609f5bff95a7a53be.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/a86d626c9ed2e222d190.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/a9e286b0c0264a9fc737.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/ab309078b494f850430a.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/b15e3989b7b90b5a8d9d.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/b36717fbb06f21d53b01.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/ba4b6e82fe5a816c40a5.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/bb2b310570da7a3587e9.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/be92bcf7bb99753b4b3d.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/c2ffa011d7f52a0ddf45.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/d83457b1b925c1718f6d.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/e473e1e9f20af114bbb4.data +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/f2617180c6907263a7ff.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/fe99a6dbf5a71d308989.png +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/jupytergis_core/labextension/static/style.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/externalcommand.d.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/externalcommand.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/factory.d.ts +4 -4
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/index.d.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/jgisplugin/plugins.d.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/layerBrowserRegistry.d.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/layerBrowserRegistry.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/plugin.d.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/schemaregistry.d.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/lib/schemaregistry.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/scripts/bump-version.py +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/setup.py +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/src/schemaregistry.ts +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/style/base.css +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/style/index.css +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/style/index.js +0 -0
- {jupytergis_core-0.4.5 → jupytergis_core-0.6.0}/tsconfig.json +0 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Dict, Optional, Set
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
import tornado
|
|
10
|
+
from jupyter_server.base.handlers import APIHandler
|
|
11
|
+
from jupyter_server.utils import url_path_join
|
|
12
|
+
from tornado.httpclient import AsyncHTTPClient, HTTPRequest, HTTPResponse
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class ProxyConfig:
|
|
17
|
+
"""Configuration for the proxy handler."""
|
|
18
|
+
|
|
19
|
+
default_timeout: int
|
|
20
|
+
max_redirects: int
|
|
21
|
+
max_body_size: int
|
|
22
|
+
rate_limit_requests: int
|
|
23
|
+
rate_limit_window: int
|
|
24
|
+
cors_origin: str
|
|
25
|
+
exempt_domains: Set[str]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def load_config() -> ProxyConfig:
|
|
29
|
+
"""Load configuration from environment variables with defaults."""
|
|
30
|
+
return ProxyConfig(
|
|
31
|
+
default_timeout=int(os.environ.get("JGIS_TIMEOUT", "30")),
|
|
32
|
+
max_redirects=int(os.environ.get("JGIS_MAX_REDIRECTS", "3")),
|
|
33
|
+
max_body_size=int(os.environ.get("JGIS_MAX_BODY_SIZE", str(10 * 1024 * 1024))),
|
|
34
|
+
rate_limit_requests=int(os.environ.get("JGIS_RATE_LIMIT_REQUESTS", "100")),
|
|
35
|
+
rate_limit_window=int(os.environ.get("JGIS_RATE_LIMIT_WINDOW", "60")),
|
|
36
|
+
cors_origin=os.environ.get("JGIS_CORS_ORIGIN", "*"),
|
|
37
|
+
exempt_domains=os.environ.get(
|
|
38
|
+
"JGIS_EXEMPT_DOMAINS",
|
|
39
|
+
{
|
|
40
|
+
"https://geodes.cnes.fr",
|
|
41
|
+
"https://gdh-portal-prod.cnes.fr",
|
|
42
|
+
"https://geodes-portal.cnes.fr/api/stac/",
|
|
43
|
+
},
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# Configure logging
|
|
49
|
+
logger = logging.getLogger(__name__)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ProxyError(Exception):
|
|
53
|
+
"""Base exception for proxy-related errors."""
|
|
54
|
+
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ValidationError(ProxyError):
|
|
59
|
+
"""Raised when request validation fails."""
|
|
60
|
+
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class RateLimitError(ProxyError):
|
|
65
|
+
"""Raised when rate limit is exceeded."""
|
|
66
|
+
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ProxyHandler(APIHandler):
|
|
71
|
+
"""Secure proxy handler with enhanced validation and async processing."""
|
|
72
|
+
|
|
73
|
+
def initialize(self) -> None:
|
|
74
|
+
"""Initialize the handler with configuration and HTTP client."""
|
|
75
|
+
self.proxy_config = load_config()
|
|
76
|
+
self._request_timestamps = []
|
|
77
|
+
self.http_client = AsyncHTTPClient(
|
|
78
|
+
defaults={
|
|
79
|
+
"connect_timeout": self.proxy_config.default_timeout,
|
|
80
|
+
"request_timeout": self.proxy_config.default_timeout,
|
|
81
|
+
"max_redirects": self.proxy_config.max_redirects,
|
|
82
|
+
"max_body_size": self.proxy_config.max_body_size,
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def _check_rate_limit(self) -> None:
|
|
87
|
+
"""Check if the current request exceeds rate limits.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
RateLimitError: If rate limit is exceeded
|
|
91
|
+
"""
|
|
92
|
+
current_time = time.time()
|
|
93
|
+
window_start = current_time - self.proxy_config.rate_limit_window
|
|
94
|
+
|
|
95
|
+
# Remove old timestamps
|
|
96
|
+
self._request_timestamps = [
|
|
97
|
+
ts for ts in self._request_timestamps if ts > window_start
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
if len(self._request_timestamps) >= self.proxy_config.rate_limit_requests:
|
|
101
|
+
raise RateLimitError("Rate limit exceeded")
|
|
102
|
+
|
|
103
|
+
self._request_timestamps.append(current_time)
|
|
104
|
+
|
|
105
|
+
@tornado.web.authenticated
|
|
106
|
+
async def get(self) -> None:
|
|
107
|
+
"""Process GET requests with validation and error handling."""
|
|
108
|
+
await self._handle_request("GET")
|
|
109
|
+
|
|
110
|
+
@tornado.web.authenticated
|
|
111
|
+
async def post(self) -> None:
|
|
112
|
+
"""Process POST requests with validation and error handling."""
|
|
113
|
+
await self._handle_request("POST")
|
|
114
|
+
|
|
115
|
+
async def _handle_request(self, method: str) -> None:
|
|
116
|
+
"""Central request handling method.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
method: The HTTP method to use (GET or POST)
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
tornado.web.HTTPError: If the request fails validation or processing
|
|
123
|
+
"""
|
|
124
|
+
try:
|
|
125
|
+
# Check rate limit
|
|
126
|
+
self._check_rate_limit()
|
|
127
|
+
|
|
128
|
+
# Validate and parse input
|
|
129
|
+
url = self._validate_url(self.get_argument("url"))
|
|
130
|
+
body = await self._validate_body(method)
|
|
131
|
+
|
|
132
|
+
logger.info("Proxying %s request to: %s", method, url)
|
|
133
|
+
|
|
134
|
+
# Make async HTTP request
|
|
135
|
+
response = await self._make_request(url, method, body)
|
|
136
|
+
|
|
137
|
+
# Forward response
|
|
138
|
+
self._set_response_headers(response)
|
|
139
|
+
self.finish(response.body)
|
|
140
|
+
|
|
141
|
+
except RateLimitError as e:
|
|
142
|
+
logger.warning("Rate limit exceeded: %s", e)
|
|
143
|
+
self.set_status(429)
|
|
144
|
+
self.finish(
|
|
145
|
+
json.dumps(
|
|
146
|
+
{
|
|
147
|
+
"error": "Rate limit exceeded",
|
|
148
|
+
"code": "rate_limit_error",
|
|
149
|
+
"message": str(e),
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
except ValidationError as e:
|
|
155
|
+
logger.warning("Validation error: %s", e)
|
|
156
|
+
self.set_status(400)
|
|
157
|
+
self.finish(
|
|
158
|
+
json.dumps(
|
|
159
|
+
{
|
|
160
|
+
"error": "Validation error",
|
|
161
|
+
"code": "validation_error",
|
|
162
|
+
"message": str(e),
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
except tornado.web.HTTPError as e:
|
|
168
|
+
logger.warning("Client error: %s", e)
|
|
169
|
+
raise
|
|
170
|
+
|
|
171
|
+
except Exception as e:
|
|
172
|
+
logger.exception("Proxy request failed")
|
|
173
|
+
self._handle_error_response(e)
|
|
174
|
+
|
|
175
|
+
def _validate_url(self, url: str) -> str:
|
|
176
|
+
"""Validate and sanitize target URL.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
url: The URL to validate
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
The validated URL
|
|
183
|
+
|
|
184
|
+
Raises:
|
|
185
|
+
ValidationError: If the URL is invalid
|
|
186
|
+
"""
|
|
187
|
+
parsed = urlparse(url)
|
|
188
|
+
|
|
189
|
+
if parsed.scheme not in ("http", "https"):
|
|
190
|
+
raise ValidationError("Invalid protocol")
|
|
191
|
+
|
|
192
|
+
return url
|
|
193
|
+
|
|
194
|
+
async def _validate_body(self, method: str) -> Optional[str]:
|
|
195
|
+
"""Validate and prepare request body.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
method: The HTTP method being used
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
The validated and prepared request body, or None for GET requests
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
ValidationError: If the body is invalid
|
|
205
|
+
"""
|
|
206
|
+
if method == "POST":
|
|
207
|
+
try:
|
|
208
|
+
body = self.get_json_body()
|
|
209
|
+
if not body or not isinstance(body, Dict):
|
|
210
|
+
raise ValidationError("Invalid JSON body")
|
|
211
|
+
|
|
212
|
+
# Validate body size
|
|
213
|
+
body_str = json.dumps(body)
|
|
214
|
+
if len(body_str.encode("utf-8")) > self.proxy_config.max_body_size:
|
|
215
|
+
raise ValidationError("Request body too large")
|
|
216
|
+
|
|
217
|
+
return body_str
|
|
218
|
+
except json.JSONDecodeError as e:
|
|
219
|
+
raise ValidationError("Malformed JSON payload") from e
|
|
220
|
+
|
|
221
|
+
return None
|
|
222
|
+
|
|
223
|
+
async def _make_request(
|
|
224
|
+
self, url: str, method: str, body: Optional[str] = None
|
|
225
|
+
) -> HTTPResponse:
|
|
226
|
+
"""Execute proxy request with safety controls.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
url: The target URL
|
|
230
|
+
method: The HTTP method to use
|
|
231
|
+
body: Optional request body
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
The HTTP response
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
tornado.web.HTTPError: If the request fails
|
|
238
|
+
"""
|
|
239
|
+
try:
|
|
240
|
+
parsed_url = urlparse(url)
|
|
241
|
+
host = parsed_url.netloc.split(":")[0] # Remove port if present
|
|
242
|
+
|
|
243
|
+
# Disable SSL verification for exempt domains
|
|
244
|
+
validate_cert = host not in self.proxy_config.exempt_domains
|
|
245
|
+
logger.info("validate_cert: %s", validate_cert)
|
|
246
|
+
|
|
247
|
+
request = HTTPRequest(
|
|
248
|
+
url=url,
|
|
249
|
+
method=method,
|
|
250
|
+
body=body,
|
|
251
|
+
headers={"Content-Type": "application/json"} if body else None,
|
|
252
|
+
validate_cert=validate_cert,
|
|
253
|
+
allow_nonstandard_methods=False,
|
|
254
|
+
decompress_response=True,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
return await self.http_client.fetch(request)
|
|
258
|
+
|
|
259
|
+
except tornado.httpclient.HTTPClientError as e:
|
|
260
|
+
logger.error("Upstream error: %d %s", e.code, e.message)
|
|
261
|
+
raise tornado.web.HTTPError(e.code, "Upstream service error") from e
|
|
262
|
+
|
|
263
|
+
except tornado.httpclient.HTTPError as e:
|
|
264
|
+
logger.error("Network error: %s", str(e))
|
|
265
|
+
raise tornado.web.HTTPError(503, "Service unavailable") from e
|
|
266
|
+
|
|
267
|
+
def _set_response_headers(self, response: HTTPResponse) -> None:
|
|
268
|
+
"""Set secure CORS and content headers.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
response: The HTTP response to get headers from
|
|
272
|
+
"""
|
|
273
|
+
self.set_header("Access-Control-Allow-Origin", self.proxy_config.cors_origin)
|
|
274
|
+
self.set_header("Access-Control-Allow-Methods", "GET, POST")
|
|
275
|
+
self.set_header(
|
|
276
|
+
"Access-Control-Allow-Headers",
|
|
277
|
+
"Content-Type, Authorization, X-Requested-With",
|
|
278
|
+
)
|
|
279
|
+
self.set_header("Content-Security-Policy", "default-src 'none'")
|
|
280
|
+
self.set_header(
|
|
281
|
+
"Content-Type", response.headers.get("Content-Type", "application/json")
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def _handle_error_response(self, error: Exception) -> None:
|
|
285
|
+
"""Standardized error response handling.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
error: The exception that occurred
|
|
289
|
+
"""
|
|
290
|
+
self.set_status(500)
|
|
291
|
+
self.finish(
|
|
292
|
+
json.dumps(
|
|
293
|
+
{
|
|
294
|
+
"error": "Internal server error",
|
|
295
|
+
"code": "internal_error",
|
|
296
|
+
"message": str(error),
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def setup_handlers(web_app: Any) -> None:
|
|
303
|
+
"""Register handlers with configuration validation.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
web_app: The Jupyter web application instance
|
|
307
|
+
"""
|
|
308
|
+
host_pattern = ".*$"
|
|
309
|
+
base_url = web_app.settings["base_url"]
|
|
310
|
+
|
|
311
|
+
# Configure proxy route
|
|
312
|
+
proxy_route = url_path_join(base_url, "jupytergis_core", "proxy")
|
|
313
|
+
handlers = [(proxy_route, ProxyHandler)]
|
|
314
|
+
|
|
315
|
+
# Add feature flags
|
|
316
|
+
if os.environ.get("JGIS_EXPOSE_MAPS", False):
|
|
317
|
+
web_app.settings.setdefault("page_config_data", {})
|
|
318
|
+
web_app.settings["page_config_data"]["jgis_expose_maps"] = True
|
|
319
|
+
|
|
320
|
+
web_app.add_handlers(host_pattern, handlers)
|
|
321
|
+
logger.info("JupyterGIS proxy endpoint initialized at: %s", proxy_route)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import Any, Callable
|
|
3
3
|
from functools import partial
|
|
4
|
+
from packaging.version import Version
|
|
4
5
|
|
|
5
6
|
from pycrdt import Array, Map
|
|
6
7
|
from jupyter_ydoc.ybasedoc import YBaseDoc
|
|
8
|
+
from .schema import SCHEMA_VERSION
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class YJGIS(YBaseDoc):
|
|
@@ -16,7 +18,7 @@ class YJGIS(YBaseDoc):
|
|
|
16
18
|
self._ydoc["metadata"] = self._ymetadata = Map()
|
|
17
19
|
|
|
18
20
|
def version(self) -> str:
|
|
19
|
-
return
|
|
21
|
+
return SCHEMA_VERSION
|
|
20
22
|
|
|
21
23
|
def get(self) -> str:
|
|
22
24
|
"""
|
|
@@ -31,6 +33,7 @@ class YJGIS(YBaseDoc):
|
|
|
31
33
|
layers_tree = self._ylayerTree.to_py()
|
|
32
34
|
return json.dumps(
|
|
33
35
|
dict(
|
|
36
|
+
schemaVersion=SCHEMA_VERSION,
|
|
34
37
|
layers=layers,
|
|
35
38
|
sources=sources,
|
|
36
39
|
options=options,
|
|
@@ -49,6 +52,15 @@ class YJGIS(YBaseDoc):
|
|
|
49
52
|
"""
|
|
50
53
|
valueDict = json.loads(value)
|
|
51
54
|
|
|
55
|
+
# Assuming file version 0.5.0 if the version is not specified
|
|
56
|
+
file_version = (
|
|
57
|
+
Version(valueDict["schemaVersion"])
|
|
58
|
+
if "schemaVersion" in valueDict
|
|
59
|
+
else Version("0.5.0")
|
|
60
|
+
)
|
|
61
|
+
if file_version > Version(SCHEMA_VERSION):
|
|
62
|
+
raise ValueError(f"Cannot load file version {file_version}")
|
|
63
|
+
|
|
52
64
|
with self._ydoc.transaction():
|
|
53
65
|
self._ylayers.clear()
|
|
54
66
|
self._ylayers.update(valueDict.get("layers", {}))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupytergis/jupytergis-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "JupyterGIS core extension",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jupyter",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"author": "JupyterGIS contributors",
|
|
16
16
|
"files": [
|
|
17
17
|
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
|
|
18
|
-
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
|
|
18
|
+
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
|
|
19
|
+
"schema/**/*.{json,js,ts}"
|
|
19
20
|
],
|
|
20
21
|
"main": "lib/index.js",
|
|
21
22
|
"types": "lib/index.d.ts",
|
|
@@ -53,8 +54,8 @@
|
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"@jupyter/collaborative-drive": "^3.0.0",
|
|
56
|
-
"@jupytergis/base": "^0.
|
|
57
|
-
"@jupytergis/schema": "^0.
|
|
57
|
+
"@jupytergis/base": "^0.6.0",
|
|
58
|
+
"@jupytergis/schema": "^0.6.0",
|
|
58
59
|
"@jupyterlab/application": "^4.3.0",
|
|
59
60
|
"@jupyterlab/apputils": "^4.3.0",
|
|
60
61
|
"@jupyterlab/docregistry": "^4.3.0",
|
|
@@ -91,6 +92,7 @@
|
|
|
91
92
|
"access": "public"
|
|
92
93
|
},
|
|
93
94
|
"jupyterlab": {
|
|
95
|
+
"schemaDir": "schema",
|
|
94
96
|
"discovery": {
|
|
95
97
|
"server": {
|
|
96
98
|
"managers": [
|
|
@@ -118,7 +120,7 @@
|
|
|
118
120
|
}
|
|
119
121
|
},
|
|
120
122
|
"_build": {
|
|
121
|
-
"load": "static/remoteEntry.
|
|
123
|
+
"load": "static/remoteEntry.0d09a4d6aa378d4b27c2.js",
|
|
122
124
|
"extension": "./extension",
|
|
123
125
|
"style": "./style"
|
|
124
126
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "JupyterGIS Settings",
|
|
3
|
+
"description": "Settings for the JupyterGIS extension.",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"proxyUrl": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"title": "Proxy URL",
|
|
9
|
+
"description": "The proxy URL to use for external requests.",
|
|
10
|
+
"default": "https://corsproxy.io"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jupytergis/jupytergis-core",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "JupyterGIS core extension",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"jupyter",
|
|
7
|
+
"jupyterlab",
|
|
8
|
+
"jupyterlab-extension"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/geojupyter/jupytergis",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/geojupyter/jupytergis/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "BSD-3-Clause",
|
|
15
|
+
"author": "JupyterGIS contributors",
|
|
16
|
+
"files": [
|
|
17
|
+
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
|
|
18
|
+
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
|
|
19
|
+
"schema/**/*.{json,js,ts}"
|
|
20
|
+
],
|
|
21
|
+
"main": "lib/index.js",
|
|
22
|
+
"types": "lib/index.d.ts",
|
|
23
|
+
"style": "style/index.css",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/geojupyter/jupytergis.git"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "jlpm build:lib && jlpm build:labextension:dev",
|
|
30
|
+
"build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
|
|
31
|
+
"build:labextension": "jupyter labextension build .",
|
|
32
|
+
"build:labextension:dev": "jupyter labextension build --development True .",
|
|
33
|
+
"build:lib": "tsc --sourceMap",
|
|
34
|
+
"build:lib:prod": "tsc",
|
|
35
|
+
"build:dev": "jlpm run build",
|
|
36
|
+
"clean": "jlpm clean:lib",
|
|
37
|
+
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
|
|
38
|
+
"clean:lintcache": "rimraf .eslintcache .stylelintcache",
|
|
39
|
+
"clean:labextension": "rimraf jupytergis_core/labextension jupytergis_core/_version.py",
|
|
40
|
+
"clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache",
|
|
41
|
+
"eslint": "jlpm eslint:check --fix",
|
|
42
|
+
"eslint:check": "eslint . --cache --ext .ts,.tsx",
|
|
43
|
+
"install:extension": "jlpm build",
|
|
44
|
+
"lint": "jlpm stylelint && jlpm prettier && jlpm eslint",
|
|
45
|
+
"lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check",
|
|
46
|
+
"prettier": "jlpm prettier:base --write",
|
|
47
|
+
"prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"",
|
|
48
|
+
"prettier:check": "jlpm prettier:base --check",
|
|
49
|
+
"stylelint": "jlpm stylelint:check --fix",
|
|
50
|
+
"stylelint:check": "stylelint --cache \"style/**/*.css\"",
|
|
51
|
+
"watch": "run-p watch:src watch:labextension",
|
|
52
|
+
"watch:src": "tsc -w --sourceMap",
|
|
53
|
+
"watch:labextension": "jupyter labextension watch ."
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@jupyter/collaborative-drive": "^3.0.0",
|
|
57
|
+
"@jupytergis/base": "^0.6.0",
|
|
58
|
+
"@jupytergis/schema": "^0.6.0",
|
|
59
|
+
"@jupyterlab/application": "^4.3.0",
|
|
60
|
+
"@jupyterlab/apputils": "^4.3.0",
|
|
61
|
+
"@jupyterlab/docregistry": "^4.3.0",
|
|
62
|
+
"@jupyterlab/filebrowser": "^4.3.0",
|
|
63
|
+
"@jupyterlab/launcher": "^4.3.0",
|
|
64
|
+
"@jupyterlab/mainmenu": "^4.3.0",
|
|
65
|
+
"@jupyterlab/services": "^7.3.0",
|
|
66
|
+
"@jupyterlab/translation": "^4.3.0",
|
|
67
|
+
"@jupyterlab/ui-components": "^4.3.0",
|
|
68
|
+
"@lumino/commands": "^2.0.0",
|
|
69
|
+
"util": "^0.12.5"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@jupyterlab/builder": "^4.3.0",
|
|
73
|
+
"@types/json-schema": "^7.0.11",
|
|
74
|
+
"@types/react": "^18.0.26",
|
|
75
|
+
"@types/react-addons-linked-state-mixin": "^0.14.22",
|
|
76
|
+
"copy-webpack-plugin": "^10.0.0",
|
|
77
|
+
"css-loader": "^6.7.1",
|
|
78
|
+
"mkdirp": "^1.0.3",
|
|
79
|
+
"npm-run-all": "^4.1.5",
|
|
80
|
+
"rimraf": "^3.0.2",
|
|
81
|
+
"style-loader": "^3.3.1",
|
|
82
|
+
"typescript": "^5",
|
|
83
|
+
"webpack": "^5.76.3",
|
|
84
|
+
"yjs": "^13.5.0"
|
|
85
|
+
},
|
|
86
|
+
"sideEffects": [
|
|
87
|
+
"style/*.css",
|
|
88
|
+
"style/index.js"
|
|
89
|
+
],
|
|
90
|
+
"styleModule": "style/index.js",
|
|
91
|
+
"publishConfig": {
|
|
92
|
+
"access": "public"
|
|
93
|
+
},
|
|
94
|
+
"jupyterlab": {
|
|
95
|
+
"schemaDir": "schema",
|
|
96
|
+
"discovery": {
|
|
97
|
+
"server": {
|
|
98
|
+
"managers": [
|
|
99
|
+
"pip"
|
|
100
|
+
],
|
|
101
|
+
"base": {
|
|
102
|
+
"name": "jupytergis_core"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"extension": true,
|
|
107
|
+
"outputDir": "jupytergis_core/labextension",
|
|
108
|
+
"sharedPackages": {
|
|
109
|
+
"@jupytergis/base": {
|
|
110
|
+
"singleton": true,
|
|
111
|
+
"bundled": true
|
|
112
|
+
},
|
|
113
|
+
"@jupytergis/schema": {
|
|
114
|
+
"singleton": true,
|
|
115
|
+
"bundled": true
|
|
116
|
+
},
|
|
117
|
+
"@jupyter/docprovider": {
|
|
118
|
+
"singleton": true,
|
|
119
|
+
"bundled": false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|