react-native-pointr 10.7.1 → 10.9.0

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.
@@ -12,7 +12,24 @@ import React
12
12
  class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
13
13
 
14
14
  private var hasListeners = false
15
-
15
+
16
+ /// Names of the events emitted to JS through the event emitter. JS reads
17
+ /// them from `PTREvents` in `src/constants/index.ts` and Android declares
18
+ /// them in `PTRNativeLibrary`'s companion object — the three must match.
19
+ ///
20
+ /// The payload keys of these events live in `PTRBridgeKeys.EventPayloadKeys`.
21
+ enum EventNames {
22
+ static let onPositionManagerCalculatedLocation = "OnPositionManagerCalculatedLocation"
23
+ static let onBuildingClicked = "OnBuildingClicked"
24
+ static let onSiteClicked = "OnSiteClicked"
25
+ static let onGeofenceEvent = "OnGeofenceEvent"
26
+ static let onDataManagerStartDataManagementForSite = "OnDataManagerStartDataManagementForSite"
27
+ static let onDataManagerCompleteAllForSite = "OnDataManagerCompleteAllForSite"
28
+ static let onDataManagerBeginProcessingDataForSite = "OnDataManagerBeginProcessingDataForSite"
29
+ static let onDataManagerEndProcessingDataForSite = "OnDataManagerEndProcessingDataForSite"
30
+ static let onDataManagerReadyForSite = "OnDataManagerReadyForSite"
31
+ }
32
+
16
33
  // PointrApp functionality moved here
17
34
  @objc public weak var eventManagerDelegate: PTREventManagerDelegate?
18
35
  @objc public static var shouldRequestPermissionsAtStartup: Bool = true
@@ -78,10 +95,15 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
78
95
 
79
96
  override func supportedEvents() -> [String]! {
80
97
  return [
81
- "OnPositionManagerCalculatedLocation",
82
- "OnBuildingClicked",
83
- "OnSiteClicked",
84
- "OnGeofenceEvent",
98
+ EventNames.onPositionManagerCalculatedLocation,
99
+ EventNames.onBuildingClicked,
100
+ EventNames.onSiteClicked,
101
+ EventNames.onGeofenceEvent,
102
+ EventNames.onDataManagerStartDataManagementForSite,
103
+ EventNames.onDataManagerCompleteAllForSite,
104
+ EventNames.onDataManagerBeginProcessingDataForSite,
105
+ EventNames.onDataManagerEndProcessingDataForSite,
106
+ EventNames.onDataManagerReadyForSite,
85
107
  ]
86
108
  }
87
109
 
@@ -242,6 +264,7 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
242
264
  if Pointr.shared.state == .running {
243
265
  Pointr.shared.positioningManager?.addListener(self)
244
266
  Pointr.shared.geofenceManager?.addListener(self)
267
+ Pointr.shared.dataManager?.addListener(self)
245
268
  resolve(nil)
246
269
  } else {
247
270
  let stateStr = self.getPointrStateStringFromPointrState(state: Pointr.shared.state)
@@ -252,6 +275,7 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
252
275
  @objc func stop() {
253
276
  Pointr.shared.positioningManager?.removeListener(self)
254
277
  Pointr.shared.geofenceManager?.removeListener(self)
278
+ Pointr.shared.dataManager?.removeListener(self)
255
279
  Pointr.shared.stop()
256
280
  }
257
281
 
@@ -347,6 +371,150 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
347
371
  resolve(poisData)
348
372
  }
349
373
 
