bmlt-query-client 1.0.7 → 1.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.
- package/.claude/settings.local.json +10 -0
- package/PROJECT_SUMMARY.md +1 -1
- package/README.md +51 -7
- package/dist/app.d.ts +74 -10
- package/dist/app.js +251 -184
- package/dist/app.js.map +1 -1
- package/package.json +2 -2
package/PROJECT_SUMMARY.md
CHANGED
|
@@ -87,7 +87,7 @@ import { BmltClient, Weekday, VenueType } from 'bmlt-query-client';
|
|
|
87
87
|
|
|
88
88
|
// Initialize client with NYC demo server
|
|
89
89
|
const client = new BmltClient({
|
|
90
|
-
|
|
90
|
+
serverURL: 'https://latest.aws.bmlt.app/main_server',
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
// Search by address with automatic geocoding
|
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ The easiest way to use the BMLT Query Client in the browser is via ES modules:
|
|
|
38
38
|
|
|
39
39
|
// Initialize the client
|
|
40
40
|
const client = new BmltClient({
|
|
41
|
-
|
|
41
|
+
serverURL: 'https://latest.aws.bmlt.app/main_server', // NYC demo server
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
// Search for virtual meetings
|
|
@@ -72,7 +72,7 @@ npm install bmlt-query-client
|
|
|
72
72
|
import { BmltClient, VenueType, MeetingQueryBuilder } from 'bmlt-query-client';
|
|
73
73
|
|
|
74
74
|
const client = new BmltClient({
|
|
75
|
-
|
|
75
|
+
serverURL: 'https://your-bmlt-server.org/main_server',
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
// Search for meetings
|
|
@@ -183,6 +183,50 @@ const todaysVirtualMeetings = await quickSearch
|
|
|
183
183
|
.execute();
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
+
### Finding Duplicate Meetings
|
|
187
|
+
|
|
188
|
+
When querying meetings from multiple service bodies or servers, use `findDuplicateMeetings` to identify the same meeting appearing in more than one list:
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
import { findDuplicateMeetings } from 'bmlt-query-client';
|
|
192
|
+
|
|
193
|
+
const [listA, listB] = await Promise.all([
|
|
194
|
+
client.searchMeetings({ services: [1] }),
|
|
195
|
+
client.searchMeetings({ services: [2] }),
|
|
196
|
+
]);
|
|
197
|
+
|
|
198
|
+
const duplicates = findDuplicateMeetings([listA, listB]);
|
|
199
|
+
|
|
200
|
+
for (const group of duplicates) {
|
|
201
|
+
console.log(`Duplicate: ${group.key}`);
|
|
202
|
+
for (const { meeting, listIndex } of group.entries) {
|
|
203
|
+
console.log(` List ${listIndex}: id=${meeting.id_bigint}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
By default, meetings are compared on `weekday_tinyint`, `start_time`, `meeting_name`, and `location_text` (case-insensitive). You can customize the fields:
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
// Compare only on name and street address
|
|
212
|
+
const duplicates = findDuplicateMeetings([listA, listB], {
|
|
213
|
+
fields: ['meeting_name', 'location_street'],
|
|
214
|
+
normalize: true, // lowercase + trim (default)
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Counting Unique Groups
|
|
219
|
+
|
|
220
|
+
Use `countUniqueGroups` to get the total number of distinct groups in a meeting list. A group is identified by its service body plus meeting name (case-insensitive, trimmed), so multiple weekly occurrences of the same group count once:
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
import { countUniqueGroups } from 'bmlt-query-client';
|
|
224
|
+
|
|
225
|
+
const meetings = await client.searchMeetings();
|
|
226
|
+
const total = countUniqueGroups(meetings);
|
|
227
|
+
console.log(`Total unique groups: ${total}`);
|
|
228
|
+
```
|
|
229
|
+
|
|
186
230
|
## Error Handling
|
|
187
231
|
|
|
188
232
|
The client provides comprehensive error handling with specific error types:
|
|
@@ -253,9 +297,9 @@ console.log(client.getUserAgent()); // 'my-updated-app/2.0.0'
|
|
|
253
297
|
client.setTimeout(60000); // 60 seconds
|
|
254
298
|
console.log(client.getTimeout()); // 60000
|
|
255
299
|
|
|
256
|
-
// Update
|
|
257
|
-
client.
|
|
258
|
-
console.log(client.
|
|
300
|
+
// Update server URL
|
|
301
|
+
client.setServerURL('https://new-server.org/main_server');
|
|
302
|
+
console.log(client.getServerURL());
|
|
259
303
|
|
|
260
304
|
// Update default data format
|
|
261
305
|
client.setDefaultFormat(BmltDataFormat.JSONP);
|
|
@@ -266,7 +310,7 @@ console.log(client.getDefaultFormat());
|
|
|
266
310
|
|
|
267
311
|
```javascript
|
|
268
312
|
const client = new BmltClient({
|
|
269
|
-
|
|
313
|
+
serverURL: 'https://your-server.org/main_server', // Required
|
|
270
314
|
defaultFormat: BmltDataFormat.JSON, // Optional
|
|
271
315
|
timeout: 30000, // 30 seconds
|
|
272
316
|
userAgent: 'my-app/1.0.0', // Custom user agent
|
|
@@ -283,7 +327,7 @@ const client = new BmltClient({
|
|
|
283
327
|
|
|
284
328
|
```javascript
|
|
285
329
|
const client = new BmltClient({
|
|
286
|
-
|
|
330
|
+
serverURL: 'https://your-server.org/main_server',
|
|
287
331
|
geocodingOptions: {
|
|
288
332
|
countryCode: 'us', // ISO country code bias
|
|
289
333
|
viewbox: [-74.2, 40.4, -73.7, 40.9], // Geographic bounding box [w,s,e,n]
|
package/dist/app.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare class BmltClient {
|
|
|
11
11
|
private timeout;
|
|
12
12
|
private userAgent;
|
|
13
13
|
private readonly geocodingService?;
|
|
14
|
-
private
|
|
14
|
+
private serverURL;
|
|
15
15
|
private defaultFormat;
|
|
16
16
|
constructor(options: BmltClientOptions);
|
|
17
17
|
/**
|
|
@@ -81,13 +81,13 @@ export declare class BmltClient {
|
|
|
81
81
|
*/
|
|
82
82
|
reverseGeocode(coordinates: Coordinates, options?: Partial<GeocodeOptions>): Promise<GeocodeResult>;
|
|
83
83
|
/**
|
|
84
|
-
* Get the
|
|
84
|
+
* Get the server URL
|
|
85
85
|
*/
|
|
86
|
-
|
|
86
|
+
getServerURL(): string;
|
|
87
87
|
/**
|
|
88
|
-
* Update the
|
|
88
|
+
* Update the server URL
|
|
89
89
|
*/
|
|
90
|
-
|
|
90
|
+
setServerURL(url: string): void;
|
|
91
91
|
/**
|
|
92
92
|
* Get the default data format
|
|
93
93
|
*/
|
|
@@ -126,8 +126,8 @@ export declare class BmltClient {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
export declare interface BmltClientOptions {
|
|
129
|
-
/**
|
|
130
|
-
|
|
129
|
+
/** Server URL */
|
|
130
|
+
serverURL: string;
|
|
131
131
|
/** Default data format */
|
|
132
132
|
defaultFormat?: BmltDataFormat;
|
|
133
133
|
/** HTTP request timeout in milliseconds */
|
|
@@ -284,6 +284,15 @@ export declare interface Coordinates {
|
|
|
284
284
|
longitude: number;
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Count unique groups across a list of meetings.
|
|
289
|
+
*
|
|
290
|
+
* A "group" is identified by the combination of service body and meeting name
|
|
291
|
+
* (case-insensitive, trimmed), so multiple weekly meetings of the same group
|
|
292
|
+
* count once.
|
|
293
|
+
*/
|
|
294
|
+
export declare function countUniqueGroups(meetings: Meeting[]): number;
|
|
295
|
+
|
|
287
296
|
export declare interface CoverageArea {
|
|
288
297
|
/** North boundary */
|
|
289
298
|
north_latitude: number;
|
|
@@ -295,6 +304,21 @@ export declare interface CoverageArea {
|
|
|
295
304
|
west_longitude: number;
|
|
296
305
|
}
|
|
297
306
|
|
|
307
|
+
/** A single meeting paired with the index of the list it came from */
|
|
308
|
+
export declare interface DuplicateMeetingEntry {
|
|
309
|
+
meeting: Meeting;
|
|
310
|
+
/** Index of the source list in the array passed to findDuplicateMeetings */
|
|
311
|
+
listIndex: number;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** A group of meetings from different lists that match on the comparison key */
|
|
315
|
+
export declare interface DuplicateMeetingGroup {
|
|
316
|
+
/** Composite key used for matching */
|
|
317
|
+
key: string;
|
|
318
|
+
/** All matching entries, one per occurrence across the lists */
|
|
319
|
+
entries: DuplicateMeetingEntry[];
|
|
320
|
+
}
|
|
321
|
+
|
|
298
322
|
/**
|
|
299
323
|
* Factory class for creating specific error types
|
|
300
324
|
*/
|
|
@@ -372,6 +396,37 @@ export declare interface FieldValuesParams extends BaseSearchParams {
|
|
|
372
396
|
all_formats?: boolean;
|
|
373
397
|
}
|
|
374
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Find meetings that appear in more than one of the provided lists.
|
|
401
|
+
*
|
|
402
|
+
* Comparison is done via a composite key built from the specified fields
|
|
403
|
+
* (default: weekday, start time, meeting name, location). Only groups that
|
|
404
|
+
* span at least two different lists are returned.
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* const duplicates = findDuplicateMeetings([listA, listB]);
|
|
408
|
+
* for (const group of duplicates) {
|
|
409
|
+
* console.log(`Duplicate: ${group.key}`);
|
|
410
|
+
* for (const { meeting, listIndex } of group.entries) {
|
|
411
|
+
* console.log(` List ${listIndex}: id=${meeting.id_bigint}`);
|
|
412
|
+
* }
|
|
413
|
+
* }
|
|
414
|
+
*/
|
|
415
|
+
export declare function findDuplicateMeetings(meetingLists: Meeting[][], options?: FindDuplicatesOptions): DuplicateMeetingGroup[];
|
|
416
|
+
|
|
417
|
+
export declare interface FindDuplicatesOptions {
|
|
418
|
+
/**
|
|
419
|
+
* Meeting fields used to build the composite comparison key.
|
|
420
|
+
* Defaults to weekday, start time, meeting name, and location.
|
|
421
|
+
*/
|
|
422
|
+
fields?: Array<keyof Meeting>;
|
|
423
|
+
/**
|
|
424
|
+
* Normalize string values before comparing (lowercase + trim).
|
|
425
|
+
* Defaults to true.
|
|
426
|
+
*/
|
|
427
|
+
normalize?: boolean;
|
|
428
|
+
}
|
|
429
|
+
|
|
375
430
|
export declare interface Format {
|
|
376
431
|
/** Format ID */
|
|
377
432
|
id: string;
|
|
@@ -640,6 +695,13 @@ export declare class MeetingQueryBuilder {
|
|
|
640
695
|
* Search for specific text
|
|
641
696
|
*/
|
|
642
697
|
searchText(text: string): this;
|
|
698
|
+
/**
|
|
699
|
+
* Search by address using server-side geocoding (StringSearchIsAnAddress=1).
|
|
700
|
+
* Note: typically broken on most BMLT servers because their Google API key uses
|
|
701
|
+
* HTTP referer restrictions rather than server IP allowlisting. Prefer
|
|
702
|
+
* BmltClient.searchMeetingsByAddress() which uses Nominatim client-side.
|
|
703
|
+
*/
|
|
704
|
+
searchAddress(address: string, radius?: number): this;
|
|
643
705
|
/**
|
|
644
706
|
* Meetings starting after specific time
|
|
645
707
|
*/
|
|
@@ -881,6 +943,8 @@ export declare interface SearchResultsParams extends BaseSearchParams {
|
|
|
881
943
|
SearchString?: string;
|
|
882
944
|
/** Search radius for geographic searches */
|
|
883
945
|
SearchStringRadius?: number;
|
|
946
|
+
/** Treat SearchString as an address and have the server geocode it. Note: typically broken on most servers because the Google API key uses HTTP referer restrictions rather than server IP allowlisting. Prefer searchMeetingsByAddress() which uses Nominatim client-side. */
|
|
947
|
+
StringSearchIsAnAddress?: boolean;
|
|
884
948
|
/** Meetings starting after hour (0-23) */
|
|
885
949
|
StartsAfterH?: number;
|
|
886
950
|
/** Meetings starting after minute (0-59) */
|
|
@@ -989,7 +1053,7 @@ export declare enum SortKey {
|
|
|
989
1053
|
}
|
|
990
1054
|
|
|
991
1055
|
export declare interface URLBuilderOptions {
|
|
992
|
-
|
|
1056
|
+
serverURL: string;
|
|
993
1057
|
format: BmltDataFormat;
|
|
994
1058
|
endpoint: BmltEndpoint;
|
|
995
1059
|
parameters?: Record<string, unknown>;
|
|
@@ -1011,9 +1075,9 @@ export declare function validateEndpointFormat(endpoint: BmltEndpoint, format: B
|
|
|
1011
1075
|
export declare function validateRadius(radius: number): void;
|
|
1012
1076
|
|
|
1013
1077
|
/**
|
|
1014
|
-
* Clean and validate a
|
|
1078
|
+
* Clean and validate a server URL
|
|
1015
1079
|
*/
|
|
1016
|
-
export declare function
|
|
1080
|
+
export declare function validateServerURL(url: string): string;
|
|
1017
1081
|
|
|
1018
1082
|
export declare enum VenueType {
|
|
1019
1083
|
IN_PERSON = 1,
|