@doorstepai/dropoff-sdk 2.0.7 → 2.0.9

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 (39) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/doorstepai/dropoffsdk/DoorstepAIModule.kt +168 -7
  3. package/ios/DoorstepAI.mm +25 -1
  4. package/ios/DoorstepAI.swift +147 -3
  5. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/DoorstepDropoffSDK +0 -0
  6. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Info.plist +0 -0
  7. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.abi.json +5436 -1479
  8. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +93 -9
  9. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  10. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios.swiftinterface +93 -9
  11. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/DoorstepDropoffSDK.framework/_CodeSignature/CodeResources +11 -11
  12. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/DWARF/DoorstepDropoffSDK +0 -0
  13. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/DoorstepDropoffSDK.yml +2560 -2106
  14. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/DoorstepDropoffSDK +0 -0
  15. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Info.plist +0 -0
  16. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +5436 -1479
  17. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +93 -9
  18. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  19. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +93 -9
  20. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +5436 -1479
  21. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +93 -9
  22. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  23. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/Modules/DoorstepDropoffSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +93 -9
  24. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/DoorstepDropoffSDK.framework/_CodeSignature/CodeResources +21 -21
  25. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/DWARF/DoorstepDropoffSDK +0 -0
  26. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/DoorstepDropoffSDK.yml +2560 -2106
  27. package/ios/DoorstepDropoffSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/DoorstepDropoffSDK.framework.dSYM/Contents/Resources/Relocations/x86_64/DoorstepDropoffSDK.yml +2551 -2096
  28. package/lib/module/DoorstepAI.js +107 -12
  29. package/lib/module/DoorstepAI.js.map +1 -1
  30. package/lib/module/index.js.map +1 -1
  31. package/lib/typescript/src/DoorstepAI.d.ts +75 -2
  32. package/lib/typescript/src/DoorstepAI.d.ts.map +1 -1
  33. package/lib/typescript/src/RootDoorstepAI.d.ts +1 -1
  34. package/lib/typescript/src/RootDoorstepAI.d.ts.map +1 -1
  35. package/lib/typescript/src/index.d.ts +1 -1
  36. package/lib/typescript/src/index.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/DoorstepAI.tsx +199 -18
  39. package/src/index.tsx +4 -0
@@ -1,6 +1,14 @@
1
- import { NativeModules, Platform } from 'react-native';
1
+ import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
2
+ import type { EmitterSubscription } from 'react-native';
2
3
  const { DoorstepAI } = NativeModules;
3
4
 
5
+ // Bridges the native geofence-session event stream (iOS RCTEventEmitter /
6
+ // Android DeviceEventManagerModule) to JS. See `addGeofenceSessionListener`.
7
+ const GEOFENCE_SESSION_EVENT = 'DoorstepGeofenceSessionEvent';
8
+ const doorstepEventEmitter = DoorstepAI
9
+ ? new NativeEventEmitter(DoorstepAI)
10
+ : undefined;
11
+
4
12
  type AddressType = {
5
13
  streetNumber: string;
6
14
  route: string;
@@ -15,6 +23,45 @@ type LatLngObject = {
15
23
  lng: number;
16
24
  };
17
25
 
26
+ /**
27
+ * A single stop the SDK should geofence in `startRouteGeofencing`. On geofence
28
+ * ENTER the SDK auto-starts a delivery session for `deliveryId`; on EXIT it stops
29
+ * it (only if `markDropoff` was called for that id — otherwise the per-session
30
+ * timeout backstop applies).
31
+ */
32
+ type DeliveryStop = {
33
+ deliveryId: string;
34
+ address: string;
35
+ latitude: number;
36
+ longitude: number;
37
+ /** Fence radius in meters. Falls back to `RouteGeofenceOptions.defaultRadiusMeters` (250 m). */
38
+ radiusMeters?: number;
39
+ customerId?: string;
40
+ driverId?: string;
41
+ };
42
+
43
+ /** Route-wide options for `startRouteGeofencing`. */
44
+ type RouteGeofenceOptions = {
45
+ /** Radius (m) for stops that don't set their own `radiusMeters`. Default 250. */
46
+ defaultRadiusMeters?: number;
47
+ /** Per-session safety timeout (s) forwarded to the auto-started delivery. */
48
+ timeoutSeconds?: number;
49
+ /** Auto-stop countdown (s) applied when `stopDelivery` is called for a stop. */
50
+ autoStopAfterDropoffSeconds?: number;
51
+ /** Android only. Host owns the foreground service; SDK won't promote its own. Ignored on iOS. */
52
+ manualForeground?: boolean;
53
+ };
54
+
55
+ type GeofenceSessionEventType = 'STARTED' | 'STOPPED';
56
+
57
+ /** Emitted whenever route geofencing auto-starts or auto-stops a session. */
58
+ type GeofenceSessionEvent = {
59
+ deliveryId: string;
60
+ type: GeofenceSessionEventType;
61
+ /** Short trigger tag, e.g. "geofence", "distance", "route_cleared". */
62
+ reason: string;
63
+ };
64
+
18
65
  /**
19
66
  * Per-delivery options shared across both platforms. Fields not supported on a
20
67
  * given platform are silently ignored.
@@ -39,6 +86,16 @@ type StartDeliveryOptions = {
39
86
  * Ignored on iOS.
40
87
  */
41
88
  manualForeground?: boolean;
89
+ /**
90
+ * Optional customer identifier associated with this delivery. Forwarded to
91
+ * the native SDK on both platforms.
92
+ */
93
+ customerId?: string;
94
+ /**
95
+ * Optional driver identifier associated with this delivery. Forwarded to the
96
+ * native SDK on both platforms.
97
+ */
98
+ driverId?: string;
42
99
  };
