bmlt-query-client 1.1.0 → 1.2.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.
package/AGENTS.md CHANGED
@@ -97,6 +97,20 @@ Key rules:
97
97
  4. Export any new public types from `src/types/index.ts` and any new public classes/functions from `src/index.ts`.
98
98
  5. Add a usage example in `examples/basic-usage.ts`.
99
99
  6. Add or extend a test in `test/basic.test.ts`.
100
+ 7. Update `CHANGELOG.md` under `[Unreleased]`.
101
+
102
+ ## Raw Query
103
+
104
+ `BmltClient.rawQuery<T>(queryString, format?)` sends a raw BMLT query string directly to the server. The first token is treated as the switcher value when it has no `=` sign:
105
+
106
+ - `'GetSearchResults&venue_types=2'` → `switcher=GetSearchResults&venue_types=2`
107
+ - `'switcher=GetSearchResults&venue_types=2'` → passed through unchanged
108
+
109
+ The internal HTTP fetch+parse logic lives in the private `fetchAndParse` method shared with `makeRequest`. Do not duplicate it.
110
+
111
+ ## Array Parameters
112
+
113
+ `meeting_key_value` in `SearchResultsParams` accepts `string | string[]`. The URL builder serialises arrays as repeated `key[]=value` entries (e.g. `meeting_key_value[]=USA&meeting_key_value[]=US`). This same pattern applies to all other array-typed parameters (`weekdays`, `venue_types`, `formats`, `services`, `root_server_ids`, `meeting_ids`).
100
114
 
101
115
  ## Geocoding
102
116
 
package/CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [1.2.0] - 2026-05-12
10
+
11
+ ### Added
12
+
13
+ - `BmltClient.rawQuery<T>(queryString, format?)` — execute a raw BMLT query string directly against the server. The switcher can be written as a bare endpoint name (`GetSearchResults&...`) or with the explicit `switcher=` key (`switcher=GetSearchResults&...`).
14
+ - `meeting_key_value` in `SearchResultsParams` now accepts `string | string[]`, enabling multi-value field searches (e.g. `meeting_key_value: ['USA', 'US']` serialises as `meeting_key_value[]=USA&meeting_key_value[]=US`).
15
+ - `MeetingQueryBuilder.fieldValue()` now accepts `string | string[]` to match multiple values for a field key.
16
+ - Raw query input section added to the browser demo (`docs/index.html`).
17
+
18
+ ## [1.1.0] - 2026-04-27
19
+
20
+ ### Added
21
+
22
+ - `BmltClient.searchMeetingsWithFormats()` — fetches meetings and the formats they reference in a single round-trip using `get_used_formats=true`. Avoids a separate `getFormats()` call on large servers.
23
+ - `MeetingQueryBuilder.executeWithFormats()` — equivalent fluent builder method that returns `MeetingsWithFormats`.
24
+ - `BmltClient.getServerURL()` and `BmltClient.setServerURL()` — read and update the server URL after construction.
25
+ - `findDuplicateMeetings(lists, options?)` utility — identifies the same meeting appearing across multiple result lists. Configurable comparison fields and normalization.
26
+ - `countUniqueGroups(meetings)` utility — counts distinct groups (service body + meeting name) in a meeting list.
27
+ - Additional language codes added to the `Language` enum.
28
+
29
+ ## [1.0.6] - 2026-03-26
30
+
31
+ ### Fixed
32
+
33
+ - Response type corrections in `responses.ts`.
34
+
35
+ ### Changed
36
+
37
+ - Dependency updates.
38
+
39
+ ## [1.0.0] - 2025-09-06
40
+
41
+ ### Added
42
+
43
+ - Initial release.
44
+ - `BmltClient` with full BMLT Semantic API coverage: `searchMeetings`, `getFormats`, `getServiceBodies`, `getChanges`, `getFieldKeys`, `getFieldValues`, `getNAWSDump`, `getServerInfo`, `getCoverageArea`.
45
+ - `MeetingQueryBuilder` — fluent, chainable query builder for meeting searches.
46
+ - `QuickSearch` — convenience helpers (`today()`, `virtual()`, `evening()`, `weekend()`, etc.).
47
+ - Built-in geocoding via OpenStreetMap Nominatim with rate limiting and retry.
48
+ - `BmltClient.searchMeetingsByAddress()` and `searchMeetingsByCoordinates()` for geographic searches.
49
+ - `BmltClient.geocodeAddress()` and `reverseGeocode()`.
50
+ - Configurable user agent, timeout, default format, and geocoding options.
51
+ - `BmltQueryError` / `BmltErrorType` for typed error handling.
52
+ - Zero external runtime dependencies — p-queue and p-retry are bundled via Vite.
53
+ - ES module only; native `fetch` API; TypeScript declarations included.
54
+
55
+ [Unreleased]: https://github.com/bmlt-enabled/bmlt-query-client/compare/v1.2.0...HEAD
56
+ [1.2.0]: https://github.com/bmlt-enabled/bmlt-query-client/compare/v1.1.0...v1.2.0
57
+ [1.1.0]: https://github.com/bmlt-enabled/bmlt-query-client/compare/v1.0.6...v1.1.0
58
+ [1.0.6]: https://github.com/bmlt-enabled/bmlt-query-client/compare/v1.0.0...v1.0.6
59
+ [1.0.0]: https://github.com/bmlt-enabled/bmlt-query-client/releases/tag/v1.0.0
package/README.md CHANGED
@@ -183,6 +183,44 @@ const todaysVirtualMeetings = await quickSearch
183
183
  .execute();