374
+ // MARK: - Data Manager
375
+
376
+ @objc(loadDataForSite:shouldRespectCachePolicy:isExternalIdentifier:resolver:rejecter:)
377
+ func loadDataForSite(_ siteId: String,
378
+ shouldRespectCachePolicy: Bool,
379
+ isExternalIdentifier: Bool,
380
+ resolver resolve: @escaping RCTPromiseResolveBlock,
381
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
382
+ guard let site = resolveSite(siteId, isExternalIdentifier: isExternalIdentifier) else {
383
+ reject("SITE_NOT_FOUND", "Site not found: \(siteId)", nil)
384
+ return
385
+ }
386
+ Pointr.shared.dataManager?.loadData(forSite: site.internalIdentifier,
387
+ shouldRespectCachePolicy: shouldRespectCachePolicy)
388
+ resolve(nil)
389
+ }
390
+
391
+ @objc(isSiteContentReady:isExternalIdentifier:resolver:rejecter:)
392
+ func isSiteContentReady(_ siteId: String,
393
+ isExternalIdentifier: Bool,
394
+ resolver resolve: @escaping RCTPromiseResolveBlock,
395
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
396
+ guard let site = resolveSite(siteId, isExternalIdentifier: isExternalIdentifier) else {
397
+ reject("SITE_NOT_FOUND", "Site not found: \(siteId)", nil)
398
+ return
399
+ }
400
+ let ready = Pointr.shared.dataManager?.isContentReady(forSite: site.internalIdentifier) ?? false
401
+ resolve(ready)
402
+ }
403
+
404
+ private func resolveSite(_ siteId: String, isExternalIdentifier: Bool) -> PTRSite? {
405
+ guard let siteManager = Pointr.shared.siteManager else { return nil }
406
+ return isExternalIdentifier
407
+ ? siteManager.site(withExternalIdentifier: siteId)
408
+ : siteManager.site(withInternalIdentifier: siteId)
409
+ }
410
+
411
+ // MARK: - Site Manager
412
+
413
+ @objc(getSite:isExternalIdentifier:resolver:rejecter:)
414
+ func getSite(_ siteId: String,
415
+ isExternalIdentifier: Bool,
416
+ resolver resolve: @escaping RCTPromiseResolveBlock,
417
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
418
+ if let site = resolveSite(siteId, isExternalIdentifier: isExternalIdentifier) {
419
+ resolve(site.dict)
420
+ } else {
421
+ resolve(NSNull())
422
+ }
423
+ }
424
+
425
+ @objc(getSiteBuildings:isExternalIdentifier:resolver:rejecter:)
426
+ func getSiteBuildings(_ siteId: String,
427
+ isExternalIdentifier: Bool,
428
+ resolver resolve: @escaping RCTPromiseResolveBlock,
429
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
430
+ guard let site = resolveSite(siteId, isExternalIdentifier: isExternalIdentifier) else {
431
+ reject("SITE_NOT_FOUND", "Site not found: \(siteId)", nil)
432
+ return
433
+ }
434
+ let buildings = Pointr.shared.siteManager?.buildings(forSiteId: site.internalIdentifier) ?? []
435
+ resolve(buildings.map { $0.dict })
436
+ }
437
+
438
+ @objc(getBuilding:buildingId:isExternalIdentifier:resolver:rejecter:)
439
+ func getBuilding(_ siteId: String,
440
+ buildingId: String,
441
+ isExternalIdentifier: Bool,
442
+ resolver resolve: @escaping RCTPromiseResolveBlock,
443
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
444
+ guard let siteManager = Pointr.shared.siteManager else {
445
+ reject("NOT_READY", "Site manager is not available", nil)
446
+ return
447
+ }
448
+ // Unknown site resolves null rather than rejecting, matching Android's
449
+ // getBuilding, which returns null for a site it cannot find.
450
+ guard let site = resolveSite(siteId, isExternalIdentifier: isExternalIdentifier) else {
451
+ resolve(NSNull())
452
+ return
453
+ }
454
+ // PointrKit's sync accessors search globally, so the result has to be
455
+ // checked against the requested site — Android scopes the lookup itself.
456
+ // The site-scoped async variants are not used here: they resolve nil
457
+ // until the site's content is ready, which would make this return null
458
+ // for buildings that `getSiteBuildings` already returns.
459
+ let building = isExternalIdentifier
460
+ ? siteManager.building(withExternalIdentifier: buildingId)
461
+ : siteManager.building(withInternalIdentifier: buildingId)
462
+ if let building = building,
463
+ building.site.internalIdentifier == site.internalIdentifier {
464
+ resolve(building.dict)
465
+ } else {
466
+ resolve(NSNull())
467
+ }
468
+ }
469
+
470
+ @objc(getLevelByExternalIdentifier:levelExternalIdentifier:resolver:rejecter:)
471
+ func getLevelByExternalIdentifier(_ buildingExternalIdentifier: String,
472
+ levelExternalIdentifier: String,
473
+ resolver resolve: @escaping RCTPromiseResolveBlock,
474
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
475
+ // PointrKit takes (level, building); this bridge and the Android SDK take
476
+ // (building, level). Keep the labels explicit so the order can't drift.
477
+ let level = Pointr.shared.siteManager?.level(
478
+ withExternalIdentifier: levelExternalIdentifier,
479
+ buildingExternalIdentifier: buildingExternalIdentifier
480
+ )
481
+ if let level = level {
482
+ typealias ModelKeys = PTRBridgeKeys.ModelKeys
483
+ resolve([
484
+ ModelKeys.identifier: level.identifier,
485
+ ModelKeys.externalIdentifier: level.externalIdentifier,
486
+ ModelKeys.name: level.name,
487
+ ModelKeys.index: level.index
488
+ ])
489
+ } else {
490
+ resolve(NSNull())
491
+ }
492
+ }
493
+
494
+ @objc(getMapUrl:isExternalIdentifier:resolver:rejecter:)
495
+ func getMapUrl(_ siteId: String,
496
+ isExternalIdentifier: Bool,
497
+ resolver resolve: @escaping RCTPromiseResolveBlock,
498
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
499
+ guard let site = resolveSite(siteId, isExternalIdentifier: isExternalIdentifier) else {
500
+ reject("SITE_NOT_FOUND", "Site not found: \(siteId)", nil)
501
+ return
502
+ }
503
+ Pointr.shared.siteManager?.mapUrl(forSite: site.internalIdentifier) { mapUrl, error in
504
+ if let error = error {
505
+ reject("ERROR", error, nil)
506
+ } else {
507
+ resolve(mapUrl?.absoluteString)
508
+ }
509
+ }
510
+ }
511
+
512
+ @objc(getStyleJsonUrl:rejecter:)
513
+ func getStyleJsonUrl(_ resolve: @escaping RCTPromiseResolveBlock,
514
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
515
+ resolve(Pointr.shared.siteManager?.styleJsonURL()?.absoluteString)
516
+ }
517
+
350
518
  // MARK: - Sites & Buildings
