esri-gl 0.9.0-alpha.9 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +366 -35
  2. package/dist/IdentifyImage-B1oeOjpm.js +4174 -0
  3. package/dist/IdentifyImage-B1oeOjpm.js.map +1 -0
  4. package/dist/index-DuO9oU8x.d.ts +1500 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +4 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/index.umd.js +4215 -0
  9. package/dist/index.umd.js.map +1 -0
  10. package/dist/package.json +69 -0
  11. package/dist/react-map-gl.d.ts +101 -0
  12. package/dist/react-map-gl.js +479 -0
  13. package/dist/react-map-gl.js.map +1 -0
  14. package/dist/react.d.ts +114 -0
  15. package/dist/react.js +406 -0
  16. package/dist/react.js.map +1 -0
  17. package/dist/useFeatureService-BSZr2zvH.d.ts +140 -0
  18. package/dist/useFeatureService-D2kPkS3Y.js +205 -0
  19. package/dist/useFeatureService-D2kPkS3Y.js.map +1 -0
  20. package/package.json +93 -47
  21. package/dist/esri-gl.esm.js +0 -2694
  22. package/dist/esri-gl.esm.js.map +0 -1
  23. package/dist/esri-gl.js +0 -2719
  24. package/dist/esri-gl.js.map +0 -1
  25. package/dist/esri-gl.min.js +0 -2
  26. package/dist/esri-gl.min.js.map +0 -1
  27. package/dist/types/Services/DynamicMapService.d.ts +0 -35
  28. package/dist/types/Services/FeatureService.d.ts +0 -48
  29. package/dist/types/Services/ImageService.d.ts +0 -32
  30. package/dist/types/Services/MapService.d.ts +0 -30
  31. package/dist/types/Services/MapServiceTypes.d.ts +0 -87
  32. package/dist/types/Services/Service.d.ts +0 -118
  33. package/dist/types/Services/SimpleMapService.d.ts +0 -30
  34. package/dist/types/Services/TiledMapService.d.ts +0 -28
  35. package/dist/types/Services/VectorBasemapStyle.d.ts +0 -9
  36. package/dist/types/Services/VectorTileService.d.ts +0 -41
  37. package/dist/types/Tasks/Find.d.ts +0 -85
  38. package/dist/types/Tasks/IdentifyFeatures.d.ts +0 -91
  39. package/dist/types/Tasks/IdentifyImage.d.ts +0 -107
  40. package/dist/types/Tasks/Query.d.ts +0 -180
  41. package/dist/types/Tasks/Task.d.ts +0 -50
  42. package/dist/types/examples/EsriLeafletStyleAPI.d.ts +0 -8
  43. package/dist/types/main.d.ts +0 -14
  44. package/dist/types/types.d.ts +0 -88
  45. package/dist/types/utils.d.ts +0 -4
package/README.md CHANGED
@@ -37,7 +37,13 @@ A TypeScript library that bridges Esri ArcGIS REST services with MapLibre GL JS
37
37
  - **Layer Definitions** - Filter data server-side using SQL-like expressions
38
38
  - **Time-aware Services** - Support for temporal data visualization
39
39
  - **Attribution Management** - Automatic service attribution handling
40
+ - **React Integration** - Hooks and components for React applications
41
+ - **React Map GL Support** - Direct integration with react-map-gl
40
42
  - **TypeScript Support** - Full type safety with comprehensive interfaces
43
+ - **ArcGIS Online (AGOL) Support** - Proper JSON error handling, token auth, and API key support
44
+ - **Feature Editing** - Add, update, delete features and apply batch edits
45
+ - **Attachments** - Query, add, and delete feature attachments
46
+ - **Query Pagination** - Automatic pagination through large result sets
41
47
 
42
48
  ## Installation
43
49
 
@@ -46,30 +52,7 @@ A TypeScript library that bridges Esri ArcGIS REST services with MapLibre GL JS
46
52
  npm install esri-gl
