@happyvertical/smrt-places 0.51.32 → 0.51.33

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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=__smrt-register__.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__smrt-register__.d.ts","sourceRoot":"","sources":["../src/__smrt-register__.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import type { Asset } from '@happyvertical/smrt-assets';
2
+ import type { SmrtCollectionOptions } from '@happyvertical/smrt-core';
3
+ import { SmrtJunction } from '@happyvertical/smrt-core';
4
+ import { PlaceAsset } from '../models/PlaceAsset';
5
+ export interface PlaceAssetCollectionOptions extends SmrtCollectionOptions {
6
+ }
7
+ export declare class PlaceAssetCollection extends SmrtJunction<PlaceAsset> {
8
+ static readonly _itemClass: typeof PlaceAsset;
9
+ protected leftField: string;
10
+ protected rightField: string;
11
+ private placeCollectionPromise;
12
+ private getPlaceCollection;
13
+ getAssets(placeId: string, relationship?: string): Promise<Asset[]>;
14
+ addAsset(placeId: string, asset: Asset, relationship?: string, sortOrder?: number): Promise<void>;
15
+ removeAsset(placeId: string, assetId: string, relationship?: string): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=PlaceAssetCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaceAssetCollection.d.ts","sourceRoot":"","sources":["../../src/collections/PlaceAssetCollection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAMxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,YAAY,EAAQ,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,MAAM,WAAW,2BAA4B,SAAQ,qBAAqB;CAAG;AAE7E,qBAKa,oBAAqB,SAAQ,YAAY,CAAC,UAAU,CAAC;IAChE,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;IACxC,SAAS,CAAC,SAAS,SAAa;IAChC,SAAS,CAAC,UAAU,SAAa;IAEjC,OAAO,CAAC,sBAAsB,CAAyC;YAEzD,kBAAkB;IAS1B,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAQnE,QAAQ,CACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,YAAY,SAAe,EAC3B,SAAS,SAAI,GACZ,OAAO,CAAC,IAAI,CAAC;IAWV,WAAW,CACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;CASjB"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * PlaceCollection - Collection manager for Place objects
3
+ *
4
+ * Provides hierarchy traversal and organic place database growth via
5
+ * lookupOrCreate method that integrates with @happyvertical/geo.
6
+ */
7
+ import type { Asset } from '@happyvertical/smrt-assets';
8
+ import { SmrtCollection } from '@happyvertical/smrt-core';
9
+ import { Place } from '../models/Place';
10
+ import type { DiscoverNearbyOptions, LookupOrCreateOptions, ResolveTrackPlacesOptions, TrackPlacesResult, TrackPoint } from '../types';
11
+ export declare class PlaceCollection extends SmrtCollection<Place> {
12
+ static readonly _itemClass: typeof Place;
13
+ /**
14
+ * Look up a place by query or coordinates, creating it if not found
15
+ *
16
+ * This is the key method for organic database growth:
17
+ * 1. Search local database first
18
+ * 2. If not found, query @happyvertical/geo
19
+ * 3. Create place from geocoding result
20
+ * 4. Return place
21
+ *
22
+ * @param query - Address or location query string
23
+ * @param options - Lookup options (provider, type, parent, etc.)
24
+ * @returns Place instance
25
+ */
26
+ lookupOrCreate(query: string, options?: LookupOrCreateOptions): Promise<Place | null>;
27
+ /**
28
+ * Find place by coordinates (within small threshold)
29
+ *
30
+ * @param latitude - Latitude to search
31
+ * @param longitude - Longitude to search
32
+ * @param threshold - Max distance in degrees (default: 0.0001 ~11m)
33
+ * @returns Place instance or null
34
+ */
35
+ private findByCoordinates;
36
+ /**
37
+ * Find place by query text (matches name, city, region, country)
38
+ *
39
+ * @param query - Search query
40
+ * @returns Place instance or null
41
+ */
42
+ private findByQuery;
43
+ /**
44
+ * Geocode query or coordinates using @happyvertical/geo
45
+ *
46
+ * @param query - Address query
47
+ * @param coords - Optional coordinates for reverse geocoding
48
+ * @param provider - Geo provider to use
49
+ * @returns Array of Location results
50
+ */
51
+ private geocode;
52
+ /**
53
+ * Find a place by the provider's native id (Google place_id, OSM
54
+ * osm-node-N, etc.). Used as the primary idempotency key by
55
+ * `discoverNearby` so repeat POI searches don't create duplicate rows.
56
+ */
57
+ private findByExternalId;
58
+ /**
59
+ * Idempotent "find or create" for a geo Location. Keyed purely on the
60
+ * provider's externalId (Google place_id, osm-node-*, etc.), which is
61
+ * stable per POI across repeat searches. The older `lookupOrCreate`
62
+ * keeps its own fallback chain (name/address/coordinate matching) for
63
+ * address-style workflows where externalId isn't reliable.
64
+ *
65
+ * Returns `{ place, created }` so callers can distinguish fresh rows
66
+ * from reused ones without re-querying the table — this is how
67
+ * `resolveTrackPlaces` derives its `cacheHitCount` without a full
68
+ * scan per bucket.
69
+ */
70
+ private ensureFromLocation;
71
+ /**
72
+ * Create place from @happyvertical/geo Location data
73
+ *
74
+ * @param location - Location from geocoding
75
+ * @param typeSlug - Optional type slug override
76
+ * @param parentId - Optional parent place ID
77
+ * @returns Created Place instance
78
+ */
79
+ private createFromLocation;
80
+ /**
81
+ * Discover POIs near a coordinate and persist them as Place rows.
82
+ *
83
+ * Composes `@happyvertical/geo`'s `findPoisNear` with `ensureFromLocation`
84
+ * so every returned POI is either reused from the local DB (when the
85
+ * provider returns an id matching an existing Place `externalId`) or
86
+ * created fresh otherwise. The cache is effectively automatic because
87
+ * the provider's own place_id becomes the Place row's `externalId`, so
88
+ * calling `discoverNearby` twice for the same area on the same provider
89
+ * is a no-op after the first run when the provider returns stable ids.
90
+ *
91
+ * Requires a geo provider that implements `findPoisNear`. Throws a clear
92
+ * error otherwise so consumers can fall back to `lookupOrCreate` or
93
+ * switch providers.
94
+ */
95
+ discoverNearby(latitude: number, longitude: number, radiusMeters: number, options?: DiscoverNearbyOptions): Promise<Place[]>;
96
+ /**
97
+ * Internal variant of `discoverNearby` that exposes whether each
98
+ * returned Place was created during this call (`true`) or reused from
99
+ * an earlier call (`false`). Used by `resolveTrackPlaces` to classify
100
+ * buckets as cache hits without having to re-scan the Place table.
101
+ */
102
+ private discoverNearbyDetailed;
103
+ /**
104
+ * Resolve POIs along a GPS track (e.g. a video's per-frame path).
105
+ *
106
+ * Naively walking every point would hammer the provider with redundant
107
+ * requests — consecutive samples are usually within a few meters. This
108
+ * method buckets points into a `bucketMeters`-wide grid, calls
109
+ * `discoverNearby` once per distinct bucket, and throttles requests per
110
+ * `throttleMs` so free tiers (Overpass, Nominatim) stay inside their
111
+ * community rate limits without the caller having to manage a queue.
112
+ *
113
+ * The returned `places` are deduped across buckets by Place id, so a
114
+ * POI that falls within several overlapping search radii appears once.
115
+ */
116
+ resolveTrackPlaces(points: ReadonlyArray<TrackPoint>, options?: ResolveTrackPlacesOptions): Promise<TrackPlacesResult>;
117
+ /**
118
+ * Provider wiring (env keys, user-agent string, etc.) that `geocode`
119
+ * and `discoverNearby` share so the two code paths can't drift. Kept
120
+ * separate from the adapter call itself so tests and future providers
121
+ * can inspect or override the options before construction.
122
+ */
123
+ private getGeoAdapterOptions;
124
+ /**
125
+ * Build a geo adapter configured for this call. Single source of truth
126
+ * for provider wiring — `geocode` and `discoverNearby` both come through
127
+ * here.
128
+ */
129
+ private getGeoAdapter;
130
+ /**
131
+ * Get immediate children of a parent place
132
+ *
133
+ * @param parentId - The parent place ID
134
+ * @returns Array of child places
135
+ */
136
+ getChildren(parentId: string): Promise<Place[]>;
137
+ /**
138
+ * Get root places (no parent)
139
+ *
140
+ * @returns Array of root places
141
+ */
142
+ getRootPlaces(): Promise<Place[]>;
143
+ /**
144
+ * Get places by type
145
+ *
146
+ * @param typeSlug - PlaceType slug
147
+ * @returns Array of places of that type
148
+ */
149
+ getByType(typeSlug: string): Promise<Place[]>;
150
+ /**
151
+ * Get place hierarchy (all ancestors and descendants)
152
+ *
153
+ * @param placeId - The place ID
154
+ * @returns Object with ancestors, current place, and descendants
155
+ */
156
+ getHierarchy(placeId: string): Promise<import("@happyvertical/smrt-core").HierarchyView<Place>>;
157
+ getAssets(placeId: string, relationship?: string): Promise<Asset[]>;
158
+ addAsset(placeId: string, asset: Asset, relationship?: string, sortOrder?: number): Promise<void>;
159
+ removeAsset(placeId: string, assetId: string, relationship?: string): Promise<void>;
160
+ /**
161
+ * Search places by proximity to coordinates
162
+ *
163
+ * @param latitude - Center latitude
164
+ * @param longitude - Center longitude
165
+ * @param radiusKm - Search radius in kilometers
166
+ * @returns Array of places within radius, sorted by distance
167
+ */
168
+ searchByProximity(latitude: number, longitude: number, radiusKm?: number): Promise<Place[]>;
169
+ /**
170
+ * Calculate distance between two coordinates using Haversine formula
171
+ *
172
+ * @param lat1 - First latitude
173
+ * @param lng1 - First longitude
174
+ * @param lat2 - Second latitude
175
+ * @param lng2 - Second longitude
176
+ * @returns Distance in kilometers
177
+ */
178
+ private calculateDistance;
179
+ /**
180
+ * Convert degrees to radians
181
+ */
182
+ private toRad;
183
+ /**
184
+ * Find all places belonging to a specific tenant
185
+ *
186
+ * @param tenantId - The tenant ID to filter by
187
+ * @returns Array of places for the tenant
188
+ */
189
+ findByTenant(tenantId: string): Promise<Place[]>;
190
+ /**
191
+ * Find all global places (not associated with any tenant).
192
+ *
193
+ * Routes through the shared tenant-global helper so it does not throw under
194
+ * an active tenant context (an explicit `tenant_id IS NULL` filter would be
195
+ * flagged as an isolation violation). (#1600)
196
+ *
197
+ * @returns Array of global places
198
+ */
199
+ findGlobal(): Promise<Place[]>;
200
+ /**
201
+ * Find places for a tenant including global places.
202
+ *
203
+ * Fails closed if an active tenant context requests a different tenant's
204
+ * rows; the admin/system path keeps the cross-tenant capability. (#1600)
205
+ *
206
+ * @param tenantId - The tenant ID to include
207
+ * @returns Array of tenant-specific and global places
208
+ */
209
+ findWithGlobals(tenantId: string): Promise<Place[]>;
210
+ }
211
+ //# sourceMappingURL=PlaceCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaceCollection.d.ts","sourceRoot":"","sources":["../../src/collections/PlaceCollection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAMxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,UAAU,EACX,MAAM,UAAU,CAAC;AAiBlB,qBAAa,eAAgB,SAAQ,cAAc,CAAC,KAAK,CAAC;IACxD,MAAM,CAAC,QAAQ,CAAC,UAAU,eAAS;IAEnC;;;;;;;;;;;;OAYG;IACG,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAiDxB;;;;;;;OAOG;YACW,iBAAiB;IA8B/B;;;;;OAKG;YACW,WAAW;IAgCzB;;;;;;;OAOG;YACW,OAAO;IAerB;;;;OAIG;YACW,gBAAgB;IAS9B;;;;;;;;;;;OAWG;YACW,kBAAkB;IAahC;;;;;;;OAOG;YACW,kBAAkB;IAwChC;;;;;;;;;;;;;;OAcG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,KAAK,EAAE,CAAC;IAenB;;;;;OAKG;YACW,sBAAsB;IAqCpC;;;;;;;;;;;;OAYG;IACG,kBAAkB,CACtB,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,EACjC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,iBAAiB,CAAC;IAyF7B;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAc5B;;;;OAIG;YACW,aAAa;IAM3B;;;;;OAKG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAMrD;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAMvC;;;;;OAKG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAYnD;;;;;OAKG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM;IAO5B,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAInE,QAAQ,CACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,YAAY,SAAe,EAC3B,SAAS,SAAI,GACZ,OAAO,CAAC,IAAI,CAAC;IAWV,WAAW,CACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAUhB;;;;;;;OAOG;IACG,iBAAiB,CACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,GAAE,MAAW,GACpB,OAAO,CAAC,KAAK,EAAE,CAAC;IAgCnB;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;OAEG;IACH,OAAO,CAAC,KAAK;IAQb;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAItD;;;;;;;;OAQG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAIpC;;;;;;;;OAQG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;CAG1D"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * PlaceTypeCollection - Collection manager for PlaceType objects
3
+ *
4
+ * Provides simple lookup and creation for place types.
5
+ */
6
+ import { SmrtCollection } from '@happyvertical/smrt-core';
7
+ import { PlaceType } from '../models/PlaceType';
8
+ export declare class PlaceTypeCollection extends SmrtCollection<PlaceType> {
9
+ static readonly _itemClass: typeof PlaceType;
10
+ /**
11
+ * Get or create a place type by slug
12
+ *
13
+ * @param slug - PlaceType slug (e.g., 'city', 'building')
14
+ * @param name - Optional display name (defaults to capitalized slug)
15
+ * @returns PlaceType instance
16
+ */
17
+ getOrCreate(slug: string, name?: string): Promise<PlaceType>;
18
+ /**
19
+ * Get a place type by slug
20
+ *
21
+ * @param slug - PlaceType slug to search for
22
+ * @returns PlaceType instance or null if not found
23
+ */
24
+ getBySlug(slug: string): Promise<PlaceType | null>;
25
+ /**
26
+ * Initialize default place types
27
+ *
28
+ * Creates standard types if they don't exist:
29
+ * - country
30
+ * - region (state/province)
31
+ * - city
32
+ * - address
33
+ * - building
34
+ * - room
35
+ * - zone (for abstract/virtual places)
36
+ *
37
+ * @returns Array of created/existing place types
38
+ */
39
+ initializeDefaults(): Promise<PlaceType[]>;
40
+ }
41
+ //# sourceMappingURL=PlaceTypeCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaceTypeCollection.d.ts","sourceRoot":"","sources":["../../src/collections/PlaceTypeCollection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,qBAAa,mBAAoB,SAAQ,cAAc,CAAC,SAAS,CAAC;IAChE,MAAM,CAAC,QAAQ,CAAC,UAAU,mBAAa;IAEvC;;;;;;OAMG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAkBlE;;;;;OAKG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAIxD;;;;;;;;;;;;;OAaG;IACG,kBAAkB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CAoBjD"}