351
519
 
352
520
  @objc
@@ -494,22 +662,22 @@ class PTRNativeLibrary: RCTEventEmitter, PTREventManagerDelegate {
494
662
 
495
663
  func onPositionManagerCalculatedLocation(location: [String : Any]) {
496
664
  guard hasListeners else { return }
497
- sendEvent(withName: "OnPositionManagerCalculatedLocation", body: location)
665
+ sendEvent(withName: EventNames.onPositionManagerCalculatedLocation, body: location)
498
666
  }
499
667
 
500
668
  func onGeofenceEvent(_ geofenceEvent: [String: Any]) {
501
669
  guard hasListeners else { return }
502
- sendEvent(withName: "OnGeofenceEvent", body: geofenceEvent)
670
+ sendEvent(withName: EventNames.onGeofenceEvent, body: geofenceEvent)
503
671
  }
504
672
 
505
673
  func onBuildingClicked(_ building: [String : Any]) {
506
674
  guard hasListeners else { return }
507
- sendEvent(withName: "OnBuildingClicked", body: building)
675
+ sendEvent(withName: EventNames.onBuildingClicked, body: building)
508
676
  }
509
677
 
510
678
  func onSiteClicked(_ site: [String : Any]) {
511
679
  guard hasListeners else { return }
512
- sendEvent(withName: "OnSiteClicked", body: site)
680
+ sendEvent(withName: EventNames.onSiteClicked, body: site)
513
681
  }
514
682
  }
515
683
 
@@ -526,6 +694,91 @@ extension PTRNativeLibrary: PTRGeofenceManagerDelegate {
526
694
  }