47
53
  ```
48
54
 
49
- ### Alpha/Beta Releases
50
- ```bash
51
- # Latest alpha release (current: v0.1.0-alpha.2)
52
- npm install esri-gl@alpha
53
-
54
- # Specific alpha version
55
- npm install esri-gl@0.1.0-alpha.2
56
55
 
57
- # Latest beta release
58
- npm install esri-gl@beta
59
- ```
60
-
61
- ### GitHub Packages (Alternative Registry)
62
- ```bash
63
- # Configure npm to use GitHub Packages for @muimsd scope
64
- npm config set @muimsd:registry https://npm.pkg.github.com/
65
-
66
- # Install from GitHub Packages
67
- npm install @muimsd/esri-gl
68
-
69
- # Or use the setup script
70
- ./scripts/github-packages.sh configure
71
- ./scripts/github-packages.sh install
72
- ```
73
56
 
74
57
  ## Quick Start
75
58
 
@@ -183,16 +166,60 @@ const service = new TiledMapService('source-id', map, {
183
166
  ```
184
167
 
185
168
  ### FeatureService
186
- Vector data with intelligent vector tile detection and automatic GeoJSON fallback.
169
+ Efficient tile-based feature loading from ArcGIS FeatureServers with PBF (Protocol Buffer) support for minimal payload size.
187
170
 
188
171
  ```typescript
189
172
  const service = new FeatureService('source-id', map, {
190
173
  url: 'https://example.com/arcgis/rest/services/MyService/FeatureServer/0',
191
- useVectorTiles: true, // Smart detection with fallback
192
- useBoundingBox: true, // Viewport-based loading
193
174
  where: '1=1',
194
175
  outFields: '*',
195
- maxRecordCount: 2000
176
+ // PBF options (requires ArcGIS Server 10.7+)
177
+ minZoom: 2, // Minimum zoom level for data requests
178
+ simplifyFactor: 0.3, // Geometry simplification (0-1)
179
+ precision: 8, // Coordinate decimal precision
180
+ useServiceBounds: true, // Limit requests to service extent
181
+ setAttributionFromService: true // Auto-set attribution
182
+ });
183
+
184
+ // Update filters dynamically
185
+ service.setWhere("STATUS = 'Active'");
186
+ service.setDate(new Date(), new Date('2024-01-01'));
187
+ service.setToken('your-token');
188
+
189
+ // Query features by location
190
+ const features = await service.getFeaturesByLonLat({ lng: -118, lat: 34 }, 100);
191
+
192
+ // Query by object IDs
193
+ const specific = await service.getFeaturesByObjectIds([1, 2, 3], true);
194
+ ```
195
+
196
+ #### Feature Editing (AGOL)
197
+
198
+ ```typescript
199
+ // Edit features on an AGOL Feature Service
200
+ const service = new FeatureService('editable-source', map, {
201
+ url: 'https://services.arcgis.com/.../FeatureServer/0',
202
+ token: 'your-agol-token'
203
+ });
204
+
205
+ // Add features
206
+ const addResults = await service.addFeatures([
207
+ { type: 'Feature', geometry: { type: 'Point', coordinates: [-95, 37] }, properties: { name: 'New Point' } }
208
+ ]);
209
+
210
+ // Update features
211
+ const updateResults = await service.updateFeatures([
212
+ { type: 'Feature', geometry: { type: 'Point', coordinates: [-95, 37] }, properties: { OBJECTID: 1, name: 'Updated' } }
213
+ ]);
214
+
215
+ // Delete features
216
+ const deleteResults = await service.deleteFeatures({ objectIds: [1, 2, 3] });
217
+
218
+ // Batch edits
219
+ const batchResults = await service.applyEdits({
220
+ adds: [newFeature],
221
+ updates: [updatedFeature],
222
+ deletes: [4, 5]
196
223
  });
197
224
  ```
198
225
 
