@callforge/tracking-client 0.7.0 → 0.7.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/README.md CHANGED
@@ -43,7 +43,13 @@ const client = CallForge.init({
43
43
  const { session, location } = client.getSessionAsync();
44
44
 
45
45
  // Location is delivered independently (often faster than phone number assignment)
46
- console.log(await location); // { city: "Woodstock", state: "Georgia", stateCode: "GA" } or null
46
+ console.log(await location);
47
+ // {
48
+ // city: "Woodstock",
49
+ // state: "Georgia",
50
+ // stateCode: "GA",
51
+ // zipOptions: ["30188", "30189", "30066", ...] // may be []
52
+ // } or null
47
53
 
48
54
  // Phone session data (deterministic token + phone number)
49
55
  console.log(await session); // { sessionToken, leaseId, phoneNumber }
@@ -160,7 +166,16 @@ Get location data only. Returns cached data if valid, otherwise fetches from the
160
166
 
161
167
  ```typescript
162
168
  const location = await client.getLocation();
163
- // { city, state, stateCode } or null
169
+ // { city, state, stateCode, zipOptions } or null
170
+ ```
171
+
172
+ ```typescript
173
+ interface TrackingLocation {
174
+ city: string;
175
+ state: string;
176
+ stateCode: string;
177
+ zipOptions?: string[]; // ordered by proximity, may be []
178
+ }
164
179
  ```
165
180
 
166
181
  ### `client.getSessionAsync()`
@@ -172,6 +187,7 @@ const { session, location } = client.getSessionAsync();
172
187
 
173
188
  location.then((loc) => {
174
189
  // show city/state ASAP
190
+ // optionally render loc?.zipOptions in a ZIP picker
175
191
  });
176
192
 
177
193
  session.then((sess) => {
@@ -204,7 +220,7 @@ Subscribe to location ready event. Callback is called once location data is avai
204
220
 
205
221
  ```typescript
206
222
  client.onLocationReady((location) => {
207
- // location is { city, state, stateCode } or null
223
+ // location is { city, state, stateCode, zipOptions } or null
208
224
  });
209
225
  ```
210
226
 
package/dist/index.d.mts CHANGED
@@ -21,6 +21,8 @@ interface TrackingLocation {
21
21
  state: string;
22
22
  /** State abbreviation (e.g., "GA") */
23
23
  stateCode: string;
24
+ /** Suggested ZIPs ordered by proximity (may be empty) */
25
+ zipOptions?: string[];
24
26
  }
25
27
  type TrackingLocationSource = 'google_criteria' | 'cloudflare_geo';
26
28
  /**
@@ -70,6 +72,7 @@ interface ApiLocationResponse {
70
72
  stateCode: string;
71
73
  source: TrackingLocationSource;
72
74
  } | null;
75
+ zipOptions?: string[];
73
76
  expiresAt: number;
74
77
  }
75
78
  interface CallIntentResponse {
@@ -174,6 +177,8 @@ declare class CallForge {
174
177
  private fetchLocationFromApi;
175
178
  private saveToCache;
176
179
  private saveLocationToCache;
180
+ private toTrackingLocation;
181
+ private normalizeZipOptions;
177
182
  private formatSession;
178
183
  private formatApiResponse;
179
184
  private syncParamsToCallForgeIfPossible;
package/dist/index.d.ts CHANGED
@@ -21,6 +21,8 @@ interface TrackingLocation {
21
21
  state: string;
22
22
  /** State abbreviation (e.g., "GA") */
23
23
  stateCode: string;
24
+ /** Suggested ZIPs ordered by proximity (may be empty) */
25
+ zipOptions?: string[];
24
26
  }
25
27
  type TrackingLocationSource = 'google_criteria' | 'cloudflare_geo';
26
28
  /**
@@ -70,6 +72,7 @@ interface ApiLocationResponse {
70
72
  stateCode: string;
71
73
  source: TrackingLocationSource;
72
74
  } | null;
75
+ zipOptions?: string[];
73
76
  expiresAt: number;
74
77
  }
75
78
  interface CallIntentResponse {
@@ -174,6 +177,8 @@ declare class CallForge {
174
177
  private fetchLocationFromApi;
175
178
  private saveToCache;
176
179
  private saveLocationToCache;
180
+ private toTrackingLocation;
181
+ private normalizeZipOptions;
177
182
  private formatSession;
178
183
  private formatApiResponse;
179
184
  private syncParamsToCallForgeIfPossible;
package/dist/index.js CHANGED
@@ -424,18 +424,14 @@ var CallForge = class _CallForge {
424
424
  return this.formatApiResponse(data);
425
425
  }
426
426
  async fetchLocation() {
427
- var _a;
427
+ var _a, _b;
428
428
  const locationId = this.getLocationId();
429
429
  if (typeof window !== "undefined" && window.__cfTrackingLocation) {
430
430
  try {
431
431
  const data2 = await window.__cfTrackingLocation;
432
432
  const dataWithExtras = data2;
433
433
  const effectiveLocId = (_a = dataWithExtras.locId) != null ? _a : locationId;
434
- const location2 = data2.location ? {
435
- city: data2.location.city,
436
- state: data2.location.state,
437
- stateCode: data2.location.stateCode
438
- } : null;
434
+ const location2 = this.toTrackingLocation(data2.location, dataWithExtras.zipOptions);
439
435
  this.saveLocationToCache(effectiveLocId, location2, data2.expiresAt);
440
436
  return location2;
441
437
  } catch (e) {
@@ -443,14 +439,10 @@ var CallForge = class _CallForge {
443
439
  }
444
440
  const cached = this.locationCache.get(locationId);
445
441
  if (cached) {
446
- return cached.location;
442
+ return this.toTrackingLocation(cached.location, (_b = cached.location) == null ? void 0 : _b.zipOptions);
447
443
  }
448
444
  const data = await this.fetchLocationFromApi(locationId);
449
- const location = data.location ? {
450
- city: data.location.city,
451
- state: data.location.state,
452
- stateCode: data.location.stateCode
453
- } : null;
445
+ const location = this.toTrackingLocation(data.location, data.zipOptions);
454
446
  this.saveLocationToCache(locationId, location, data.expiresAt);
455
447
  return location;
456
448
  }
@@ -525,6 +517,27 @@ var CallForge = class _CallForge {
525
517
  tokenVersion: "v1"
526
518
  });
527
519
  }
520
+ toTrackingLocation(location, zipOptions) {
521
+ if (!location) {
522
+ return null;
523
+ }
524
+ return {
525
+ city: location.city,
526
+ state: location.state,
527
+ stateCode: location.stateCode,
528
+ zipOptions: this.normalizeZipOptions(zipOptions)
529
+ };
530
+ }
531
+ normalizeZipOptions(value) {
532
+ if (!Array.isArray(value)) {
533
+ return [];
534
+ }
535
+ return Array.from(
536
+ new Set(
537
+ value.filter((zip) => typeof zip === "string" && /^\d{5}$/.test(zip))
538
+ )
539
+ );
540
+ }
528
541
  formatSession(cached) {
529
542
  return {
530
543
  sessionToken: cached.sessionToken,
@@ -609,12 +622,12 @@ var lkey='cf_location_v1_'+site;
609
622
  try{
610
623
  var cl=JSON.parse(localStorage.getItem(lkey));
611
624
  if(cl&&cl.expiresAt>Date.now()+30000){
612
- if(!loc||(loc&&cl.locId===loc)){window.__cfTrackingLocation=Promise.resolve(cl)}
625
+ if(!loc||(loc&&cl.locId===loc)){if(cl.location&&!Array.isArray(cl.location.zipOptions))cl.location.zipOptions=[];window.__cfTrackingLocation=Promise.resolve(cl)}
613
626
  }}catch(e){}
614
627
  if(!window.__cfTrackingLocation){
615
628
  var lurl='${endpoint}/v1/tracking/location';
616
629
  if(loc)lurl+='?loc_physical_ms='+encodeURIComponent(loc);
617
- window.__cfTrackingLocation=fetch(lurl,{credentials:'omit'}).then(function(r){if(!r.ok)throw new Error('tracking preload location failed');return r.json()}).then(function(d){d.locId=loc;try{localStorage.setItem(lkey,JSON.stringify({locId:loc,location:d.location?{city:d.location.city,state:d.location.state,stateCode:d.location.stateCode}:null,expiresAt:d.expiresAt,tokenVersion:'v1'}))}catch(e){}return d});
630
+ window.__cfTrackingLocation=fetch(lurl,{credentials:'omit'}).then(function(r){if(!r.ok)throw new Error('tracking preload location failed');return r.json()}).then(function(d){var z=Array.isArray(d.zipOptions)?d.zipOptions.filter(function(x){return /^\\d{5}$/.test(x)}):[];d.locId=loc;d.zipOptions=z;try{localStorage.setItem(lkey,JSON.stringify({locId:loc,location:d.location?{city:d.location.city,state:d.location.state,stateCode:d.location.stateCode,zipOptions:z}:null,expiresAt:d.expiresAt,tokenVersion:'v1'}))}catch(e){}return d});
618
631
  }
619
632
  var token=null;
620
633
  try{
package/dist/index.mjs CHANGED
@@ -400,18 +400,14 @@ var CallForge = class _CallForge {
400
400
  return this.formatApiResponse(data);
401
401
  }
402
402
  async fetchLocation() {
403
- var _a;
403
+ var _a, _b;
404
404
  const locationId = this.getLocationId();
405
405
  if (typeof window !== "undefined" && window.__cfTrackingLocation) {
406
406
  try {
407
407
  const data2 = await window.__cfTrackingLocation;
408
408
  const dataWithExtras = data2;
409
409
  const effectiveLocId = (_a = dataWithExtras.locId) != null ? _a : locationId;
410
- const location2 = data2.location ? {
411
- city: data2.location.city,
412
- state: data2.location.state,
413
- stateCode: data2.location.stateCode
414
- } : null;
410
+ const location2 = this.toTrackingLocation(data2.location, dataWithExtras.zipOptions);
415
411
  this.saveLocationToCache(effectiveLocId, location2, data2.expiresAt);
416
412
  return location2;
417
413
  } catch (e) {
@@ -419,14 +415,10 @@ var CallForge = class _CallForge {
419
415
  }
420
416
  const cached = this.locationCache.get(locationId);
421
417
  if (cached) {
422
- return cached.location;
418
+ return this.toTrackingLocation(cached.location, (_b = cached.location) == null ? void 0 : _b.zipOptions);
423
419
  }
424
420
  const data = await this.fetchLocationFromApi(locationId);
425
- const location = data.location ? {
426
- city: data.location.city,
427
- state: data.location.state,
428
- stateCode: data.location.stateCode
429
- } : null;
421
+ const location = this.toTrackingLocation(data.location, data.zipOptions);
430
422
  this.saveLocationToCache(locationId, location, data.expiresAt);
431
423
  return location;
432
424
  }
@@ -501,6 +493,27 @@ var CallForge = class _CallForge {
501
493
  tokenVersion: "v1"
502
494
  });
503
495
  }
496
+ toTrackingLocation(location, zipOptions) {
497
+ if (!location) {
498
+ return null;
499
+ }
500
+ return {
501
+ city: location.city,
502
+ state: location.state,
503
+ stateCode: location.stateCode,
504
+ zipOptions: this.normalizeZipOptions(zipOptions)
505
+ };
506
+ }
507
+ normalizeZipOptions(value) {
508
+ if (!Array.isArray(value)) {
509
+ return [];
510
+ }
511
+ return Array.from(
512
+ new Set(
513
+ value.filter((zip) => typeof zip === "string" && /^\d{5}$/.test(zip))
514
+ )
515
+ );
516
+ }
504
517
  formatSession(cached) {
505
518
  return {
506
519
  sessionToken: cached.sessionToken,
@@ -585,12 +598,12 @@ var lkey='cf_location_v1_'+site;
585
598
  try{
586
599
  var cl=JSON.parse(localStorage.getItem(lkey));
587
600
  if(cl&&cl.expiresAt>Date.now()+30000){
588
- if(!loc||(loc&&cl.locId===loc)){window.__cfTrackingLocation=Promise.resolve(cl)}
601
+ if(!loc||(loc&&cl.locId===loc)){if(cl.location&&!Array.isArray(cl.location.zipOptions))cl.location.zipOptions=[];window.__cfTrackingLocation=Promise.resolve(cl)}
589
602
  }}catch(e){}
590
603
  if(!window.__cfTrackingLocation){
591
604
  var lurl='${endpoint}/v1/tracking/location';
592
605
  if(loc)lurl+='?loc_physical_ms='+encodeURIComponent(loc);
593
- window.__cfTrackingLocation=fetch(lurl,{credentials:'omit'}).then(function(r){if(!r.ok)throw new Error('tracking preload location failed');return r.json()}).then(function(d){d.locId=loc;try{localStorage.setItem(lkey,JSON.stringify({locId:loc,location:d.location?{city:d.location.city,state:d.location.state,stateCode:d.location.stateCode}:null,expiresAt:d.expiresAt,tokenVersion:'v1'}))}catch(e){}return d});
606
+ window.__cfTrackingLocation=fetch(lurl,{credentials:'omit'}).then(function(r){if(!r.ok)throw new Error('tracking preload location failed');return r.json()}).then(function(d){var z=Array.isArray(d.zipOptions)?d.zipOptions.filter(function(x){return /^\\d{5}$/.test(x)}):[];d.locId=loc;d.zipOptions=z;try{localStorage.setItem(lkey,JSON.stringify({locId:loc,location:d.location?{city:d.location.city,state:d.location.state,stateCode:d.location.stateCode,zipOptions:z}:null,expiresAt:d.expiresAt,tokenVersion:'v1'}))}catch(e){}return d});
594
607
  }
595
608
  var token=null;
596
609
  try{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callforge/tracking-client",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -17,17 +17,17 @@
17
17
  "files": [
18
18
  "dist"
19
19
  ],
20
- "devDependencies": {
21
- "jsdom": "^27.4.0",
22
- "tsup": "^8.0.0",
23
- "typescript": "^5.3.0",
24
- "vitest": "^1.6.0",
25
- "@callforge/tsconfig": "0.0.0"
26
- },
27
20
  "scripts": {
28
21
  "build": "tsup src/index.ts --format esm,cjs --dts",
29
22
  "clean": "rm -rf dist",
30
23
  "test": "vitest run",
31
24
  "test:watch": "vitest"
25
+ },
26
+ "devDependencies": {
27
+ "@callforge/tsconfig": "workspace:*",
28
+ "jsdom": "^27.4.0",
29
+ "tsup": "^8.0.0",
30
+ "typescript": "^5.3.0",
31
+ "vitest": "^1.6.0"
32
32
  }
33
- }
33
+ }