@ibicash/geolayers-sdk 1.0.2 → 1.1.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.
package/dist/index.cjs CHANGED
@@ -32,6 +32,11 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ActiveVolcanoPropsSchema: () => ActiveVolcanoPropsSchema,
34
34
  BboxObservationsResultSchema: () => BboxObservationsResultSchema,
35
+ ChartMeasurementsSchema: () => ChartMeasurementsSchema,
36
+ ChartMetaSchema: () => ChartMetaSchema,
37
+ ChartObservationSchema: () => ChartObservationSchema,
38
+ ChartResponseSchema: () => ChartResponseSchema,
39
+ ChartTimeRangeSchema: () => ChartTimeRangeSchema,
35
40
  DEFAULT_CONFIG: () => DEFAULT_CONFIG,
36
41
  EarthquakePropsSchema: () => EarthquakePropsSchema,
37
42
  EventPayloadSchema: () => EventPayloadSchema,
@@ -387,12 +392,36 @@ var ObservationStatsResultSchema = import_zod2.z.object({
387
392
  totalObservations: import_zod2.z.number(),
388
393
  source: import_zod2.z.literal("data-warehouse")
389
394
  });
395
+ var ChartMeasurementsSchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.number().optional());
396
+ var ChartObservationSchema = import_zod2.z.object({
397
+ stationId: import_zod2.z.string(),
398
+ timestamp: import_zod2.z.string(),
399
+ // ISO8601
400
+ measurements: ChartMeasurementsSchema
401
+ });
402
+ var ChartTimeRangeSchema = import_zod2.z.object({
403
+ start: import_zod2.z.string(),
404
+ // ISO8601
405
+ end: import_zod2.z.string()
406
+ // ISO8601
407
+ });
408
+ var ChartMetaSchema = import_zod2.z.object({
409
+ stationId: import_zod2.z.string(),
410
+ timeRange: ChartTimeRangeSchema,
411
+ count: import_zod2.z.number()
412
+ });
413
+ var ChartResponseSchema = import_zod2.z.object({
414
+ data: import_zod2.z.array(ChartObservationSchema),
415
+ meta: ChartMetaSchema
416
+ });
390
417
 
391
418
  // src/core/config.ts
392
419
  var DEFAULT_CONFIG = {
393
420
  baseUrl: (typeof process !== "undefined" ? process.env.GEOLAYERS_BASE_URL : void 0) || "",
394
421
  timeout: 3e4,
395
- retries: 2
422
+ retries: 2,
423
+ apiVersion: "v1",
424
+ apiBasePath: "/api"
396
425
  };
397
426
 
398
427
  // src/core/errors.ts