@@ -236,6 +263,15 @@ const service = new VectorBasemapStyle('source-id', map, {
236
263
  });
237
264
  ```
238
265
 
266
+ ```typescript
267
+ // Custom portal item style
268
+ const customBasemap = new VectorBasemapStyle('source-id', map, {
269
+ style: 'arcgis/streets',
270
+ itemId: 'your-portal-item-id',
271
+ token: 'your-token'
272
+ });
273
+ ```
274
+
239
275
  ## Task-Based Operations
240
276
 
241
277
  Modeled after Esri Leaflet's chainable task pattern for querying and identifying features.
@@ -291,6 +327,252 @@ const results = await query({
291
327
  .run();
292
328
  ```
293
329
 
330
+ ```typescript
331
+ // Automatic pagination through all results
332
+ import { query } from 'esri-gl';
333
+
334
+ const allResults = await query({
335
+ url: 'https://example.com/arcgis/rest/services/MyService/FeatureServer/0'
336
+ })
337
+ .where("STATE_NAME = 'California'")
338
+ .runAll(); // Automatically paginates through all pages
339
+ ```
340
+
341
+ ## React Integration
342
+
343
+ esri-gl provides first-class React.js support with comprehensive hooks, components, and seamless integration with **react-map-gl**. Whether you're building with vanilla React + MapLibre/Mapbox or using the react-map-gl wrapper, esri-gl has you covered.
344
+
345
+ ### Installation for React Projects
346
+
347
+ ```bash
348
+ # Core library
349
+ npm install esri-gl
350
+
351
+ # For React hooks and components
352
+ npm install react react-dom @types/react @types/react-dom
353
+
354
+ # For react-map-gl integration (recommended)
355
+ npm install react-map-gl mapbox-gl
356
+ # OR for MapLibre
357
+ npm install react-map-gl maplibre-gl
358
+ ```
359
+
360
+ ### React Hooks Pattern
361
+
362
+ Perfect for custom React components with full control over map lifecycle:
363
+
364
+ ```typescript
365
+ import React, { useState, useRef, useEffect } from 'react';
366
+ import { Map } from 'maplibre-gl';
367
+ import { useDynamicMapService, useIdentifyFeatures, useFeatureService } from 'esri-gl/react';
368
+
369
+ function CustomMapComponent() {
370
+ const mapRef = useRef<HTMLDivElement>(null);
371
+ const [map, setMap] = useState<Map | null>(null);
372
+
373
+ // Initialize MapLibre map
374
+ useEffect(() => {
375
+ if (!mapRef.current) return;
376
+ const mapInstance = new Map({
377
+ container: mapRef.current,
378
+ style: 'https://demotiles.maplibre.org/style.json',
379
+ center: [-95, 37],
380
+ zoom: 4
381
+ });
382
+ setMap(mapInstance);
383
+ return () => mapInstance.remove();
384
+ }, []);
385
+
386
+ // Use esri-gl React hooks
387
+ const { service: dynamicService, loading, error } = useDynamicMapService({
388
+ sourceId: 'usa-service',
389
+ map,
390
+ options: {
391
+ url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer',
392
+ layers: [0, 1, 2],
393
+ transparent: true
394
+ }
395
+ });
396
+
397
+ const { service: featureService } = useFeatureService({
398
+ sourceId: 'states-service',
399
+ map,
400
+ options: {
401
+ url: 'https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/USA_Census_States/FeatureServer/0',
402
+ useVectorTiles: true,
403
+ useBoundingBox: true
404
+ }
405
+ });
406
+
407
+ const { identify } = useIdentifyFeatures({
408
+ url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer',
409
+ tolerance: 3
410
+ });
411
+
412
+ // Handle map clicks for identify
413
+ useEffect(() => {
414
+ if (!map) return;
415
+ const handleClick = async (e: any) => {
416
+ const results = await identify({ lng: e.lngLat.lng, lat: e.lngLat.lat }, map);
417
+ console.log('Identify results:', results);
418
+ };
419
+ map.on('click', handleClick);
420
+ return () => map.off('click', handleClick);
421
+ }, [map, identify]);
422
+
423
+ return (
424
+ <div>
425
+ <div ref={mapRef} style={{ width: '100%', height: '500px' }} />
426
+ {loading && <div>Loading Esri services...</div>}
427
+ {error && <div>Error: {error.message}</div>}
428
+ </div>
429
+ );
430
+ }
431
+ ```
432
+
433
+ ### React Map GL Components (Recommended)
434
+
435
+ For the smoothest React experience with declarative layer management:
436
+
437
+ ```typescript
438
+ import React, { useState } from 'react';
439
+ import { Map } from 'react-map-gl/mapbox';
440
+ import {
441
+ EsriDynamicLayer,
442
+ EsriFeatureLayer,
443
+ EsriVectorTileLayer,
444
+ EsriImageLayer
445
+ } from 'esri-gl/react-map-gl';
446
+
447
+ function MapWithEsriLayers() {
448
+ const [viewState, setViewState] = useState({
449
+ longitude: -95,
450
+ latitude: 37,
451
+ zoom: 4
452
+ });
453
+
454
+ const [selectedStates, setSelectedStates] = useState<string[]>([]);
455
+
456
+ return (
457
+ <Map
458
+ {...viewState}
459
+ onMove={evt => setViewState(evt.viewState)}
460
+ mapStyle="mapbox://styles/mapbox/streets-v11"
461
+ style={{ width: '100%', height: '600px' }}
462
+ >
463
+ {/* Dynamic Map Service Layer */}
464
+ <EsriDynamicLayer
465
+ id="usa-demographics"
466
+ url="https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer"
467
+ layers={[0, 1, 2]}
468
+ layerDefs={{
469
+ 0: "POP2000 > 100000",
470
+ 1: "STATE_NAME IN ('California', 'Texas', 'New York')"
471
+ }}
472
+ opacity={0.8}
473
+ beforeId="waterway-label"
474
+ />
475
+
476
+ {/* Feature Service with Vector Tiles */}
477
+ <EsriFeatureLayer
478
+ id="us-states"
479
+ url="https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/USA_Census_States/FeatureServer/0"
480
+ useVectorTiles={true}
481
+ useBoundingBox={true}
482
+ where={selectedStates.length > 0 ? `STATE_NAME IN ('${selectedStates.join("','")}')` : undefined}
483
+ paint={{
484
+ 'fill-color': [
485
+ 'case',
486
+ ['in', ['get', 'STATE_NAME'], ['literal', selectedStates]],
487
+ '#ff6b6b',
488
+ '#627BC1'
489
+ ],
490
+ 'fill-opacity': 0.6,
491
+ 'fill-outline-color': '#ffffff'
492
+ }}
493
+ onClick={(feature) => {
494
+ const stateName = feature.properties?.STATE_NAME;
495
+ if (stateName) {
496
+ setSelectedStates(prev =>
497
+ prev.includes(stateName)
498
+ ? prev.filter(s => s !== stateName)
499
+ : [...prev, stateName]
500
+ );
501
+ }
502
+ }}
503
+ />
504
+
505
+ {/* Vector Tile Service */}
506
+ <EsriVectorTileLayer
507
+ id="world-imagery-labels"
508
+ url="https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/VectorTileServer"
509
+ beforeId="usa-demographics"
510
+ />
511
+
512
+ {/* Image Service for Analytical Data */}
513
+ <EsriImageLayer
514
+ id="elevation-hillshade"
515
+ url="https://sampleserver6.arcgisonline.com/arcgis/rest/services/Elevation/ImageServer"
516
+ renderingRule={{
517
+ rasterFunction: "Hillshade",
518
+ rasterFunctionArguments: {
519
+ Azimuth: 315,
520
+ Altitude: 45
521
+ }
522
+ }}
523
+ opacity={0.5}
524
+ />
525
+ </Map>
526
+ );
527
+ }
528
+ ```
529
+
530
+ ### Why Choose React Integration?
531
+
532
+ #### React Hooks Benefits
533
+ - **🎛️ Full Control** - Direct access to map instance and service lifecycle
534
+ - **🔄 State Management** - Seamless integration with React state and effects
535
+ - **🎯 Custom Logic** - Perfect for complex interactions and custom components
536
+ - **📦 Lightweight** - Use only what you need
537
+
538
+ #### React Map GL Benefits
539
+ - **📋 Declarative** - Define layers as JSX components
540
+ - **🔄 Automatic Updates** - Props changes automatically update layers
541
+ - **🎨 Built-in Styling** - Direct paint and layout prop support
542
+ - **👆 Event Handling** - onClick, onHover events built-in
543
+ - **🏗️ Component Ecosystem** - Works with all react-map-gl features
544
+
545
+ ### TypeScript Support
546
+
547
+ Full TypeScript support with comprehensive type definitions:
548
+
549
+ ```typescript
550
+ import type {
551
+ DynamicMapServiceOptions,
552
+ FeatureServiceOptions,
553
+ IdentifyResult,
554
+ EsriLayerProps
555
+ } from 'esri-gl';
556
+ import type { MapRef } from 'react-map-gl/mapbox';
557
+
558
+ // Fully typed component props
559
+ interface MapComponentProps {
560
+ serviceUrl: string;
561
+ initialLayers?: number[];
562
+ onFeatureClick?: (feature: IdentifyResult) => void;
563
+ }
564
+
565
+ const TypedMapComponent: React.FC<MapComponentProps> = ({
566
+ serviceUrl,
567
+ initialLayers = [0],
568
+ onFeatureClick
569
+ }) => {
570
+ // Component implementation with full type safety
571
+ };
572
+ ```
573
+
574
+ See [REACT.md](REACT.md) for complete React integration documentation and advanced patterns.
575
+
294
576
  ## Advanced Features