527
695
  }
528
696
 
697
+ // MARK: - PTRDataManagerDelegate
698
+ extension PTRNativeLibrary: PTRDataManagerDelegate {
699
+ private typealias Keys = PTRBridgeKeys.EventPayloadKeys
700
+
701
+ @objc func onDataManagerStartDataManagement(for site: PTRSite, dataFromOnline isOnlineData: Bool) {
702
+ guard hasListeners else { return }
703
+ sendEvent(withName: EventNames.onDataManagerStartDataManagementForSite, body: [
704
+ Keys.site: site.dict,
705
+ Keys.isOnlineData: isOnlineData,
706
+ ])
707
+ }
708
+
709
+ @objc func onDataManagerCompleteAll(for site: PTRSite,
710
+ isSuccessful: Bool,
711
+ dataFromOnline isOnlineData: Bool,
712
+ errorMessages: [NSNumber: String]) {
713
+ guard hasListeners else { return }
714
+ sendEvent(withName: EventNames.onDataManagerCompleteAllForSite, body: [
715
+ Keys.site: site.dict,
716
+ Keys.isSuccessful: isSuccessful,
717
+ Keys.isOnlineData: isOnlineData,
718
+ Keys.errors: Array(errorMessages.values),
719
+ ])
720
+ }
721
+
722
+ @objc func onDataManagerBeginProcessingData(for site: PTRSite,
723
+ dataType: PTRDataType,
724
+ dataFromOnline isOnlineData: Bool) {
725
+ guard hasListeners else { return }
726
+ sendEvent(withName: EventNames.onDataManagerBeginProcessingDataForSite, body: [
727
+ Keys.site: site.dict,
728
+ Keys.dataType: dataTypeDict(dataType),
729
+ Keys.isOnlineData: isOnlineData,
730
+ ])
731
+ }
732
+
733
+ @objc func onDataManagerEndProcessingData(for site: PTRSite,
734
+ dataType: PTRDataType,
735
+ dataFromOnline isOnlineData: Bool,
736
+ isSuccessful: Bool,
737
+ errorMessages: [String]) {
738
+ guard hasListeners else { return }
739
+ sendEvent(withName: EventNames.onDataManagerEndProcessingDataForSite, body: [
740
+ Keys.site: site.dict,
741
+ Keys.dataType: dataTypeDict(dataType),
742
+ Keys.isOnlineData: isOnlineData,
743
+ Keys.isSuccessful: isSuccessful,
744
+ Keys.errors: errorMessages,
745
+ ])
746
+ }
747
+
748
+ @objc func onDataManagerReady(for site: PTRSite) {
749
+ guard hasListeners else { return }
750
+ sendEvent(withName: EventNames.onDataManagerReadyForSite, body: [
751
+ Keys.site: site.dict,
752
+ ])
753
+ }
754
+
755
+ private func dataTypeDict(_ dataType: PTRDataType) -> [String: Any] {
756
+ return [
757
+ Keys.dataTypeValue: dataType.rawValue,
758
+ Keys.dataTypeName: dataTypeName(dataType),
759
+ ]
760
+ }
761
+
762
+ private func dataTypeName(_ dataType: PTRDataType) -> String {
763
+ switch dataType {
764
+ case .poi: return "Poi"
765
+ case .beacon: return "Beacon"
766
+ case .obstacle: return "Obstacle"
767
+ case .configuration: return "Config"
768
+ case .graph: return "Graph"
769
+ case .versions: return "Versions"
770
+ case .geofence: return "Geofence"
771
+ case .sites: return "Sites"
772
+ case .featureType: return "FeatureType"
773
+ case .beaconUuid: return "BeaconUuid"
774
+ case .client: return "Client"
775
+ case .buildings: return "Buildings"
776
+ case .mapContent: return "MapContent"
777
+ default: return "Unknown"
778
+ }
779
+ }
780
+ }
781
+
529
782
  // MARK: - PTRExitButtonEventsListener