184
184
  ```
185
185
 
186
+ ### Raw Query
187
+
188
+ When you need to pass a BMLT query string exactly as-is — including parameters like `meeting_key_value[]` that match multiple values — use `rawQuery`:
189
+
190
+ ```javascript
191
+ // Bare endpoint shorthand (most common)
192
+ const meetings = await client.rawQuery(
193
+ 'GetSearchResults&venue_types=2&meeting_key=location_nation&meeting_key_value[]=USA&meeting_key_value[]=US'
194
+ );
195
+
196
+ // Explicit switcher= form also works
197
+ const meetings2 = await client.rawQuery('switcher=GetSearchResults&page_size=10');
198
+
199
+ // With get_used_formats — returns { meetings, formats }
200
+ import type { MeetingsWithFormats } from 'bmlt-query-client';
201
+
202
+ const result = await client.rawQuery<MeetingsWithFormats>(
203
+ 'GetSearchResults&get_used_formats=1&venue_types=2'
204
+ );
205
+ ```
206
+
207
+ Multi-value `meeting_key_value` is also available through the typed API:
208
+
209
+ ```javascript
210
+ // Typed params — array serialises as meeting_key_value[]=USA&meeting_key_value[]=US
211
+ const meetings = await client.searchMeetings({
212
+ venue_types: VenueType.IN_PERSON,
213
+ meeting_key: 'location_nation',
214
+ meeting_key_value: ['USA', 'US'],
215
+ });
216
+
217
+ // Or via query builder
218
+ const meetings2 = await new MeetingQueryBuilder(client)
219
+ .inPersonOnly()
220
+ .fieldValue('location_nation', ['USA', 'US'])
221
+ .execute();
222
+ ```
223
+
186
224
  ### Finding Duplicate Meetings
187
225
 
188
226
  When querying meetings from multiple service bodies or servers, use `findDuplicateMeetings` to identify the same meeting appearing in more than one list:
package/dist/app.d.ts CHANGED
@@ -14,10 +14,27 @@ export declare class BmltClient {
14
14
  private serverURL;
15
15
  private defaultFormat;
16
16
  constructor(options: BmltClientOptions);
17
+ /**
18
+ * Fetch a URL and parse the response according to format
19
+ */
20
+ private fetchAndParse;
17
21
  /**
18
22
  * Make a request to the BMLT API
19
23
  */
20
24
  private makeRequest;
25
+ /**
26
+ * Execute a raw BMLT query string against the server.
27
+ *
28
+ * Pass the query exactly as you'd append it to a BMLT URL. The switcher
29
+ * can be written with or without the key name:
30
+ *
31
+ * // bare endpoint name — most common shorthand
32
+ * client.rawQuery('GetSearchResults&venue_types=2&meeting_key=location_nation&meeting_key_value[]=USA&meeting_key_value[]=US')
33
+ *
34
+ * // explicit switcher= key also works
35
+ * client.rawQuery('switcher=GetSearchResults&venue_types=2')
36
+ */
37
+ rawQuery<T = unknown>(queryString: string, format?: BmltDataFormat): Promise<T>;
21
38
  /**
22
39
  * Search for meetings
23
40
  */
@@ -75,11 +92,11 @@ export declare class BmltClient {
75
92
  /**
76
93
  * Geocode an address using the built-in geocoding service
77
94
  */
78
- geocodeAddress(address: string, options?: Partial<GeocodeOptions>): Promise<GeocodeResult>;
95
+ geocodeAddress(address: string, options?: Partial<GeocodeOptions>): Promise< GeocodeResult>;
79
96
  /**
80
97
  * Reverse geocode coordinates to an address
81
98
  */
82
- reverseGeocode(coordinates: Coordinates, options?: Partial<GeocodeOptions>): Promise<GeocodeResult>;
99
+ reverseGeocode(coordinates: Coordinates, options?: Partial<GeocodeOptions>): Promise< GeocodeResult>;
83
100
  /**
84
101
  * Get the server URL
85
102
  */
@@ -729,9 +746,9 @@ export declare class MeetingQueryBuilder {
729
746
  */
730
747
  nearCoordinates(coordinates: Coordinates, radiusMiles?: number, radiusKm?: number): this;
731
748
  /**
732
- * Search for specific field value
749
+ * Search for specific field value; pass an array to match any of multiple values
733
750
  */
734
- fieldValue(fieldKey: string, value: string): this;
751
+ fieldValue(fieldKey: string, value: string | string[]): this;
735
752
  /**
736
753
  * Return only specific fields
737
754
  */
@@ -979,8 +996,8 @@ export declare interface SearchResultsParams extends BaseSearchParams {
979
996
  sort_results_by_distance?: boolean;
980
997
  /** Search for specific field value */
981
998
  meeting_key?: string;
982
- /** The value to search for */
983
- meeting_key_value?: string;
999
+ /** The value to search for; pass an array to match any of multiple values */
1000
+ meeting_key_value?: string | string[];
984
1001
  /** Return only specific fields (comma-separated) */
985
1002
  data_field_key?: string;
986
1003
  /** Sort results by specific fields (comma-separated) */