spotny-sdk 1.0.16 → 1.0.18

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.
@@ -21,7 +21,6 @@ public typealias SpotnyEventCallback = @convention(block) (_ name: String, _ bod
21
21
 
22
22
  private struct CampaignData {
23
23
  let campaignId: Int? // nil when no active campaign
24
- let sessionId: String? // set after campaign fetch response
25
24
  let inQueue: Bool // campaign is queued — skip impressions
26
25
  let major: Int
27
26
  let minor: Int
@@ -54,6 +53,8 @@ public class SpotnyBeaconScanner: NSObject {
54
53
  // backendURL and kontaktAPIKey are fixed — not overridable by consumers.
55
54
  // backendURL is var to allow owner-only debug override via superDebugConfig in initialize().
56
55
  private var backendURL: String = "https://api.spotny.app"
56
+ /// When true, full API response bodies (success and error) are printed to the console.
57
+ private var debugMode: Bool = false
57
58
  private let apiBasePath: String = "/api/app/sdk"
58
59
  private let kontaktAPIKey: String = "mgrz08TOKNHafeY02cWIs9mxUHbynNQJ"
59
60
  private var maxDetectionDistance: Double = 8.0
@@ -96,6 +97,8 @@ public class SpotnyBeaconScanner: NSObject {
96
97
  private var campaignFetchInProgress: [String: Bool] = [:]
97
98
  private var campaignFetched: [String: Bool] = [:]
98
99
  private var campaignFetchCooldown: [String: Date] = [:] // backoff after failed fetch
100
+ // session_id returned by /proximity NEARBY response — sent with every /track heartbeat
101
+ private var beaconSessionIds: [String: String] = [:]
99
102
 
100
103
  // MARK: - Init
101
104
 
@@ -243,6 +246,10 @@ public class SpotnyBeaconScanner: NSObject {
243
246
  backendURL = url
244
247
  print("⚠️ [OWNER DEBUG] SpotnySDK: backendURL overridden → \(backendURL)")
245
248
  }
249
+ if let debug = config["debug"] as? Bool {
250
+ debugMode = debug
251
+ print("⚙️ SpotnySDK: debugMode = \(debug)")
252
+ }
246
253
  guard let token = config["token"] as? String, !token.isEmpty else {
247
254
  reject("MISSING_TOKEN", "initialize() requires a token", nil)
248
255
  return
@@ -583,14 +590,23 @@ public class SpotnyBeaconScanner: NSObject {
583
590
  completion(.failure(error)); return
584
591
  }
585
592
 
586
- URLSession.shared.dataTask(with: req) { data, response, error in
593
+ URLSession.shared.dataTask(with: req) { [weak self] data, response, error in
587
594
  DispatchQueue.main.async {
588
595
  if bg != .invalid { UIApplication.shared.endBackgroundTask(bg); bg = .invalid }
589
- if let error = error { completion(.failure(error)); return }
596
+ if let error = error {
597
+ if self?.debugMode == true {
598
+ print("🔍 SpotnySDK [DEBUG] \(endpoint) → error: \(error)")
599
+ }
600
+ completion(.failure(error)); return
601
+ }
590
602
  guard let http = response as? HTTPURLResponse, let data = data else {
591
603
  completion(.failure(NSError(domain: "SpotnySDK", code: -2,
592
604
  userInfo: [NSLocalizedDescriptionKey: "Bad response"]))); return
593
605
  }
606
+ if self?.debugMode == true {
607
+ let body = String(data: data, encoding: .utf8) ?? "(unreadable)"
608
+ print("🔍 SpotnySDK [DEBUG] \(endpoint) → \(http.statusCode): \(body)")
609
+ }
594
610
  completion(.success((http.statusCode, data)))
595
611
  }
596
612
  }.resume()
@@ -638,7 +654,7 @@ public class SpotnyBeaconScanner: NSObject {
638
654
  return
639
655
  }
640
656
  if let cid = campaign.campaignId { payload["campaign_id"] = cid }
641
- if let sid = campaign.sessionId { payload["session_id"] = sid }
657
+ if let sid = beaconSessionIds[key] { payload["session_id"] = sid }
642
658
  } else {
643
659
  if let cid = activeCampaigns[key]?.campaignId { payload["campaign_id"] = cid }
644
660
  }
@@ -646,8 +662,16 @@ public class SpotnyBeaconScanner: NSObject {
646
662
  post(endpoint: endpoint, payload: payload) { [weak self] result in
647
663
  guard let self = self else { return }
648
664
  switch result {
649
- case .success(let (status, _)):
665
+ case .success(let (status, data)):
650
666
  if 200...299 ~= status {
667
+ // Capture backend-generated session_id from the NEARBY proximity response
668
+ if eventType == "NEARBY",
669
+ let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
670
+ let dataObj = json["data"] as? [String: Any],
671
+ let sid = dataObj["session_id"] as? String, !sid.isEmpty {
672
+ self.beaconSessionIds[key] = sid
673
+ print("✅ SpotnySDK: NEARBY session_id stored — \(sid)")
674
+ }
651
675
  print("✅ SpotnySDK: \(eventType) — \(String(format: "%.2f", distance))m")
652
676
  self.logToFile("\(eventType) beacon \(key) @ \(String(format: "%.2f", distance))m")
653
677
  } else if status == 429 {
@@ -684,17 +708,15 @@ public class SpotnyBeaconScanner: NSObject {
684
708
  let dObj = json["data"] as? [String: Any] else { return }
685
709
 
686
710
  var campaignId: Int?
687
- var sessionId: String?
688
711
  var inQueue = false
689
712
 
690
713
  if let campaignObj = dObj["campaign"] as? [String: Any] {
691
714
  campaignId = campaignObj["id"] as? Int
692
- sessionId = campaignObj["session_id"] as? String
693
715
  inQueue = campaignObj["inQueue"] as? Bool ?? false
694
716
  }
695
717
 
696
718
  self.activeCampaigns[key] = CampaignData(
697
- campaignId: campaignId, sessionId: sessionId,
719
+ campaignId: campaignId,
698
720
  inQueue: inQueue, major: major, minor: minor
699
721
  )
700
722
  self.campaignFetched[key] = true
@@ -738,6 +760,7 @@ public class SpotnyBeaconScanner: NSObject {
738
760
  campaignFetchInProgress.removeValue(forKey: key)
739
761
  campaignFetched.removeValue(forKey: key)
740
762
  campaignFetchCooldown.removeValue(forKey: key)
763
+ beaconSessionIds.removeValue(forKey: key)
741
764
  print("🧹 SpotnySDK: Cleaned up \(key)")
742
765
  }
743
766
 
@@ -1 +1 @@
1
- {"version":3,"names":["NativeEventEmitter","NativeModules","NativeSpotnySdk","SpotnyEvents","ON_BEACONS_RANGED","ON_BEACON_REGION_EVENT","eventEmitter","SpotnySdk","startScanner","stopScanner","isScanning","initialize","config","requestNotificationPermissions","getDebugLogs","clearDebugLogs","setDebounceInterval","interval","clearDebounceCache","getDebounceStatus","addBeaconsRangedListener","callback","addListener","addBeaconRegionListener"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,kBAAkB,EAAEC,aAAa,QAAQ,cAAc;AAChE,OAAOC,eAAe,MAAM,sBAAmB;;AAE/C;AACA,OAAO,MAAMC,YAAY,GAAG;EAC1BC,iBAAiB,EAAE,iBAAiB;EACpCC,sBAAsB,EAAE;AAC1B,CAAU;;AAEV;;AAoDA;AACA,MAAMC,YAAY,GAAG,IAAIN,kBAAkB,CAACC,aAAa,CAACM,SAAS,CAAC;;AAEpE;;AAEA;AACA,OAAO,SAASC,YAAYA,CAAA,EAAoB;EAC9C,OAAON,eAAe,CAACM,YAAY,CAAC,CAAC;AACvC;;AAEA;AACA,OAAO,SAASC,WAAWA,CAAA,EAAoB;EAC7C,OAAOP,eAAe,CAACO,WAAW,CAAC,CAAC;AACtC;;AAEA;AACA,OAAO,SAASC,UAAUA,CAAA,EAAqB;EAC7C,OAAOR,eAAe,CAACQ,UAAU,CAAC,CAAC;AACrC;;AAEA;;AAEA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAACC,MAAuB,EAAmB;EACnE,OAAOV,eAAe,CAACS,UAAU,CAACC,MAAgB,CAAC;AACrD;;AAEA;;AAEA;AACA,OAAO,SAASC,8BAA8BA,CAAA,EAAoB;EAChE,OAAOX,eAAe,CAACW,8BAA8B,CAAC,CAAC;AACzD;;AAEA;;AAEA;AACA,OAAO,SAASC,YAAYA,CAAA,EAAoB;EAC9C,OAAOZ,eAAe,CAACY,YAAY,CAAC,CAAC;AACvC;;AAEA;AACA,OAAO,SAASC,cAAcA,CAAA,EAAoB;EAChD,OAAOb,eAAe,CAACa,cAAc,CAAC,CAAC;AACzC;;AAEA;;AAEA;AACA,OAAO,SAASC,mBAAmBA,CAACC,QAAgB,EAAmB;EACrE,OAAOf,eAAe,CAACc,mBAAmB,CAACC,QAAQ,CAAC;AACtD;;AAEA;AACA,OAAO,SAASC,kBAAkBA,CAAA,EAAoB;EACpD,OAAOhB,eAAe,CAACgB,kBAAkB,CAAC,CAAC;AAC7C;;AAEA;AACA,OAAO,SAASC,iBAAiBA,CAAA,EAAoB;EACnD,OAAOjB,eAAe,CAACiB,iBAAiB,CAAC,CAAC;AAC5C;;AAEA;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,wBAAwBA,CACtCC,QAA4C,EAC5C;EACA,OAAOf,YAAY,CAACgB,WAAW,CAC7BnB,YAAY,CAACC,iBAAiB,EAC9BiB,QACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASE,uBAAuBA,CACrCF,QAA4C,EAC5C;EACA,OAAOf,YAAY,CAACgB,WAAW,CAC7BnB,YAAY,CAACE,sBAAsB,EACnCgB,QACF,CAAC;AACH","ignoreList":[]}
1
+ {"version":3,"names":["NativeEventEmitter","NativeModules","NativeSpotnySdk","SpotnyEvents","ON_BEACONS_RANGED","ON_BEACON_REGION_EVENT","eventEmitter","SpotnySdk","startScanner","stopScanner","isScanning","initialize","config","requestNotificationPermissions","getDebugLogs","clearDebugLogs","setDebounceInterval","interval","clearDebounceCache","getDebounceStatus","addBeaconsRangedListener","callback","addListener","addBeaconRegionListener"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,kBAAkB,EAAEC,aAAa,QAAQ,cAAc;AAChE,OAAOC,eAAe,MAAM,sBAAmB;;AAE/C;AACA,OAAO,MAAMC,YAAY,GAAG;EAC1BC,iBAAiB,EAAE,iBAAiB;EACpCC,sBAAsB,EAAE;AAC1B,CAAU;;AAEV;;AA0DA;AACA,MAAMC,YAAY,GAAG,IAAIN,kBAAkB,CAACC,aAAa,CAACM,SAAS,CAAC;;AAEpE;;AAEA;AACA,OAAO,SAASC,YAAYA,CAAA,EAAoB;EAC9C,OAAON,eAAe,CAACM,YAAY,CAAC,CAAC;AACvC;;AAEA;AACA,OAAO,SAASC,WAAWA,CAAA,EAAoB;EAC7C,OAAOP,eAAe,CAACO,WAAW,CAAC,CAAC;AACtC;;AAEA;AACA,OAAO,SAASC,UAAUA,CAAA,EAAqB;EAC7C,OAAOR,eAAe,CAACQ,UAAU,CAAC,CAAC;AACrC;;AAEA;;AAEA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAACC,MAAuB,EAAmB;EACnE,OAAOV,eAAe,CAACS,UAAU,CAACC,MAAgB,CAAC;AACrD;;AAEA;;AAEA;AACA,OAAO,SAASC,8BAA8BA,CAAA,EAAoB;EAChE,OAAOX,eAAe,CAACW,8BAA8B,CAAC,CAAC;AACzD;;AAEA;;AAEA;AACA,OAAO,SAASC,YAAYA,CAAA,EAAoB;EAC9C,OAAOZ,eAAe,CAACY,YAAY,CAAC,CAAC;AACvC;;AAEA;AACA,OAAO,SAASC,cAAcA,CAAA,EAAoB;EAChD,OAAOb,eAAe,CAACa,cAAc,CAAC,CAAC;AACzC;;AAEA;;AAEA;AACA,OAAO,SAASC,mBAAmBA,CAACC,QAAgB,EAAmB;EACrE,OAAOf,eAAe,CAACc,mBAAmB,CAACC,QAAQ,CAAC;AACtD;;AAEA;AACA,OAAO,SAASC,kBAAkBA,CAAA,EAAoB;EACpD,OAAOhB,eAAe,CAACgB,kBAAkB,CAAC,CAAC;AAC7C;;AAEA;AACA,OAAO,SAASC,iBAAiBA,CAAA,EAAoB;EACnD,OAAOjB,eAAe,CAACiB,iBAAiB,CAAC,CAAC;AAC5C;;AAEA;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,wBAAwBA,CACtCC,QAA4C,EAC5C;EACA,OAAOf,YAAY,CAACgB,WAAW,CAC7BnB,YAAY,CAACC,iBAAiB,EAC9BiB,QACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASE,uBAAuBA,CACrCF,QAA4C,EAC5C;EACA,OAAOf,YAAY,CAACgB,WAAW,CAC7BnB,YAAY,CAACE,sBAAsB,EACnCgB,QACF,CAAC;AACH","ignoreList":[]}
@@ -45,6 +45,12 @@ export type SpotnySdkConfig = {
45
45
  * TX power variance (default: 0.5, tuned for Kontakt.io -12 dBm beacons).
46
46
  */
47
47
  distanceCorrectionFactor?: number;
48
+ /**
49
+ * When `true`, full API response bodies (status + JSON) are printed to the
50
+ * console for every SDK network call. Useful for diagnosing backend errors.
51
+ * Default: `false`.
52
+ */
53
+ debug?: boolean;
48
54
  /** @internal Owner-only: override the backend URL for local API debugging. */
49
55
  superDebugConfig?: {
50
56
  backendURL: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAIX,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACvC,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,CAAC;AAOF,6BAA6B;AAC7B,wBAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAE9C;AAED,mDAAmD;AACnD,wBAAgB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAE7C;AAED,uDAAuD;AACvD,wBAAgB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAE7C;AAID;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AAID,gEAAgE;AAChE,wBAAgB,8BAA8B,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhE;AAID,yCAAyC;AACzC,wBAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAE9C;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhD;AAID,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEpD;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEnD;AAID;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,4CAM7C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,4CAM7C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAIX,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACvC,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,CAAC;AAOF,6BAA6B;AAC7B,wBAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAE9C;AAED,mDAAmD;AACnD,wBAAgB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAE7C;AAED,uDAAuD;AACvD,wBAAgB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAE7C;AAID;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnE;AAID,gEAAgE;AAChE,wBAAgB,8BAA8B,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhE;AAID,yCAAyC;AACzC,wBAAgB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAE9C;AAED,2CAA2C;AAC3C,wBAAgB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhD;AAID,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEpD;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEnD;AAID;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,4CAM7C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,4CAM7C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spotny-sdk",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "Beacon Scanner",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
package/src/index.tsx CHANGED
@@ -55,6 +55,12 @@ export type SpotnySdkConfig = {
55
55
  * TX power variance (default: 0.5, tuned for Kontakt.io -12 dBm beacons).
56
56
  */
57
57
  distanceCorrectionFactor?: number;
58
+ /**
59
+ * When `true`, full API response bodies (status + JSON) are printed to the
60
+ * console for every SDK network call. Useful for diagnosing backend errors.
61
+ * Default: `false`.
62
+ */
63
+ debug?: boolean;
58
64
  /** @internal Owner-only: override the backend URL for local API debugging. */
59
65
  superDebugConfig?: { backendURL: string };
60
66
  };