295
577
 
296
578
  ### Dynamic Layer Management
@@ -341,14 +623,33 @@ const service = new FeatureService('optimized-source', map, {
341
623
  });
342
624
  ```
343
625
 
626
+ ### Authentication
627
+
628
+ ```typescript
629
+ // Token-based authentication (URL parameter)
630
+ const service = new DynamicMapService('secure-source', map, {
631
+ url: 'https://example.com/arcgis/rest/services/SecureService/MapServer',
632
+ token: 'your-auth-token'
633
+ });
634
+
635
+ // Update token dynamically
636
+ service.setToken('new-token');
637
+
638
+ // API Key authentication (X-Esri-Authorization header)
639
+ const featureService = new FeatureService('api-key-source', map, {
640
+ url: 'https://services.arcgis.com/.../FeatureServer/0',
641
+ apiKey: 'your-api-key' // Sent as X-Esri-Authorization: Bearer header
642
+ });
643
+ ```
644
+
344
645
  ## Development
345
646
 
346
647
  ### Build System
347
- - **Library Build**: Rollup with `@rollup/plugin-typescript` (UMD + ESM outputs)
348
- - **Type Declarations**: Consolidated in `dist/types/` directory
349
- - **Demo Development**: Vite dev server
648
+ - **Library Build**: Rollup with TypeScript, Babel, and Terser (UMD + ESM outputs)
649
+ - **Type Declarations**: Generated with rollup-plugin-dts in `dist/` directory
650
+ - **Demo Development**: Vite dev server with React and TypeScript
350
651
  - **Documentation**: Docusaurus build system
351
- - **Test Coverage**: 92.94% with 651 focused test cases
652
+ - **Test Coverage**: 717 comprehensive test cases across 31 test suites
352
653
 
353
654
  ### Development Commands
354
655
 
@@ -400,9 +701,13 @@ src/
400
701
  └── types.ts # TypeScript interfaces
401
702
 
402
703
  dist/
403
- ├── types/ # Consolidated TypeScript declarations
404
- ├── esri-gl.js # UMD build
405
- ├── esri-gl.esm.js # ESM build
704
+ ├── index.d.ts # Main TypeScript declarations
705
+ ├── react.d.ts # React integration declarations
706
+ ├── react-map-gl.d.ts # React Map GL declarations
707
+ ├── index.js # ESM build
708
+ ├── index.umd.js # UMD build
709
+ ├── esri-gl.esm.js # ESM build (legacy)
710
+ ├── esri-gl.js # UMD build (legacy)
406
711
  └── esri-gl.min.js # Minified UMD build
407
712
  ```