43
100
 
44
101
  /**
@@ -128,6 +185,8 @@ class DoorstepAIModule {
128
185
  const timeout =
129
186
  timeoutSeconds ?? options?.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
130
187
  const autoStop = options?.autoStopAfterDropoffSeconds ?? null;
188
+ const customerId = options?.customerId ?? null;
189
+ const driverId = options?.driverId ?? null;
131
190
  const result =
132
191
  Platform.OS === 'android'
133
192
  ? await DoorstepAI.startDeliveryByPlaceID(
@@ -135,13 +194,17 @@ class DoorstepAIModule {
135
194
  deliveryId,
136
195
  timeout,
137
196
  autoStop,
138
- options?.manualForeground ?? false
197
+ options?.manualForeground ?? false,
198
+ customerId,
199
+ driverId
139
200
  )
140
201
  : await DoorstepAI.startDeliveryByPlaceID(
141
202
  placeID,
142
203
  deliveryId,
143
204
  timeout,
144
- autoStop
205
+ autoStop,
206
+ customerId,
207
+ driverId
145
208
  );
146
209
  console.log(
147
210
  'DOORSTEPAI - Delivery started successfully by Place ID:',
@@ -168,20 +231,27 @@ class DoorstepAIModule {
168
231
  try {
169
232
  const timeout =
170
233
  timeoutSeconds ?? options?.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
171
- // Android's deprecated startDeliveryByPlusCode does not accept the new
172
- // options, so we forward only the supported parameters there.
234
+ const customerId = options?.customerId ?? null;
235
+ const driverId = options?.driverId ?? null;
236
+ // Android's deprecated startDeliveryByPlusCode does not accept
237
+ // autoStopAfterDropoffSeconds, so we forward only the supported
238
+ // parameters there.
173
239
  const result =
174
240
  Platform.OS === 'ios'
175
241
  ? await DoorstepAI.startDeliveryByPlusCode(
176
242
  plusCode,
177
243
  deliveryId,
178
244
  timeout,
179
- options?.autoStopAfterDropoffSeconds ?? null
245
+ options?.autoStopAfterDropoffSeconds ?? null,
246
+ customerId,
247
+ driverId
180
248
  )
181
249
  : await DoorstepAI.startDeliveryByPlusCode(
182
250
  plusCode,
183
251
  deliveryId,
184
- timeout
252
+ timeout,
253
+ customerId,
254
+ driverId
185
255
  );
186
256
  console.log(
187
257
  'DOORSTEPAI - Delivery started successfully by Plus Code:',
@@ -209,6 +279,8 @@ class DoorstepAIModule {
209
279
  const timeout =
210
280
  timeoutSeconds ?? options?.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
211
281
  const autoStop = options?.autoStopAfterDropoffSeconds ?? null;
282
+ const customerId = options?.customerId ?? null;
283
+ const driverId = options?.driverId ?? null;
212
284
  const result =
213
285
  Platform.OS === 'android'
214
286
  ? await DoorstepAI.startDeliveryByAddress(
@@ -217,14 +289,18 @@ class DoorstepAIModule {
217
289
  coordinates ?? null,
218
290
  timeout,
219
291
  autoStop,
220
- options?.manualForeground ?? false
292
+ options?.manualForeground ?? false,
293
+ customerId,
294
+ driverId
221
295
  )
222
296
  : await DoorstepAI.startDeliveryByAddress(
223
297
  address,
224
298
  deliveryId,
225
299
  coordinates ?? null,
226
300
  timeout,
227
- autoStop
301
+ autoStop,
302
+ customerId,
303
+ driverId
228
304
  );
229
305
  console.log(
230
306
  'DOORSTEPAI - Delivery started successfully by Address:',
@@ -249,6 +325,8 @@ class DoorstepAIModule {
249
325
  const timeout =
250
326
  timeoutSeconds ?? options?.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
251
327
  const autoStop = options?.autoStopAfterDropoffSeconds ?? null;
328
+ const customerId = options?.customerId ?? null;
329
+ const driverId = options?.driverId ?? null;
252
330
  const result =
253
331
  Platform.OS === 'android'
254
332
  ? await DoorstepAI.startDeliveryByAddressString(
@@ -257,14 +335,18 @@ class DoorstepAIModule {
257
335
  coordinates ?? null,
258
336
  timeout,
259
337
  autoStop,
260
- options?.manualForeground ?? false
338
+ options?.manualForeground ?? false,
339
+ customerId,
340
+ driverId
261
341
  )
262
342
  : await DoorstepAI.startDeliveryByAddressString(
263
343
  address,
264
344
  deliveryId,
265
345
  coordinates ?? null,
266
346
  timeout,
267
- autoStop
347
+ autoStop,
348
+ customerId,
349
+ driverId
268
350
  );
269
351
  console.log(
270
352
  'DOORSTEPAI - Delivery started successfully by Address String:',
@@ -293,8 +375,11 @@ class DoorstepAIModule {
293
375
  try {
294
376
  const timeout =
295
377
  timeoutSeconds ?? options?.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
296
- // Android's deprecated startDeliveryByLatLng does not accept the new
297
- // options, so we forward only the supported parameters there.
378
+ const customerId = options?.customerId ?? null;
379
+ const driverId = options?.driverId ?? null;
380
+ // Android's deprecated startDeliveryByLatLng does not accept
381
+ // autoStopAfterDropoffSeconds, so we forward only the supported
382
+ // parameters there.
298
383
  const result =
299
384
  Platform.OS === 'ios'
300
385
  ? await DoorstepAI.startDeliveryByLatLng(
@@ -303,14 +388,18 @@ class DoorstepAIModule {
303
388
  subUnit,
304
389
  deliveryId,
305
390
  timeout,
306
- options?.autoStopAfterDropoffSeconds ?? null
391
+ options?.autoStopAfterDropoffSeconds ?? null,
392
+ customerId,
393
+ driverId
307
394
  )
308
395
  : await DoorstepAI.startDeliveryByLatLng(
309
396
  latitude,
310
397
  longitude,
311
398
  subUnit,
312
399
  deliveryId,
313
- timeout
400
+ timeout,
401
+ customerId,
402
+ driverId
314
403
  );
315
404
  console.log(
316
405
  'DOORSTEPAI - Delivery started successfully by LatLng:',
@@ -355,9 +444,21 @@ class DoorstepAIModule {
355
444
  }
356
445
  }
357
446
 
358
- static async newEvent(eventName: string, deliveryId: string) {
447
+ /**
448
+ * Record a custom event on a delivery. `timestamp` is optional epoch SECONDS —
449
+ * when provided the event is recorded at that time instead of "now".
450
+ */
451
+ static async newEvent(
452
+ eventName: string,
453
+ deliveryId: string,
454
+ timestamp?: number
455
+ ) {
359
456
  try {
360
- const result = await DoorstepAI.newEvent(eventName, deliveryId);
457
+ const result = await DoorstepAI.newEvent(
458
+ eventName,
459
+ deliveryId,
460
+ timestamp ?? null
461
+ );
361
462
  console.log('DOORSTEPAI - Event sent successfully:', result);
362
463
  return result;
363
464
  } catch (error: any) {
@@ -371,6 +472,77 @@ class DoorstepAIModule {
371
472
  }
372
473
  }
373
474
 
475
+ // ---- Route geofencing (in-SDK) ----
476
+
477
+ /**
478
+ * Begin in-SDK route geofencing. The SDK fences each stop and auto-starts a
479
+ * delivery session on geofence ENTER / stops it on EXIT (EXIT is gated on
480
+ * `markDropoff`). Requires location permission; background operation needs
481
+ * "Allow all the time" (Android) / Always authorization (iOS). Subscribe to
482
+ * start/stop events via `addGeofenceSessionListener`.
483
+ */
484
+ static async startRouteGeofencing(
485
+ stops: DeliveryStop[],
486
+ options?: RouteGeofenceOptions
487
+ ): Promise<void> {
488
+ try {
489
+ await DoorstepAI.startRouteGeofencing(stops, options ?? null);
490
+ console.log(
491
+ 'DOORSTEPAI - Route geofencing started for',
492
+ stops.length,
493
+ 'stop(s)'
494
+ );
495
+ } catch (error: any) {
496
+ console.error('DOORSTEPAI - Failed to start route geofencing:', error);
497
+ throw error;
498
+ }
499
+ }
500
+
501
+ /** Stop route geofencing and clear all monitored stops. */
502
+ static async stopRouteGeofencing(): Promise<void> {
503
+ try {
504
+ await DoorstepAI.stopRouteGeofencing();
505
+ } catch (error: any) {
506
+ console.error('DOORSTEPAI - Failed to stop route geofencing:', error);
507
+ throw error;
508
+ }
509
+ }
510
+
511
+ /**
512
+ * Re-arm route geofencing after a process relaunch if a route was active.
513
+ * Safe no-op when no route is persisted.
514
+ */
515
+ static async resumeRouteGeofencingIfNeeded(): Promise<void> {
516
+ try {
517
+ await DoorstepAI.resumeRouteGeofencingIfNeeded();
518
+ } catch (error: any) {
519
+ console.error('DOORSTEPAI - Failed to resume route geofencing:', error);
520
+ throw error;
521
+ }
522
+ }
523
+
524
+ /** The stops currently registered for route geofencing (empty if none). */
525
+ static async getMonitoredStops(): Promise<DeliveryStop[]> {
526
+ try {
527
+ const stops = await DoorstepAI.getMonitoredStops();
528
+ return (stops as DeliveryStop[]) ?? [];
529
+ } catch (error: any) {
530
+ console.error('DOORSTEPAI - Failed to get monitored stops:', error);
531
+ return [];
532
+ }
533
+ }
534
+
535
+ /**
536
+ * Subscribe to geofence-session events (auto start/stop of a delivery on
537
+ * geofence transitions). Returns a subscription — call `.remove()` to
538
+ * unsubscribe. Returns `undefined` if the native module is unavailable.
539
+ */
540
+ static addGeofenceSessionListener(
541
+ listener: (event: GeofenceSessionEvent) => void
542
+ ): EmitterSubscription | undefined {
543
+ return doorstepEventEmitter?.addListener(GEOFENCE_SESSION_EVENT, listener);
544
+ }
545
+
374
546
  // ---- Dev-mode helpers (Android exposes a richer surface than iOS) ----
375
547
 
376
548
  static async enableDevMode(apiKey: string): Promise<boolean> {
@@ -395,4 +567,13 @@ class DoorstepAIModule {
395
567
  }
396
568
 
397
569
  export { DoorstepAIModule as DoorstepAI };
398
- export type { AddressType, LatLngObject, StartDeliveryOptions, SDKLogLevel };
570
+ export type {
571
+ AddressType,
572
+ LatLngObject,
573
+ StartDeliveryOptions,
574
+ SDKLogLevel,
575
+ DeliveryStop,
576
+ RouteGeofenceOptions,
577
+ GeofenceSessionEvent,
578
+ GeofenceSessionEventType,
579
+ };
package/src/index.tsx CHANGED
@@ -5,6 +5,10 @@ export type {
5
5
  LatLngObject,
6
6
  StartDeliveryOptions,
7
7
  SDKLogLevel,
8
+ DeliveryStop,
9
+ RouteGeofenceOptions,
10
+ GeofenceSessionEvent,
11
+ GeofenceSessionEventType,
8
12
  } from './DoorstepAI';
9
13
 
10
14
  export { DoorstepAI, RootDoorstepAI };