Place Schemas
import { ... } from "@95octane/common/schemas/place"
Place data is not persisted in its own Firestore collection. It is fetched
on demand from the Google Places API, transformed by
@95octane/common/maps/places, and returned to clients. The only place-derived
data stored by 95octane is the placeId string on favorites
(User Schema) and on ride locations (Ride Schema).
Schemas
| Schema | Purpose |
|---|---|
PlaceSchema |
A single Place result from Google Places (details or search hit) |
PlacesSearchBodySchema |
Request body for POST /place/search |
PlaceByIdQuerySchema |
Query string for GET /place/details/:id |
PlacesMediaBodySchema |
Request body for POST /place/photo |
PhotoMediaSchema |
A single photo media result {name, photoUri} |
BusinessStatusEnum |
Operational status literal union |
PlacesSearchResponseSchema |
Array<Place> — response shape for POST /place/search |
PlaceByIdResponseSchema |
Alias of PlaceSchema — response shape for GET /place/details/:id |
PlacesMediaResponseSchema |
Alias of PhotoMediaSchema — response shape for POST /place/photo |
PlaceSchema
A normalized representation of a Google Places API place. All fields are
populated by transformResponse in @95octane/common/maps/places/get.ts and
search.ts. Missing or null fields from Google are coerced to safe defaults via
nullSafe.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
id |
string \| null |
yes | non-empty if set | Raw place ID (e.g., "ChIJyWEHuEmuEmsRm9hTkapTCrk") without the places/ prefix; null if Google did not return one |
name |
string \| null |
yes | non-empty if set | Full Places resource name (e.g., "places/ChIJ..."); use as input to getPlaceByName and photo fetches |
displayName |
string |
yes | non-empty trimmed | Human-readable name shown to users (e.g., "Prestige Lakeside Habitat"); defaults to "" if missing |
formattedAddress |
string \| null |
yes | non-empty if set | Full postal address as formatted by Google; null when unavailable |
businessStatus |
BusinessStatusEnum |
yes | enum | Operating status (see below); defaults to "UNKNOWN" if Google did not return one |
googleMapsUri |
string |
yes | URL or "" |
Deep link to the place on Google Maps; defaults to "" if missing |
location |
{lat, lng} \| null |
no | lat −90..90; lng −180..180 | WGS-84 coordinates; null when either latitude or longitude is missing from Google's response (default: null) |
photosName |
string[] |
yes | each non-empty | Photo resource names (e.g., "places/ChIJ.../photos/AF1QipO..."); pass any element to POST /place/photo |
type |
BreakpointTypeEnum |
yes | enum | App-specific category derived from Google types[] via getBreakpointType |
BusinessStatusEnum
"BUSINESS_STATUS_UNSPECIFIED" | "CLOSED_TEMPORARILY" | "CLOSED_PERMANENTLY" | "OPERATIONAL" | "UNKNOWN"
type derivation
type reuses BreakpointTypeEnum from the ride schema. The categorization is
performed by getBreakpointType(placeTypes) in
@95octane/common/maps/places/utils.ts:
Google types[] contains |
App type |
|---|---|
"restaurant" or "cafe" |
restaurant |
"gas_station" |
fuelStation |
| anything else | other |
The values origin, destination, additionalDestination, meetingPoint, and
haltPoint are part of the enum but are never assigned by Google Places results
— they are only used when the client labels a saved location (favorite or ride
breakpoint).
PlacesSearchBodySchema
Request body for POST /place/search.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
text |
string |
yes | non-empty | Free-text query |
regionCode |
SupportedRegionListSchema |
yes | CLDR region code | Region bias for results |
languageCode |
SupportedLanguageListSchema |
yes | BCP-47 language code | Result localization |
currentLocation |
LatLngSchema |
no | lat −90..90; lng −180..180 | Optional center point for location bias |
radius |
number |
no | 5_000 ≤ x ≤ 500_000 (m) | Bias radius in metres; only honored when currentLocation is also present |
When both currentLocation and radius are provided, the Places API
locationBias.circle is set. If either is missing, an unbiased global search is
performed.
PlaceByIdQuerySchema
Query string for GET /place/details/:id.
| Field | Type | Required | Description |
|---|---|---|---|
regionCode |
SupportedRegionListSchema |
yes | Region for request locale |
languageCode |
SupportedLanguageListSchema |
yes | Language for the response |
The :id path parameter is the raw place ID without a places/ prefix; the
service layer prepends places/ before calling Google.
PlacesMediaBodySchema
Request body for POST /place/photo.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
name |
string |
yes | non-empty trimmed | Full photo resource name from PlaceSchema.photosName[] (e.g., "places/ChIJ.../photos/AF1QipO...") — no /media suffix |
maxWidth |
number |
no | > 0 | Desired max width in pixels; defaults to 1024 server-side |
maxHeight |
number |
no | > 0 | Desired max height in pixels; defaults to 1024 server-side |
The service appends /media to name before calling
PlacesClient.getPhotoMedia.
PhotoMediaSchema
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
name |
string |
yes | non-empty trimmed | Echo of the requested photo resource name |
photoUri |
string |
yes | URL | Time-limited Google CDN URL the client can fetch |
Firestore Storage
PlaceSchema itself is never written to Firestore. The only place-derived
references persisted are:
placeId(string, optional) on each favorite inusers/{userId}/favorites/{favoriteId}— see User Schema.placeId(string, optional) onstartLocation,endLocation, and each entry inbreakpointsToonrides/{rideId}— see Ride Schema.
Re-resolving a stored placeId back to a Place requires a fresh
GET /place/details/:id call.
Data Flow
client ── POST /place/search ─────► PlaceService.searchPlace
│
▼
@95octane/common/maps/places.searchPlace
│
PlacesClient.searchText (Google Places API)
│
transformResponse
│
Place[]
│
▼
client (renders results, may save placeId
to a favorite or ride breakpoint)
GET /place/details/:id follows the same shape, calling PlacesClient.getPlace
and returning a single Place. POST /place/photo calls
PlacesClient.getPhotoMedia and returns a PhotoMedia with a short-lived
signed URL.
Indexes
None. Place data is not stored in Firestore.
See Also
- Place API
- Ride Schema — uses
placeIdon locations - User Schema — uses
placeIdon favorites