530
783
  extension PTRNativeLibrary: PTRExitButtonEventsListener {
531
784
  func exitButtonDidTap() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-pointr",
3
- "version": "10.7.1",
3
+ "version": "10.9.0",
4
4
  "description": "Pointr React-Native Module",
5
5
  "main": "src/index",
6
6
  "files": [
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
16
16
 
17
17
  s.source_files = "ios/**/*.{h,m,mm,swift}"
18
18
 
19
- s.dependency 'PointrKit', '10.7.0'
19
+ s.dependency 'PointrKit', '10.9.0'
20
20
 
21
21
  # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
22
22
  # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
@@ -36,10 +36,39 @@ export interface Spec extends TurboModule {
36
36
  // ─── Config ─────────────────────────────────────────────────────────────────
37
37
  setPointrMapWidgetConfiguration(configJson: string): void;
38
38
 
39
+ // ─── Data Manager ─────────────────────────────────────────────────────────────
40
+ loadDataForSite(
41
+ siteId: string,
42
+ shouldRespectCachePolicy: boolean,
43
+ isExternalIdentifier: boolean
44
+ ): Promise<void>;
45
+ isSiteContentReady(
46
+ siteId: string,
47
+ isExternalIdentifier: boolean
48
+ ): Promise<boolean>;
49
+
39
50
  // ─── POIs ───────────────────────────────────────────────────────────────────
40
51
  getPois(siteId: string): Promise<Object[]>;
41
52
  searchPois(siteId: string, query: string): Promise<Object[]>;
42
53
 
54
+ // ─── Site Manager ─────────────────────────────────────────────────────────────
55
+ getSite(siteId: string, isExternalIdentifier: boolean): Promise<Object | null>;
56
+ getSiteBuildings(
57
+ siteId: string,
58
+ isExternalIdentifier: boolean
59
+ ): Promise<Object[]>;
60
+ getBuilding(
61
+ siteId: string,
62
+ buildingId: string,
63
+ isExternalIdentifier: boolean
64
+ ): Promise<Object | null>;
65
+ getLevelByExternalIdentifier(
66
+ buildingExternalIdentifier: string,
67
+ levelExternalIdentifier: string
68
+ ): Promise<Object | null>;
69
+ getMapUrl(siteId: string, isExternalIdentifier: boolean): Promise<string | null>;
70
+ getStyleJsonUrl(): Promise<string | null>;
71
+
43
72
  // ─── Sites & Buildings ──────────────────────────────────────────────────────
44
73
  getSites(): Promise<Object[]>;
45
74
  getBuildings(siteId: string): Promise<Object[]>;
@@ -8,8 +8,15 @@ import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
8
8
  import type { PTRConfiguration, PTRMapWidgetConfiguration } from '../types/config';
9
9
  import type { PTRPosition } from '../types/PTRPosition';
10
10
  import type { PTRPoi } from '../types/PTRPoi';
11
- import type { PTRSite, PTRBuilding } from '../types/PTRSite';
12
- import type { PTRGeofence } from '../types/events';
11
+ import type { PTRSite, PTRBuilding, PTRLevel } from '../types/PTRSite';
12
+ import type {
13
+ PTRGeofence,
14
+ PTRDataManagerStartEvent,
15
+ PTRDataManagerCompleteAllEvent,
16
+ PTRDataManagerBeginProcessingEvent,
17
+ PTRDataManagerEndProcessingEvent,
18
+ PTRDataManagerReadyEvent,
19
+ } from '../types/events';
13
20
  import { PTRState, PTRLogLevel, PTRErrorMessages, PTREvents } from '../constants';
14
21
 
15
22
  const LINKING_ERROR =
@@ -172,6 +179,45 @@ export class PointrSdk {
172
179
  return this.eventEmitter.addListener(PTREvents.ON_GEOFENCE_EVENT, callback);
173
180
  }
174
181
 
182
+ // ─── Data manager events ─────────────────────────────────────────────────────
183
+
184
+ /** Subscribe to data-management-start events. */
185
+ public onDataManagerStart(callback: (event: PTRDataManagerStartEvent) => void) {
186
+ return this.eventEmitter.addListener(PTREvents.ON_DATA_MANAGER_START, callback);
187
+ }
188
+
189
+ /** Subscribe to data-management-complete-all events. */
190
+ public onDataManagerCompleteAll(
191
+ callback: (event: PTRDataManagerCompleteAllEvent) => void
192
+ ) {
193
+ return this.eventEmitter.addListener(PTREvents.ON_DATA_MANAGER_COMPLETE_ALL, callback);
194
+ }
195
+
196
+ /** Subscribe to begin-processing events for a specific data type. */
197
+ public onDataManagerBeginProcessing(
198
+ callback: (event: PTRDataManagerBeginProcessingEvent) => void
199
+ ) {
200
+ return this.eventEmitter.addListener(
201
+ PTREvents.ON_DATA_MANAGER_BEGIN_PROCESSING,
202
+ callback
203
+ );
204
+ }
205
+
206
+ /** Subscribe to end-processing events for a specific data type. */
207
+ public onDataManagerEndProcessing(
208
+ callback: (event: PTRDataManagerEndProcessingEvent) => void
209
+ ) {
210
+ return this.eventEmitter.addListener(
211
+ PTREvents.ON_DATA_MANAGER_END_PROCESSING,
212
+ callback
213
+ );
214
+ }
215
+
216
+ /** Subscribe to site-ready events (all data available to display a site). */
217
+ public onDataManagerReady(callback: (event: PTRDataManagerReadyEvent) => void) {
218
+ return this.eventEmitter.addListener(PTREvents.ON_DATA_MANAGER_READY, callback);
219
+ }
220
+
175
221
  // ─── Map widget ────────────────────────────────────────────────────────────
176
222
 
177
223
  /**
@@ -208,6 +254,42 @@ export class PointrSdk {
208
254
  return PTRNativeLibrary.getGeofences(siteId);
209
255
  }
210
256
 
257
+ // ─── Data Manager ────────────────────────────────────────────────────────────
258
+
259
+ /**
260
+ * Start data management for a site if the data is not already present.
261
+ * @param siteId - Site identifier
262
+ * @param shouldRespectCachePolicy - When `true` (default), waits until the
263
+ * cache expires if data is already present. When `false`, ignores the internal
264
+ * cache and triggers a data update immediately.
265
+ * @param isExternalIdentifier - When `false` (default), `siteId` is the site's
266
+ * internal identifier. When `true`, it is the external identifier.
267
+ */
268
+ public loadDataForSite(
269
+ siteId: string,
270
+ shouldRespectCachePolicy: boolean = true,
271
+ isExternalIdentifier: boolean = false
272
+ ): Promise<void> {
273
+ return PTRNativeLibrary.loadDataForSite(
274
+ siteId,
275
+ shouldRespectCachePolicy,
276
+ isExternalIdentifier
277
+ );
278
+ }
279
+
280
+ /**
281
+ * Whether all data is ready for use for the given site.
282
+ * @param siteId - Site identifier
283
+ * @param isExternalIdentifier - When `false` (default), `siteId` is the site's
284
+ * internal identifier. When `true`, it is the external identifier.
285
+ */
286
+ public isSiteContentReady(
287
+ siteId: string,
288
+ isExternalIdentifier: boolean = false
289
+ ): Promise<boolean> {
290
+ return PTRNativeLibrary.isSiteContentReady(siteId, isExternalIdentifier);
291
+ }
292
+
211
293
  // ─── POIs ──────────────────────────────────────────────────────────────────
212
294
 
213
295
  /**
@@ -256,6 +338,85 @@ export class PointrSdk {
256
338
  return PTRNativeLibrary.getClientName();
257
339
  }
258
340
 
341
+ // ─── Site Manager ──────────────────────────────────────────────────────────────
342
+
343
+ /**
344
+ * Get a single site by its identifier.
345
+ * @param siteId - Site identifier
346
+ * @param isExternalIdentifier - When `false` (default), `siteId` is the
347
+ * internal identifier; when `true`, it is the external identifier.
348
+ */
349
+ public getSite(
350
+ siteId: string,
351
+ isExternalIdentifier: boolean = false
352
+ ): Promise<PTRSite | null> {
353
+ return PTRNativeLibrary.getSite(siteId, isExternalIdentifier);
354
+ }
355
+
356
+ /**
357
+ * Get all buildings for a site, resolving the site by internal or external id.
358
+ * @param siteId - Site identifier
359
+ * @param isExternalIdentifier - When `false` (default), `siteId` is the
360
+ * internal identifier; when `true`, it is the external identifier.
361
+ */
362
+ public getSiteBuildings(
363
+ siteId: string,
364
+ isExternalIdentifier: boolean = false
365
+ ): Promise<PTRBuilding[]> {
366
+ return PTRNativeLibrary.getSiteBuildings(siteId, isExternalIdentifier);
367
+ }
368
+
369
+ /**
370
+ * Get a single building within a site by its identifier.
371
+ * @param siteId - Site identifier
372
+ * @param buildingId - Building identifier
373
+ * @param isExternalIdentifier - When `false` (default), both ids are internal;
374
+ * when `true`, both are external.
375
+ */
376
+ public getBuilding(
377
+ siteId: string,
378
+ buildingId: string,
379
+ isExternalIdentifier: boolean = false
380
+ ): Promise<PTRBuilding | null> {
381
+ return PTRNativeLibrary.getBuilding(siteId, buildingId, isExternalIdentifier);
382
+ }
383
+
384
+ /**
385
+ * Get a level by its external identifier within a building.
386
+ * Resolves with the level or null if not found.
387
+ * Level ids are only unique within a building, so the building scopes the
388
+ * lookup. Both SDKs expose this by external identifier only.
389
+ * @param buildingExternalIdentifier - External identifier of the building
390
+ * @param levelExternalIdentifier - External identifier of the level
391
+ */
392
+ public getLevelByExternalIdentifier(
393
+ buildingExternalIdentifier: string,
394
+ levelExternalIdentifier: string
395
+ ): Promise<PTRLevel | null> {
396
+ return PTRNativeLibrary.getLevelByExternalIdentifier(
397
+ buildingExternalIdentifier,
398
+ levelExternalIdentifier
399
+ );
400
+ }
401
+
402
+ /**
403
+ * Get the map data URL for a site.
404
+ * @param siteId - Site identifier
405
+ * @param isExternalIdentifier - When `false` (default), `siteId` is the
406
+ * internal identifier; when `true`, it is the external identifier.
407
+ */
408
+ public getMapUrl(
409
+ siteId: string,
410
+ isExternalIdentifier: boolean = false
411
+ ): Promise<string | null> {
412
+ return PTRNativeLibrary.getMapUrl(siteId, isExternalIdentifier);
413
+ }
414
+
415
+ /** Get the URL for the map style JSON, or null if unavailable. */
416
+ public getStyleJsonUrl(): Promise<string | null> {
417
+ return PTRNativeLibrary.getStyleJsonUrl();
418
+ }
419
+
259
420
  // ─── Wayfinding ──────────────────────────────────────────────────────────────
260
421
 
261
422
  /**
@@ -1,7 +1,8 @@
1
1
  /**
2
- * Every string that crosses the JS <-> native boundary when an action is sent
3
- * to the map widget: action type discriminators, `action` / `sdkConfig` payload
4
- * keys and view-manager command names.
2
+ * Every string that crosses the JS <-> native boundary: action type
3
+ * discriminators, `action` / `sdkConfig` payload keys and view-manager command
4
+ * names on the JS -> native path, plus the payload keys of the events native
5
+ * emits back to JS.
5
6
  *
6
7
  * Nothing here may be hard-coded anywhere else — a key renamed on one side only
7
8
  * fails silently (the native side reads an empty string), so all three sides
@@ -125,3 +126,50 @@ export const PTRCommandNames = {
125
126
 
126
127
  export type PTRCommandName =
127
128
  (typeof PTRCommandNames)[keyof typeof PTRCommandNames];
129
+
130
+ /**
131
+ * Field names of the event payloads native emits to JS through the event
132
+ * emitter. Native writes them, JS reads them back through the typed interfaces
133
+ * in `src/types/events.ts` — the interface field names must match these values.
134
+ *
135
+ * Event *names* are not listed here: they live in {@link PTREvents} on the JS
136
+ * side, in `PTRNativeLibrary`'s companion object on Android and in
137
+ * `PTRNativeLibrary.EventNames` on iOS.
138
+ */
139
+ export const PTREventPayloadKeys = {
140
+ /** Site the event refers to, serialized by {@link PTRModelKeys} */
141
+ SITE: 'site',
142
+ /** Whether the data came from the server (online) or a local bundle */
143
+ IS_ONLINE_DATA: 'isOnlineData',
144
+ /** Whether the reported operation succeeded */
145
+ IS_SUCCESSFUL: 'isSuccessful',
146
+ /** Error messages collected during the operation */
147
+ ERRORS: 'errors',
148
+ /** Data type being processed */
149
+ DATA_TYPE: 'dataType',
150
+ /** Numeric value of `dataType` */
151
+ DATA_TYPE_VALUE: 'value',
152
+ /** Human-readable name of `dataType` */
153
+ DATA_TYPE_NAME: 'name',
154
+ } as const;
155
+
156
+ export type PTREventPayloadKey =
157
+ (typeof PTREventPayloadKeys)[keyof typeof PTREventPayloadKeys];
158
+
159
+ /**
160
+ * Field names shared by the site, building and level objects native serializes
161
+ * for JS — both as promise results and inside event payloads. They match the
162
+ * interfaces in `src/types/PTRSite.ts`.
163
+ */
164
+ export const PTRModelKeys = {
165
+ /** Internal identifier */
166
+ IDENTIFIER: 'identifier',
167
+ /** External (customer-facing) identifier */
168
+ EXTERNAL_IDENTIFIER: 'externalIdentifier',
169
+ /** Human-readable name */
170
+ NAME: 'name',
171
+ /** Zero-based level index */
172
+ INDEX: 'index',
173
+ } as const;
174
+
175
+ export type PTRModelKey = (typeof PTRModelKeys)[keyof typeof PTRModelKeys];
@@ -11,11 +11,15 @@ export {
11
11
  PTRActionParamKeys,
12
12
  PTRSdkConfigKeys,
13
13
  PTRCommandNames,
14
+ PTREventPayloadKeys,
15
+ PTRModelKeys,
14
16
  } from './bridgeKeys';
15
17
  export type {
16
18
  PTRActionParamKey,
17
19
  PTRSdkConfigKey,
18
20
  PTRCommandName,
21
+ PTREventPayloadKey,
22
+ PTRModelKey,
19
23
  } from './bridgeKeys';
20
24
 
21
25
  /**
@@ -86,6 +90,16 @@ export const PTREvents = {
86
90
  ON_WAYFINDING_EVENT: 'onWayfindingEvent',
87
91
  /** Fired when map widget finishes loading */
88
92
  ON_MAP_WIDGET_DID_END_LOADING: 'onMapWidgetDidEndLoading',
93
+ /** Fired when the data manager starts data management for a site */
94
+ ON_DATA_MANAGER_START: 'OnDataManagerStartDataManagementForSite',
95
+ /** Fired when the data manager completes all processing for a site */
96
+ ON_DATA_MANAGER_COMPLETE_ALL: 'OnDataManagerCompleteAllForSite',
97
+ /** Fired when the data manager begins processing a specific data type */
98
+ ON_DATA_MANAGER_BEGIN_PROCESSING: 'OnDataManagerBeginProcessingDataForSite',
99
+ /** Fired when the data manager ends processing a specific data type */
100
+ ON_DATA_MANAGER_END_PROCESSING: 'OnDataManagerEndProcessingDataForSite',
101
+ /** Fired when all data needed to display a site is available */
102
+ ON_DATA_MANAGER_READY: 'OnDataManagerReadyForSite',
89
103
  } as const;
90
104
 
91
105
  /**