@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.
@@ -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
+ }