@happyvertical/geo 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +194 -0
- package/dist/chunks/google-Ci3_ec7t.js +342 -0
- package/dist/chunks/google-Ci3_ec7t.js.map +1 -0
- package/dist/chunks/openstreetmap-DEPHzMUV.js +419 -0
- package/dist/chunks/openstreetmap-DEPHzMUV.js.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +290 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/google.d.ts +49 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/openstreetmap.d.ts +74 -0
- package/dist/providers/openstreetmap.d.ts.map +1 -0
- package/dist/shared/types.d.ts +233 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/utils.d.ts +52 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/static-maps.d.ts +214 -0
- package/dist/static-maps.d.ts.map +1 -0
- package/metadata.json +31 -0
- package/package.json +69 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types and interfaces for the Geo library
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Standardized location data structure
|
|
6
|
+
*/
|
|
7
|
+
export interface Location {
|
|
8
|
+
/**
|
|
9
|
+
* Unique identifier for the location (from provider)
|
|
10
|
+
*/
|
|
11
|
+
id: string;
|
|
12
|
+
/**
|
|
13
|
+
* Type of location
|
|
14
|
+
*/
|
|
15
|
+
type: 'country' | 'region' | 'city' | 'address' | 'point_of_interest' | 'unknown';
|
|
16
|
+
/**
|
|
17
|
+
* Full formatted name/address of the location
|
|
18
|
+
*/
|
|
19
|
+
name: string;
|
|
20
|
+
/**
|
|
21
|
+
* Latitude coordinate
|
|
22
|
+
*/
|
|
23
|
+
latitude: number;
|
|
24
|
+
/**
|
|
25
|
+
* Longitude coordinate
|
|
26
|
+
*/
|
|
27
|
+
longitude: number;
|
|
28
|
+
/**
|
|
29
|
+
* Address components (all optional)
|
|
30
|
+
*/
|
|
31
|
+
addressComponents: {
|
|
32
|
+
streetNumber?: string;
|
|
33
|
+
streetName?: string;
|
|
34
|
+
city?: string;
|
|
35
|
+
region?: string;
|
|
36
|
+
country?: string;
|
|
37
|
+
postalCode?: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* ISO 3166-1 alpha-2 country code
|
|
41
|
+
*/
|
|
42
|
+
countryCode: string;
|
|
43
|
+
/**
|
|
44
|
+
* Timezone identifier (optional, populated when provider returns it)
|
|
45
|
+
*/
|
|
46
|
+
timezone?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Raw response from the provider (for debugging or provider-specific data)
|
|
49
|
+
*/
|
|
50
|
+
raw: any;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Options for POI (point-of-interest) searches.
|
|
54
|
+
*
|
|
55
|
+
* `types` and `keyword` are both forwarded to the backing provider but each
|
|
56
|
+
* provider interprets them slightly differently:
|
|
57
|
+
*
|
|
58
|
+
* - **Google**: `types[0]` becomes the request's `type` filter (Places API
|
|
59
|
+
* accepts a single type per request; additional entries are ignored).
|
|
60
|
+
* `keyword` is a free-text match across name/type/address/reviews.
|
|
61
|
+
* - **OpenStreetMap (Overpass)**: `types` are matched against
|
|
62
|
+
* `amenity`, `shop`, and `tourism` tag values (e.g. `'cafe'`,
|
|
63
|
+
* `'supermarket'`, `'museum'`). When omitted, the provider searches across
|
|
64
|
+
* a broad set of POI-ish tag keys (`amenity`, `shop`, `tourism`,
|
|
65
|
+
* `leisure`, `office`, `historic`). `keyword` is appended as a substring
|
|
66
|
+
* filter on the `name` tag.
|
|
67
|
+
*/
|
|
68
|
+
export interface PoiSearchOptions {
|
|
69
|
+
/** Filter results to POIs matching these category values. See notes above. */
|
|
70
|
+
types?: string[];
|
|
71
|
+
/** Free-text keyword to narrow the search. */
|
|
72
|
+
keyword?: string;
|
|
73
|
+
/** Max results to return. Default 20. */
|
|
74
|
+
limit?: number;
|
|
75
|
+
/** Preferred language for place names (Google only). */
|
|
76
|
+
language?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Geo provider interface - all providers must implement lookup and
|
|
80
|
+
* reverseGeocode. `findPoisNear` is optional — providers implement it when
|
|
81
|
+
* they support POI discovery beyond reverse geocoding. Callers that need to
|
|
82
|
+
* know whether a given instance supports POI search should feature-detect:
|
|
83
|
+
*
|
|
84
|
+
* ```ts
|
|
85
|
+
* if (typeof adapter.findPoisNear === 'function') { ... }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export interface GeoProvider {
|
|
89
|
+
/**
|
|
90
|
+
* Look up locations based on a query string
|
|
91
|
+
* @param query - Search string (address, city, country, POI, etc.)
|
|
92
|
+
* @returns Promise resolving to array of matching Location objects
|
|
93
|
+
*/
|
|
94
|
+
lookup(query: string): Promise<Location[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Reverse geocode from coordinates to location
|
|
97
|
+
* @param latitude - Latitude coordinate
|
|
98
|
+
* @param longitude - Longitude coordinate
|
|
99
|
+
* @returns Promise resolving to array of matching Location objects
|
|
100
|
+
*/
|
|
101
|
+
reverseGeocode(latitude: number, longitude: number): Promise<Location[]>;
|
|
102
|
+
/**
|
|
103
|
+
* Find POIs (point-of-interest places — businesses, landmarks, amenities)
|
|
104
|
+
* within a radius of a coordinate. Returns locations with
|
|
105
|
+
* `type: 'point_of_interest'` whose coords lie inside the requested
|
|
106
|
+
* radius, sorted by the provider's relevance ranking.
|
|
107
|
+
*
|
|
108
|
+
* @param latitude - Center latitude
|
|
109
|
+
* @param longitude - Center longitude
|
|
110
|
+
* @param radiusMeters - Search radius in meters
|
|
111
|
+
* @param options - Optional filters
|
|
112
|
+
* @returns Promise resolving to array of matching Location objects
|
|
113
|
+
*/
|
|
114
|
+
findPoisNear?(latitude: number, longitude: number, radiusMeters: number, options?: PoiSearchOptions): Promise<Location[]>;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Geo adapter interface (structurally identical to GeoProvider)
|
|
118
|
+
*/
|
|
119
|
+
export interface GeoAdapter {
|
|
120
|
+
/**
|
|
121
|
+
* Look up locations based on a query string
|
|
122
|
+
* @param query - Search string (address, city, country, POI, etc.)
|
|
123
|
+
* @returns Promise resolving to array of matching Location objects
|
|
124
|
+
*/
|
|
125
|
+
lookup(query: string): Promise<Location[]>;
|
|
126
|
+
/**
|
|
127
|
+
* Reverse geocode from coordinates to location
|
|
128
|
+
* @param latitude - Latitude coordinate
|
|
129
|
+
* @param longitude - Longitude coordinate
|
|
130
|
+
* @returns Promise resolving to array of matching Location objects
|
|
131
|
+
*/
|
|
132
|
+
reverseGeocode(latitude: number, longitude: number): Promise<Location[]>;
|
|
133
|
+
/**
|
|
134
|
+
* Find POIs near a coordinate. Optional — see `GeoProvider.findPoisNear`.
|
|
135
|
+
*/
|
|
136
|
+
findPoisNear?(latitude: number, longitude: number, radiusMeters: number, options?: PoiSearchOptions): Promise<Location[]>;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Base configuration options for all providers
|
|
140
|
+
*/
|
|
141
|
+
export interface BaseGeoOptions {
|
|
142
|
+
/**
|
|
143
|
+
* Request timeout in milliseconds
|
|
144
|
+
*/
|
|
145
|
+
timeout?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Maximum number of results to return
|
|
148
|
+
*/
|
|
149
|
+
maxResults?: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Google Maps provider options
|
|
153
|
+
*/
|
|
154
|
+
export interface GoogleMapsOptions extends BaseGeoOptions {
|
|
155
|
+
provider: 'google';
|
|
156
|
+
/**
|
|
157
|
+
* Google Maps API key
|
|
158
|
+
*/
|
|
159
|
+
apiKey: string;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* OpenStreetMap provider options
|
|
163
|
+
*/
|
|
164
|
+
export interface OpenStreetMapOptions extends BaseGeoOptions {
|
|
165
|
+
provider: 'openstreetmap';
|
|
166
|
+
/**
|
|
167
|
+
* Custom User-Agent for OSM requests (optional, defaults to package name)
|
|
168
|
+
*/
|
|
169
|
+
userAgent?: string;
|
|
170
|
+
/**
|
|
171
|
+
* Rate limit delay in milliseconds (default: 1000ms for 1 req/sec)
|
|
172
|
+
*/
|
|
173
|
+
rateLimitDelay?: number;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Union type for all provider options
|
|
177
|
+
*/
|
|
178
|
+
export type GeoAdapterOptions = GoogleMapsOptions | OpenStreetMapOptions;
|
|
179
|
+
/**
|
|
180
|
+
* Base error class for geo operations.
|
|
181
|
+
* All geo-specific errors extend this class and include a machine-readable `code`
|
|
182
|
+
* and the `provider` name that produced the error.
|
|
183
|
+
*/
|
|
184
|
+
export declare class GeoError extends Error {
|
|
185
|
+
code: string;
|
|
186
|
+
provider?: string | undefined;
|
|
187
|
+
/**
|
|
188
|
+
* @param message - Human-readable error description
|
|
189
|
+
* @param code - Machine-readable error code (e.g. 'RATE_LIMIT', 'AUTH_ERROR')
|
|
190
|
+
* @param provider - Provider that raised the error ('google' | 'openstreetmap')
|
|
191
|
+
*/
|
|
192
|
+
constructor(message: string, code: string, provider?: string | undefined);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Thrown when the provider's rate limit has been exceeded.
|
|
196
|
+
*/
|
|
197
|
+
export declare class RateLimitError extends GeoError {
|
|
198
|
+
/**
|
|
199
|
+
* @param provider - Provider that raised the error
|
|
200
|
+
* @param retryAfter - Seconds to wait before retrying (if known)
|
|
201
|
+
*/
|
|
202
|
+
constructor(provider?: string, retryAfter?: number);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Thrown when the geocoding query is empty or malformed.
|
|
206
|
+
*/
|
|
207
|
+
export declare class InvalidQueryError extends GeoError {
|
|
208
|
+
/**
|
|
209
|
+
* @param query - The invalid query string
|
|
210
|
+
* @param provider - Provider that raised the error
|
|
211
|
+
*/
|
|
212
|
+
constructor(query: string, provider?: string);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Thrown when the provider rejects the API key or credentials.
|
|
216
|
+
*/
|
|
217
|
+
export declare class AuthenticationError extends GeoError {
|
|
218
|
+
/**
|
|
219
|
+
* @param provider - Provider that raised the error
|
|
220
|
+
*/
|
|
221
|
+
constructor(provider?: string);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Thrown when a geocoding query returns zero results.
|
|
225
|
+
*/
|
|
226
|
+
export declare class NoResultsError extends GeoError {
|
|
227
|
+
/**
|
|
228
|
+
* @param query - The query that produced no results
|
|
229
|
+
* @param provider - Provider that raised the error
|
|
230
|
+
*/
|
|
231
|
+
constructor(query: string, provider?: string);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Location } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Map Google Maps place types to standardized location types.
|
|
4
|
+
* Checks types in priority order: address, city, region, country, point_of_interest.
|
|
5
|
+
*
|
|
6
|
+
* @param types - Array of Google Maps place type strings (e.g. 'street_address', 'locality')
|
|
7
|
+
* @returns The standardized location type
|
|
8
|
+
*/
|
|
9
|
+
export declare function mapGooglePlaceType(types: string[]): Location['type'];
|
|
10
|
+
/**
|
|
11
|
+
* Map OpenStreetMap place types to standardized location types.
|
|
12
|
+
* Uses both the Nominatim `type` and `addresstype` fields for classification.
|
|
13
|
+
*
|
|
14
|
+
* @param type - Nominatim result type (e.g. 'house', 'city', 'state')
|
|
15
|
+
* @param addressType - Nominatim addresstype field (optional secondary classifier)
|
|
16
|
+
* @returns The standardized location type
|
|
17
|
+
*/
|
|
18
|
+
export declare function mapOSMPlaceType(type: string, addressType?: string): Location['type'];
|
|
19
|
+
/**
|
|
20
|
+
* Normalize a country code to uppercase ISO 3166-1 format.
|
|
21
|
+
* Returns 'XX' for undefined, empty, or unrecognized inputs.
|
|
22
|
+
*
|
|
23
|
+
* @param code - Country code string (alpha-2 or alpha-3)
|
|
24
|
+
* @returns Uppercase country code, or 'XX' if unknown
|
|
25
|
+
*/
|
|
26
|
+
export declare function normalizeCountryCode(code: string | undefined): string;
|
|
27
|
+
/**
|
|
28
|
+
* Validate that a latitude value is within the valid range (-90 to 90).
|
|
29
|
+
*
|
|
30
|
+
* @param lat - Latitude value to validate
|
|
31
|
+
* @returns `true` if the value is a number between -90 and 90 inclusive
|
|
32
|
+
*/
|
|
33
|
+
export declare function isValidLatitude(lat: number): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Validate that a longitude value is within the valid range (-180 to 180).
|
|
36
|
+
*
|
|
37
|
+
* @param lng - Longitude value to validate
|
|
38
|
+
* @returns `true` if the value is a number between -180 and 180 inclusive
|
|
39
|
+
*/
|
|
40
|
+
export declare function isValidLongitude(lng: number): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Validate that both latitude and longitude are within their valid ranges.
|
|
43
|
+
*
|
|
44
|
+
* @param latitude - Latitude value (-90 to 90)
|
|
45
|
+
* @param longitude - Longitude value (-180 to 180)
|
|
46
|
+
* @returns Object with `valid: true` if both are valid, or `valid: false` with an `error` message
|
|
47
|
+
*/
|
|
48
|
+
export declare function validateCoordinates(latitude: number, longitude: number): {
|
|
49
|
+
valid: boolean;
|
|
50
|
+
error?: string;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAwBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GACnB,QAAQ,CAAC,MAAM,CAAC,CA+ClB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAcrE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBpC"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Map Generation
|
|
3
|
+
*
|
|
4
|
+
* Generates static map URLs and fetches map images for location-based content.
|
|
5
|
+
* Supports Mapbox and Google Maps providers.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { getStaticMapUrl, fetchStaticMap } from '@happyvertical/geo';
|
|
10
|
+
*
|
|
11
|
+
* // Get URL for embedding
|
|
12
|
+
* const url = getStaticMapUrl(53.5461, -113.4938, {
|
|
13
|
+
* provider: 'mapbox',
|
|
14
|
+
* zoom: 14,
|
|
15
|
+
* width: 1200,
|
|
16
|
+
* height: 630
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Fetch the actual image
|
|
20
|
+
* const buffer = await fetchStaticMap(53.5461, -113.4938, {
|
|
21
|
+
* provider: 'mapbox'
|
|
22
|
+
* });
|
|
23
|
+
* await writeFile('map.png', buffer);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Static map provider
|
|
28
|
+
*/
|
|
29
|
+
export type StaticMapProvider = 'mapbox' | 'google';
|
|
30
|
+
/**
|
|
31
|
+
* Mapbox map styles
|
|
32
|
+
* @see https://docs.mapbox.com/api/maps/styles/
|
|
33
|
+
*/
|
|
34
|
+
export type MapboxStyle = 'streets-v12' | 'outdoors-v12' | 'light-v11' | 'dark-v11' | 'satellite-v9' | 'satellite-streets-v12';
|
|
35
|
+
/**
|
|
36
|
+
* Google Maps map types
|
|
37
|
+
* @see https://developers.google.com/maps/documentation/maps-static/start
|
|
38
|
+
*/
|
|
39
|
+
export type GoogleMapType = 'roadmap' | 'satellite' | 'terrain' | 'hybrid';
|
|
40
|
+
/**
|
|
41
|
+
* Marker definition for the map
|
|
42
|
+
*/
|
|
43
|
+
export interface StaticMapMarker {
|
|
44
|
+
/** Latitude */
|
|
45
|
+
latitude: number;
|
|
46
|
+
/** Longitude */
|
|
47
|
+
longitude: number;
|
|
48
|
+
/** Marker color (hex or named color) */
|
|
49
|
+
color?: string;
|
|
50
|
+
/** Marker label (single character for Google, any for Mapbox) */
|
|
51
|
+
label?: string;
|
|
52
|
+
/** Marker size ('small' | 'medium' | 'large') */
|
|
53
|
+
size?: 'small' | 'medium' | 'large';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Options for static map generation
|
|
57
|
+
*/
|
|
58
|
+
export interface StaticMapOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Map provider
|
|
61
|
+
* @default 'mapbox'
|
|
62
|
+
*/
|
|
63
|
+
provider?: StaticMapProvider;
|
|
64
|
+
/**
|
|
65
|
+
* Image width in pixels
|
|
66
|
+
* @default 1200
|
|
67
|
+
*/
|
|
68
|
+
width?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Image height in pixels
|
|
71
|
+
* @default 630
|
|
72
|
+
*/
|
|
73
|
+
height?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Zoom level (1-20)
|
|
76
|
+
* @default 14
|
|
77
|
+
*/
|
|
78
|
+
zoom?: number;
|
|
79
|
+
/**
|
|
80
|
+
* Marker color (hex without # or named color)
|
|
81
|
+
* @default 'e74c3c' (red)
|
|
82
|
+
*/
|
|
83
|
+
markerColor?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Show a marker at the center point
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
showMarker?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Mapbox access token (required for Mapbox provider)
|
|
91
|
+
* Falls back to MAPBOX_ACCESS_TOKEN env var
|
|
92
|
+
*/
|
|
93
|
+
mapboxToken?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Google Maps API key (required for Google provider)
|
|
96
|
+
* Falls back to GOOGLE_MAPS_API_KEY env var
|
|
97
|
+
*/
|
|
98
|
+
googleApiKey?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Mapbox style
|
|
101
|
+
* @default 'streets-v12'
|
|
102
|
+
*/
|
|
103
|
+
mapboxStyle?: MapboxStyle;
|
|
104
|
+
/**
|
|
105
|
+
* Google map type
|
|
106
|
+
* @default 'roadmap'
|
|
107
|
+
*/
|
|
108
|
+
googleMapType?: GoogleMapType;
|
|
109
|
+
/**
|
|
110
|
+
* Pixel density (1 or 2 for retina)
|
|
111
|
+
* @default 1
|
|
112
|
+
*/
|
|
113
|
+
scale?: 1 | 2;
|
|
114
|
+
/**
|
|
115
|
+
* Additional markers to display
|
|
116
|
+
*/
|
|
117
|
+
markers?: StaticMapMarker[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Result from fetching a static map
|
|
121
|
+
*/
|
|
122
|
+
export interface StaticMapResult {
|
|
123
|
+
/** PNG image buffer */
|
|
124
|
+
buffer: Buffer;
|
|
125
|
+
/** Image width */
|
|
126
|
+
width: number;
|
|
127
|
+
/** Image height */
|
|
128
|
+
height: number;
|
|
129
|
+
/** MIME type */
|
|
130
|
+
mimeType: 'image/png';
|
|
131
|
+
/** The URL that was fetched */
|
|
132
|
+
url: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generate a static map URL
|
|
136
|
+
*
|
|
137
|
+
* Returns a URL that can be used directly in <img> tags or fetched for processing.
|
|
138
|
+
*
|
|
139
|
+
* @param latitude - Center latitude
|
|
140
|
+
* @param longitude - Center longitude
|
|
141
|
+
* @param options - Map options
|
|
142
|
+
* @returns URL string for the static map
|
|
143
|
+
*
|
|
144
|
+
* @example Mapbox (default)
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const url = getStaticMapUrl(53.5461, -113.4938, {
|
|
147
|
+
* provider: 'mapbox',
|
|
148
|
+
* zoom: 14,
|
|
149
|
+
* mapboxStyle: 'streets-v12'
|
|
150
|
+
* });
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @example Google Maps
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const url = getStaticMapUrl(53.5461, -113.4938, {
|
|
156
|
+
* provider: 'google',
|
|
157
|
+
* zoom: 14,
|
|
158
|
+
* googleMapType: 'roadmap'
|
|
159
|
+
* });
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @example With custom markers
|
|
163
|
+
* ```typescript
|
|
164
|
+
* const url = getStaticMapUrl(53.5461, -113.4938, {
|
|
165
|
+
* showMarker: false, // Hide center marker
|
|
166
|
+
* markers: [
|
|
167
|
+
* { latitude: 53.5461, longitude: -113.4938, color: 'blue', label: 'A' },
|
|
168
|
+
* { latitude: 53.5500, longitude: -113.4900, color: 'green', label: 'B' }
|
|
169
|
+
* ]
|
|
170
|
+
* });
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export declare function getStaticMapUrl(latitude: number, longitude: number, options?: StaticMapOptions): string;
|
|
174
|
+
/**
|
|
175
|
+
* Fetch a static map image
|
|
176
|
+
*
|
|
177
|
+
* Downloads the map image and returns it as a Buffer.
|
|
178
|
+
*
|
|
179
|
+
* @param latitude - Center latitude
|
|
180
|
+
* @param longitude - Center longitude
|
|
181
|
+
* @param options - Map options
|
|
182
|
+
* @returns Promise resolving to the map image result
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```typescript
|
|
186
|
+
* const result = await fetchStaticMap(53.5461, -113.4938, {
|
|
187
|
+
* provider: 'mapbox',
|
|
188
|
+
* width: 1200,
|
|
189
|
+
* height: 630
|
|
190
|
+
* });
|
|
191
|
+
*
|
|
192
|
+
* await fs.writeFile('map.png', result.buffer);
|
|
193
|
+
* console.log(`Fetched ${result.width}x${result.height} map`);
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export declare function fetchStaticMap(latitude: number, longitude: number, options?: StaticMapOptions): Promise<StaticMapResult>;
|
|
197
|
+
/**
|
|
198
|
+
* Generate OG-sized static map URL (1200x630)
|
|
199
|
+
*
|
|
200
|
+
* Convenience function for generating Open Graph / social media sized maps.
|
|
201
|
+
*
|
|
202
|
+
* @param latitude - Center latitude
|
|
203
|
+
* @param longitude - Center longitude
|
|
204
|
+
* @param options - Map options (width/height ignored, set to 1200x630)
|
|
205
|
+
* @returns URL string for the static map
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* const url = getOGMapUrl(53.5461, -113.4938);
|
|
210
|
+
* // Returns 1200x630 map URL
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
export declare function getOGMapUrl(latitude: number, longitude: number, options?: Omit<StaticMapOptions, 'width' | 'height'>): string;
|
|
214
|
+
//# sourceMappingURL=static-maps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-maps.d.ts","sourceRoot":"","sources":["../src/static-maps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAMH;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,aAAa,GACb,cAAc,GACd,WAAW,GACX,UAAU,GACV,cAAc,GACd,uBAAuB,CAAC;AAE5B;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE3E;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,eAAe;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAE7B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB;IAChB,QAAQ,EAAE,WAAW,CAAC;IACtB,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb;AAmHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAUR;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAwB1B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,QAAQ,CAAM,GACvD,MAAM,CAMR"}
|
package/metadata.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/geo",
|
|
3
|
+
"path": "packages/geo",
|
|
4
|
+
"position": {
|
|
5
|
+
"index": 12,
|
|
6
|
+
"count": 30
|
|
7
|
+
},
|
|
8
|
+
"description": "Standardized geographical information interface supporting Google Maps and OpenStreetMap",
|
|
9
|
+
"provides": [
|
|
10
|
+
"Standardized geographical information interface supporting Google Maps and OpenStreetMap"
|
|
11
|
+
],
|
|
12
|
+
"implements": [],
|
|
13
|
+
"requires": {
|
|
14
|
+
"workspace": [
|
|
15
|
+
"@happyvertical/cache",
|
|
16
|
+
"@happyvertical/utils"
|
|
17
|
+
],
|
|
18
|
+
"externalHappyVertical": [],
|
|
19
|
+
"external": [
|
|
20
|
+
"@googlemaps/google-maps-services-js"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"dependents": [],
|
|
24
|
+
"stability": {
|
|
25
|
+
"level": "stable",
|
|
26
|
+
"reason": "Primary package surface is described as implemented and production-oriented."
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"geo"
|
|
30
|
+
]
|
|
31
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/geo",
|
|
3
|
+
"version": "0.74.8",
|
|
4
|
+
"description": "Standardized geographical information interface supporting Google Maps and OpenStreetMap",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"have-geo-context": "./dist/cli/claude-context.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"AGENT.md",
|
|
22
|
+
"metadata.json"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"registry": "https://registry.npmjs.org",
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/happyvertical/sdk.git",
|
|
31
|
+
"directory": "packages/geo"
|
|
32
|
+
},
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/happyvertical/sdk/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/happyvertical/sdk/tree/main/packages/geo#readme",
|
|
37
|
+
"keywords": [
|
|
38
|
+
"geocoding",
|
|
39
|
+
"maps",
|
|
40
|
+
"location",
|
|
41
|
+
"google-maps",
|
|
42
|
+
"openstreetmap",
|
|
43
|
+
"nominatim"
|
|
44
|
+
],
|
|
45
|
+
"author": "willgriffin@gmail.com",
|
|
46
|
+
"license": "ISC",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@googlemaps/google-maps-services-js": "^3.4.2",
|
|
49
|
+
"@happyvertical/cache": "0.74.8",
|
|
50
|
+
"@happyvertical/utils": "0.74.8"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "25.0.10",
|
|
54
|
+
"typescript": "^5.9.3",
|
|
55
|
+
"vite": "7.3.2",
|
|
56
|
+
"vite-plugin-dts": "4.5.4",
|
|
57
|
+
"vitest": "^4.1.5"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"test": "npx vitest run",
|
|
61
|
+
"test:watch": "npx vitest",
|
|
62
|
+
"build": "vite build",
|
|
63
|
+
"build:watch": "vite build --watch",
|
|
64
|
+
"docs": "typedoc --plugin typedoc-plugin-markdown --out docs --entryPoints ./src/index.ts --tsconfig ./tsconfig.json --excludePrivate --excludeInternal --hideGenerator --fileExtension .md --readme none --categorizeByGroup false --includeVersion false --hidePageHeader --hidePageTitle false --outputFileStrategy modules",
|
|
65
|
+
"docs:watch": "typedoc --plugin typedoc-plugin-markdown --out docs --entryPoints ./src/index.ts --tsconfig ./tsconfig.json --excludePrivate --excludeInternal --hideGenerator --fileExtension .md --readme none --categorizeByGroup false --includeVersion false --hidePageHeader --hidePageTitle false --outputFileStrategy modules --watch",
|
|
66
|
+
"clean": "rm -rf dist docs *.tsbuildinfo",
|
|
67
|
+
"dev": "npm run build:watch & npm run test:watch"
|
|
68
|
+
}
|
|
69
|
+
}
|