408
713
 
@@ -431,10 +736,12 @@ const options: FeatureServiceOptions = {
431
736
  };
432
737
  ```
433
738
 
434
- All type declarations are available in the `dist/types/` directory after building.
739
+ All type declarations are available in the `dist/` directory after building.
435
740
 
436
741
  ## Contributing
437
742
 
743
+ We welcome contributions! Please follow these steps:
744
+
438
745
  1. Fork the repository
439
746
  2. Create a feature branch: `git checkout -b feature/my-feature`
440
747
  3. Make changes and add tests
@@ -443,6 +750,17 @@ All type declarations are available in the `dist/types/` directory after buildin
443
750
  6. Push to branch: `git push origin feature/my-feature`
444
751
  7. Submit a pull request
445
752
 
753
+ ### Pre-commit Hooks
754
+
755
+ This project uses [Husky](https://typicode.github.io/husky/) to automatically run quality checks before each commit:
756
+
757
+ - **Formatting & Linting**: Automatically formats and lints staged files using Prettier and ESLint
758
+ - **Testing**: Runs the full test suite to ensure no regressions
759
+
760
+ The hooks are automatically installed when you run `npm install`. If you need to skip them (not recommended), you can use `git commit --no-verify`.
761
+
762
+ For more details, see [.husky/README.md](.husky/README.md).
763
+
446
764
  ## License
447
765
 
448
766
  MIT License - see [LICENSE](LICENSE) file for details.
@@ -453,3 +771,16 @@ MIT License - see [LICENSE](LICENSE) file for details.
453
771
  - **MapLibre GL JS** & **Mapbox GL JS** - Incredible WebGL mapping libraries
454
772
  - **Esri ArcGIS Platform** - Comprehensive GIS services and APIs
455
773
  - **[mapbox-gl-esri-sources](https://github.com/frontiersi/mapbox-gl-esri-sources/)** - Reference implementation for Esri service integration patterns
774
+ - **[mapbox-gl-arcgis-featureserver](https://github.com/rowanwins/mapbox-gl-arcgis-featureserver)** by **Rowan Winsemius** - The FeatureService implementation with PBF support is based on this excellent library. It provides efficient tile-based feature loading with Protocol Buffer Format (PBF) support for minimal payload size.
775
+
776
+ ## Fork Notice
777
+
778
+ This project originated as a fork of **[frontiersi/mapbox-gl-esri-sources](https://github.com/frontiersi/mapbox-gl-esri-sources/)**. It has been substantially refactored and expanded:
779
+
780
+ - Migrated to a service + task architecture similar to Esri Leaflet
781
+ - Added unified TypeScript typing and consolidated build outputs (ESM + UMD)
782
+ - Introduced additional services (Dynamic, Image, Vector Basemap Styles, Identify / Query tasks, smart FeatureService vector tile detection, etc.)
783
+ - Implemented a React/Vite demo suite and extended test coverage
784
+
785
+ All original credit for the foundational concept and early integration patterns goes to the maintainers of the upstream repository. If you need the simpler original implementation, or want to compare behavior, please visit the upstream project.
786
+