@@ -422,14 +451,79 @@ var GeoLayersValidationError = class extends GeoLayersError {
422
451
  var BaseClient = class {
423
452
  http;
424
453
  config;
454
+ preferredVersion;
425
455
  constructor(config) {
426
- this.config = { ...DEFAULT_CONFIG, ...config };
456
+ this.config = {
457
+ ...DEFAULT_CONFIG,
458
+ ...config,
459
+ apiBasePath: config.apiBasePath ?? DEFAULT_CONFIG.apiBasePath ?? "/api",
460
+ apiVersion: config.apiVersion ?? DEFAULT_CONFIG.apiVersion ?? "v1"
461
+ };
462
+ this.preferredVersion = this.config.apiVersion;
427
463
  this.http = import_axios.default.create({
428
464
  baseURL: this.config.baseUrl,
429
465
  timeout: this.config.timeout
430
466
  });
431
467
  this.setupInterceptors();
432
468
  }
469
+ /**
470
+ * Returns true if the SDK prefers API v2.
471
+ */
472
+ get isV2() {
473
+ return this.preferredVersion === "v2";
474
+ }
475
+ /**
476
+ * Returns the preferred API version.
477
+ */
478
+ get apiVersion() {
479
+ return this.preferredVersion;
480
+ }
481
+ /**
482
+ * Builds a versioned URL path.
483
+ * @param version API version to use
484
+ * @param endpoint Endpoint path (without version prefix)
485
+ */
486
+ buildVersionedPath(version, endpoint) {
487
+ const basePath = this.config.apiBasePath;
488
+ const normalizedEndpoint = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
489
+ return `${basePath}/${version}${normalizedEndpoint}`;
490
+ }
491
+ /**
492
+ * Resolves the appropriate URL based on API version and availability.
493
+ * Falls back to the other version if preferred is not available.
494
+ *
495
+ * @param endpoints Object with v1 and v2 URL paths (use null if unavailable)
496
+ * @returns ResolvedUrl with full path and selected version
497
+ * @throws Error if no endpoint is available for either version
498
+ */
499
+ resolveEndpoint(endpoints) {
500
+ if (this.isV2 && endpoints.v2 !== null) {
501
+ return {
502
+ url: this.buildVersionedPath("v2", endpoints.v2),
503
+ version: "v2"
504
+ };
505
+ }
506
+ if (endpoints.v1 !== null) {
507
+ return {
508
+ url: this.buildVersionedPath("v1", endpoints.v1),
509
+ version: "v1"
510
+ };
511
+ }
512
+ if (endpoints.v2 !== null) {
513
+ return {
514
+ url: this.buildVersionedPath("v2", endpoints.v2),
515
+ version: "v2"
516
+ };
517
+ }
518
+ throw new Error("No endpoint available for either API version");
519
+ }
520
+ /**
521
+ * Resolves URL - convenience method that returns just the URL string.
522
+ * Use resolveEndpoint() if you need to know which version was selected.
523
+ */
524
+ resolveUrl(endpoints) {
525
+ return this.resolveEndpoint(endpoints).url;
526
+ }
433
527
  setupInterceptors() {
434
528
  this.http.interceptors.request.use((config) => {
435
529
  config.headers["X-API-Key"] = this.config.apiKey;
@@ -498,6 +592,33 @@ var BaseClient = class {
498
592
  const schema = createLayerResponseSchema(createFeatureCollectionSchema(propsSchema));
499
593
  return schema.parse(data);
500
594
  }
595
+ /**
596
+ * Normalizes API responses to a consistent LayerResponse format.
597
+ * Handles both:
598
+ * - v1 responses: LayerResponse envelope with data field
599
+ * - v2 responses: Direct FeatureCollection
600
+ *
601
+ * @param data Raw response data from the API
602
+ * @param propsSchema Zod schema for feature properties
603
+ * @param provider Provider name to use when wrapping v2 responses
604
+ */
605
+ normalizeGeoJSONResponse(data, propsSchema, provider) {
606
+ const record = data;
607
+ if (record?.provider && record?.data && record?.timestamp) {
608
+ return this.parseGeoJSON(data, propsSchema);
609
+ }
610
+ if (record?.type === "FeatureCollection" && Array.isArray(record?.features)) {
611
+ const featureCollectionSchema = createFeatureCollectionSchema(propsSchema);
612
+ const featureCollection = featureCollectionSchema.parse(data);
613
+ return {
614
+ provider,
615
+ data: featureCollection,
616
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
617
+ count: featureCollection.features.length
618
+ };
619
+ }
620
+ return this.parseGeoJSON(data, propsSchema);
621
+ }
501
622
  };
502
623
 
503
624
  // src/domains/aviation.ts
@@ -507,33 +628,41 @@ var AviationDomain = class extends BaseClient {
507
628
  * @param filters Optional bounding box filters. Defaults to whole world.
508
629
  */
509
630
  async getGlobalFlights(filters = {}) {
631
+ const url = this.resolveUrl({
632
+ v1: "/geojson/flights/global",
633
+ v2: null
634
+ });
510
635
  const params = {
511
636
  lamin: filters.lamin ?? -90,
512
637
  lomin: filters.lomin ?? -180,
513
638
  lamax: filters.lamax ?? 90,
514
639
  lomax: filters.lomax ?? 180
515
640
  };
516
- const data = await this.get("/geojson/flights/global", params);
517
- return this.parseGeoJSON(data, FlightPropsSchema);
641
+ const data = await this.get(url, params);
642
+ return this.normalizeGeoJSONResponse(data, FlightPropsSchema, "global-flights");
518
643
  }
519
644
  /**
520
645
  * Get live flights (subset of global flights).
521
646
  * @param filters Center point and radius filters. Defaults to New York if not provided.
522
647
  */
523
648
  async getLiveFlights(filters = { lat: 40.7128, lng: -74.006 }) {
649
+ const url = this.resolveUrl({
650
+ v1: "/geojson/flights/live",
651
+ v2: null
652
+ });
524
653
  const params = {
525
654
  lat: filters.lat,
526
655
  lng: filters.lng,
527
656
  radius: filters.radius ?? 250
528
657
  };
529
- const data = await this.get("/geojson/flights/live", params);
530
- return this.parseGeoJSON(data, FlightPropsSchema);
658
+ const data = await this.get(url, params);
659
+ return this.normalizeGeoJSONResponse(data, FlightPropsSchema, "live-flights");
531
660
  }
532
661
  /**
533
662
  * Get flight schedule/details by callsign from AeroDataBox.
534
663
  * @param callsign Flight identifier (e.g., 'UAL1234', 'AA100')
535
664
  * @returns Raw flight schedule data from AeroDataBox API.
536
- *
665
+ *
537
666
  * @example
538
667
  * ```ts
539
668
  * const schedule = await sdk.aviation.getFlightSchedule('UAL1234');
@@ -541,7 +670,11 @@ var AviationDomain = class extends BaseClient {
541
670
  * ```
542
671
  */
543
672
  async getFlightSchedule(callsign) {
544
- const data = await this.get("/geojson/flights/schedule", { callsign });
673
+ const url = this.resolveUrl({
674
+ v1: "/geojson/flights/schedule",
675
+ v2: null
676
+ });
677
+ const data = await this.get(url, { callsign });
545
678
  return FlightScheduleResponseSchema.parse(data);
546
679
  }
547
680
  };
@@ -568,7 +701,7 @@ var EventsDomain = class extends BaseClient {
568
701
  /**
569
702
  * Get list of available event types for the event stream.
570
703
  * @returns Object with event types array and their descriptions.
571
- *
704
+ *
572
705
  * @example
573
706
  * ```ts
574
707
  * const { types, descriptions } = await sdk.eventsMeta.getEventTypes();
@@ -577,7 +710,11 @@ var EventsDomain = class extends BaseClient {
577
710
  * ```
578
711
  */
579
712
  async getEventTypes() {
580
- const data = await this.get("/events/types");
713
+ const url = this.resolveUrl({
714
+ v1: "/events/types",
715
+ v2: null
716
+ });
717
+ const data = await this.get(url);
581
718
  return EventTypesResponseSchema.parse(data);
582
719
  }
583
720
  };
@@ -589,9 +726,13 @@ var FireDomain = class extends BaseClient {
589
726
  * @param filters Optional filters. Default: last 1 day.
590
727
  */
591
728
  async getWildfires(filters = {}) {
729
+ const url = this.resolveUrl({
730
+ v1: "/geojson/wildfires",
731
+ v2: null
732
+ });
592
733
  const params = { days: filters.days ?? 1 };
593
- const data = await this.get("/geojson/wildfires", params);
594
- return this.parseGeoJSON(data, WildfirePropsSchema);
734
+ const data = await this.get(url, params);
735
+ return this.normalizeGeoJSONResponse(data, WildfirePropsSchema, "wildfires");
595
736
  }
596
737
  };
597
738
 
@@ -601,15 +742,23 @@ var MaritimeDomain = class extends BaseClient {
601
742
  * Get NOAA buoy stations (locations).
602
743
  */
603
744
  async getBuoyStations() {
604
- const data = await this.get("/geojson/buoys/stations");
605
- return this.parseGeoJSON(data, WeatherStationPropsSchema);
745
+ const url = this.resolveUrl({
746
+ v1: "/geojson/buoys/stations",
747
+ v2: "/stations?provider=buoy"
748
+ });
749
+ const data = await this.get(url);
750
+ return this.normalizeGeoJSONResponse(data, WeatherStationPropsSchema, "buoy-stations");
606
751
  }
607
752
  /**
608
753
  * Get latest buoy observations (real-time-ish).
609
754
  */
610
755
  async getLatestBuoyObservations() {
611
- const data = await this.get("/geojson/buoys/observations");
612
- return this.parseGeoJSON(data, WeatherStationPropsSchema);
756
+ const url = this.resolveUrl({
757
+ v1: "/geojson/buoys/observations",
758
+ v2: null
759
+ });
760
+ const data = await this.get(url);
761
+ return this.normalizeGeoJSONResponse(data, WeatherStationPropsSchema, "buoy-observations");
613
762
  }
614
763
  /**
615
764
  * Get historical observations for a specific buoy.
@@ -617,7 +766,11 @@ var MaritimeDomain = class extends BaseClient {
617
766
  * @param filters Date range filters.
618
767
  */
619
768
  async getBuoyObservations(buoyId, filters) {
620
- const data = await this.get(`/observations/buoy/${buoyId}`, filters);
769
+ const url = this.resolveUrl({
770
+ v1: `/observations/buoy/${buoyId}`,
771
+ v2: null
772
+ });
773
+ const data = await this.get(url, filters);
621
774
  return ObservationQueryResultSchema.parse(data);
622
775
  }
623
776
  };
@@ -628,15 +781,31 @@ var ObservationsDomain = class extends BaseClient {
628
781
  * Get active WIS2 stations that reported data in the last 24 hours.
629
782
  */
630
783
  async getActiveWis2Stations() {
631
- const rawData = await this.get("/observations/wis2/stations/active");
632
- return this.parseActiveStationsResponse(rawData, "wis2");
784
+ const url = this.resolveUrl({
785
+ v1: "/observations/wis2/stations/active",
786
+ v2: null
787
+ });
788
+ const rawData = await this.get(url);
789
+ return this.normalizeGeoJSONResponse(
790
+ rawData,
791
+ WeatherStationPropsSchema,
792
+ "active-wis2-stations"
793
+ );
633
794
  }
634
795
  /**
635
796
  * Get active IEM/AZOS stations that reported data in the last 24 hours.
636
797
  */
637
798
  async getActiveIemStations() {
638
- const rawData = await this.get("/observations/iem/stations/active");
639
- return this.parseActiveStationsResponse(rawData, "iem");
799
+ const url = this.resolveUrl({
800
+ v1: "/observations/iem/stations/active",
801
+ v2: null
802
+ });
803
+ const rawData = await this.get(url);
804
+ return this.normalizeGeoJSONResponse(
805
+ rawData,
806
+ WeatherStationPropsSchema,
807
+ "active-iem-stations"
808
+ );
640
809
  }
641
810
  /**
642
811
  * Get observations for a station from the data warehouse.
@@ -644,8 +813,12 @@ var ObservationsDomain = class extends BaseClient {
644
813
  * @param filters Query filters including provider and date range.
645
814
  */
646
815
  async getStationObservations(stationId, filters) {
816
+ const url = this.resolveUrl({
817
+ v1: `/observations/station/${stationId}`,
818
+ v2: `/observations/${stationId}/chart`
819
+ });
647
820
  const params = this.buildDateParams(filters);
648
- const data = await this.get(`/observations/station/${stationId}`, params);
821
+ const data = await this.get(url, params);
649
822
  return StationObservationsResultSchema.parse(data);
650
823
  }
651
824
  /**
@@ -654,7 +827,11 @@ var ObservationsDomain = class extends BaseClient {
654
827
  * @param provider The observation provider.
655
828
  */
656
829
  async getLatestObservation(stationId, provider) {
657
- const data = await this.get(`/observations/station/${stationId}/latest`, { provider });
830
+ const url = this.resolveUrl({
831
+ v1: `/observations/station/${stationId}/latest`,
832
+ v2: null
833
+ });
834
+ const data = await this.get(url, { provider });
658
835
  return LatestObservationResultSchema.parse(data);
659
836
  }
660
837
  /**
@@ -662,6 +839,10 @@ var ObservationsDomain = class extends BaseClient {
662
839
  * @param filters Bounding box coordinates and query filters.
663
840
  */
664
841
  async getObservationsByBbox(filters) {
842
+ const url = this.resolveUrl({
843
+ v1: "/observations/bbox",
844
+ v2: null
845
+ });
665
846
  const params = {
666
847
  ...this.buildDateParams(filters),
667
848
  minLon: filters.minLon,
@@ -669,7 +850,7 @@ var ObservationsDomain = class extends BaseClient {
669
850
  maxLon: filters.maxLon,
670
851
  maxLat: filters.maxLat
671
852
  };
672
- const data = await this.get("/observations/bbox", params);
853
+ const data = await this.get(url, params);
673
854
  return BboxObservationsResultSchema.parse(data);
674
855
  }
675
856
  /**
@@ -677,10 +858,34 @@ var ObservationsDomain = class extends BaseClient {
677
858
  * @param provider Optional provider filter. If not specified, returns stats for all providers.
678
859
  */
679
860
  async getStats(provider) {
861
+ const url = this.resolveUrl({
862
+ v1: "/observations/stats",
863
+ v2: null
864
+ });
680
865
  const params = provider ? { provider } : {};
681
- const data = await this.get("/observations/stats", params);
866
+ const data = await this.get(url, params);
682
867
  return ObservationStatsResultSchema.parse(data);
683
868
  }
869
+ /**
870
+ * Get chart-optimized observation data for a station (v2 only).
871
+ *
872
+ * The stationId should include the provider prefix in the format: `provider:native_id`
873
+ * Examples: 'wis2:0-123-456', 'iem:KJFK'
874
+ *
875
+ * @param stationId The station identifier with provider prefix (e.g., 'wis2:0-123-456')
876
+ * @param filters Time range filters (start required, end optional)
877
+ */
878
+ async getChartData(stationId, filters) {
879
+ const url = this.resolveUrl({
880
+ v1: null,
881
+ // v2 only endpoint
882
+ v2: `/observations/${stationId}/chart`
883
+ });
884
+ const params = { start: filters.start };
885
+ if (filters.end) params.end = filters.end;
886
+ const data = await this.get(url, params);
887
+ return ChartResponseSchema.parse(data);
888
+ }
684
889
  /**
685
890
  * Convert time preset to absolute date range parameters.
686
891
  */
@@ -710,34 +915,6 @@ var ObservationsDomain = class extends BaseClient {
710
915
  }
711
916
  return params;
712
917
  }
713
- /**
714
- * Parse active stations response.
715
- * The endpoint may return either a FeatureCollection directly or wrapped in LayerResponse.
716
- */
717
- parseActiveStationsResponse(rawData, provider) {
718
- const featureCollection = rawData;
719
- if (featureCollection?.type === "FeatureCollection") {
720
- const features = (featureCollection.features ?? []).map((f) => {
721
- const feature = f;
722
- return {
723
- type: "Feature",
724
- geometry: feature.geometry,
725
- properties: WeatherStationPropsSchema.parse(feature.properties ?? {}),
726
- id: feature.id
727
- };
728
- });
729
- return {
730
- provider: `active-stations-${provider}`,
731
- data: {
732
- type: "FeatureCollection",
733
- features
734
- },
735
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
736
- count: features.length
737
- };
738
- }
739
- return this.parseGeoJSON(rawData, WeatherStationPropsSchema);
740
- }
741
918
  };
742
919
 
743
920
  // src/domains/seismic.ts
@@ -789,8 +966,12 @@ var SeismicDomain = class extends BaseClient {
789
966
  ...timeRange,
790
967
  ...minMagnitude !== void 0 && { minMagnitude }
791
968
  };
792
- const data = await this.get("/geojson/earthquakes", params);
793
- return this.parseGeoJSON(data, EarthquakePropsSchema);
969
+ const url = this.resolveUrl({
970
+ v1: "/geojson/earthquakes",
971
+ v2: null
972
+ });
973
+ const data = await this.get(url, params);
974
+ return this.normalizeGeoJSONResponse(data, EarthquakePropsSchema, "earthquakes");
794
975
  }
795
976
  };
796
977
 
@@ -800,15 +981,23 @@ var TropicalDomain = class extends BaseClient {
800
981
  * Get list of currently active tropical storms/hurricanes.
801
982
  */
802
983
  async getActiveStorms() {
803
- const data = await this.get("/geojson/storms/active");
804
- return this.parseGeoJSON(data, StormPropsSchema);
984
+ const url = this.resolveUrl({
985
+ v1: "/geojson/storms/active",
986
+ v2: null
987
+ });
988
+ const data = await this.get(url);
989
+ return this.normalizeGeoJSONResponse(data, StormPropsSchema, "active-storms");
805
990
  }
806
991
  /**
807
992
  * Get list of recent tropical storms/hurricanes.
808
993
  */
809
994
  async getRecentStorms() {
810
- const data = await this.get("/geojson/storms/recent");
811
- return this.parseGeoJSON(data, StormPropsSchema);
995
+ const url = this.resolveUrl({
996
+ v1: "/geojson/storms/recent",
997
+ v2: null
998
+ });
999
+ const data = await this.get(url);
1000
+ return this.normalizeGeoJSONResponse(data, StormPropsSchema, "recent-storms");
812
1001
  }
813
1002
  };
814
1003
 
@@ -827,7 +1016,11 @@ var VolcanicDomain = class extends BaseClient {
827
1016
  * Note: API returns array of Features, normalized to FeatureCollection here.
828
1017
  */
829
1018
  async getVolcanoes() {
830
- const raw = await this.get("/geojson/volcanoes");
1019
+ const url = this.resolveUrl({
1020
+ v1: "/geojson/volcanoes",
1021
+ v2: null
1022
+ });
1023
+ const raw = await this.get(url);
831
1024
  const parsed = VolcanoesResponseSchema.parse(raw);
832
1025
  return {
833
1026
  provider: parsed.provider,
@@ -844,8 +1037,12 @@ var VolcanicDomain = class extends BaseClient {
844
1037
  * Get list of currently active volcanoes (GDACS).
845
1038
  */
846
1039
  async getActiveVolcanoes() {
847
- const data = await this.get("/geojson/volcanoes/active");
848
- return this.parseGeoJSON(data, ActiveVolcanoPropsSchema);
1040
+ const url = this.resolveUrl({
1041
+ v1: "/geojson/volcanoes/active",
1042
+ v2: null
1043
+ });
1044
+ const data = await this.get(url);
1045
+ return this.normalizeGeoJSONResponse(data, ActiveVolcanoPropsSchema, "active-volcanoes");
849
1046
  }
850
1047
  };
851
1048
 
@@ -856,12 +1053,16 @@ var WeatherDomain = class extends BaseClient {
856
1053
  * @param filters Optional pagination filters.
857
1054
  */
858
1055
  async getWis2Stations(filters = {}) {
859
- const params = {
1056
+ const { url, version } = this.resolveEndpoint({
1057
+ v1: "/geojson/stations/wis2",
1058
+ v2: "/stations?provider=wis2"
1059
+ });
1060
+ const params = version === "v2" ? filters : {
860
1061
  limit: filters.limit ?? 100,
861
1062
  offset: filters.offset ?? 0
862
1063
  };
863
- const data = await this.get("/geojson/stations/wis2", params);
864
- return this.parseGeoJSON(data, WeatherStationPropsSchema);
1064
+ const data = await this.get(url, params);
1065
+ return this.normalizeGeoJSONResponse(data, WeatherStationPropsSchema, "wis2-stations");
865
1066
  }
866
1067
  /**
867
1068
  * Get historical observations for a WIS2 station.
@@ -869,15 +1070,23 @@ var WeatherDomain = class extends BaseClient {
869
1070
  * @param filters Date range and optional WIS2-specific filters.
870
1071
  */
871
1072
  async getWis2Observations(stationId, filters) {
872
- const data = await this.get(`/observations/wis2/${stationId}`, filters);
1073
+ const url = this.resolveUrl({
1074
+ v1: `/observations/wis2/${stationId}`,
1075
+ v2: null
1076
+ });
1077
+ const data = await this.get(url, filters);
873
1078
  return ObservationQueryResultSchema.parse(data);
874
1079
  }
875
1080
  /**
876
1081
  * Get weather stations from IEM/AZOS network.
877
1082
  */
878
1083
  async getIemStations() {
879
- const data = await this.get("/geojson/stations/azos");
880
- return this.parseGeoJSON(data, WeatherStationPropsSchema);
1084
+ const { url, version } = this.resolveEndpoint({
1085
+ v1: "/geojson/stations/azos",
1086
+ v2: "/stations?provider=iem"
1087
+ });
1088
+ const data = await this.get(url);
1089
+ return this.normalizeGeoJSONResponse(data, WeatherStationPropsSchema, "iem-stations");
881
1090
  }
882
1091
  /**
883
1092
  * Get historical observations for an IEM station.
@@ -885,46 +1094,35 @@ var WeatherDomain = class extends BaseClient {
885
1094
  * @param filters Date range filters.
886
1095
  */
887
1096
  async getIemObservations(stationId, filters) {
888
- const data = await this.get(`/observations/iem/${stationId}`, filters);
1097
+ const url = this.resolveUrl({
1098
+ v1: `/observations/iem/${stationId}`,
1099
+ v2: null
1100
+ });
1101
+ const data = await this.get(url, filters);
889
1102
  return ObservationQueryResultSchema.parse(data);
890
1103
  }
891
1104
  /**
892
1105
  * Get weather stations from NWS (National Weather Service) network.
893
1106
  */
894
1107
  async getNWSWeatherStations() {
895
- const data = await this.get("/geojson/stations/nws");
896
- return this.parseGeoJSON(data, WeatherStationPropsSchema);
1108
+ const url = this.resolveUrl({
1109
+ v1: "/geojson/stations/nws",
1110
+ v2: null
1111
+ });
1112
+ const data = await this.get(url);
1113
+ return this.normalizeGeoJSONResponse(data, WeatherStationPropsSchema, "nws-stations");
897
1114
  }
898
1115
  /**
899
1116
  * Get active stations that have reported data in the last 24 hours.
900
1117
  * @param type The station network type ('iem' or 'wis2').
901
- *
902
- * Note: This endpoint returns FeatureCollection directly (not LayerResponse envelope).
903
1118
  */
904
1119
  async getActiveStations(type) {
905
- const rawData = await this.get("/stations/active", { type });
906
- const featureCollection = rawData;
907
- if (featureCollection?.type === "FeatureCollection") {
908
- const features = (featureCollection.features ?? []).map((f) => {
909
- const feature = f;
910
- return {
911
- type: "Feature",
912
- geometry: feature.geometry,
913
- properties: WeatherStationPropsSchema.parse(feature.properties ?? {}),
914
- id: feature.id
915
- };
916
- });
917
- return {
918
- provider: `active-stations-${type}`,
919
- data: {
920
- type: "FeatureCollection",
921
- features
922
- },
923
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
924
- count: features.length
925
- };
926
- }
927
- return this.parseGeoJSON(rawData, WeatherStationPropsSchema);
1120
+ const url = this.resolveUrl({
1121
+ v1: "/stations/active",
1122
+ v2: null
1123
+ });
1124
+ const rawData = await this.get(url, { type });
1125
+ return this.normalizeGeoJSONResponse(rawData, WeatherStationPropsSchema, `active-stations-${type}`);
928
1126
  }
929
1127
  };
930
1128
 
@@ -935,7 +1133,9 @@ var EventStream = class extends import_events.EventEmitter {
935
1133
  url;
936
1134
  constructor(config) {
937
1135
  super();
938
- this.url = `${config.baseUrl}/events/stream?apiKey=${config.apiKey}`;
1136
+ const baseUrl = config.baseUrl;
1137
+ const apiBasePath = config.apiBasePath ?? DEFAULT_CONFIG.apiBasePath ?? "/api";
1138
+ this.url = `${baseUrl}${apiBasePath}/v1/events/stream?apiKey=${config.apiKey}`;
939
1139
  }
940
1140
  /**
941
1141
  * Start listening to the event stream.
@@ -1007,6 +1207,11 @@ var index_default = GeoLayersSDK;
1007
1207
  0 && (module.exports = {
1008
1208
  ActiveVolcanoPropsSchema,
1009
1209
  BboxObservationsResultSchema,
1210
+ ChartMeasurementsSchema,
1211
+ ChartMetaSchema,
1212
+ ChartObservationSchema,
1213
+ ChartResponseSchema,
1214
+ ChartTimeRangeSchema,
1010
1215
  DEFAULT_CONFIG,
1011
1216
  EarthquakePropsSchema,
1012
1217
  EventPayloadSchema,