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 in users/{userId}/favorites/{favoriteId} — see User Schema.
  • placeId (string, optional) on startLocation, endLocation, and each entry in breakpointsTo on rides/{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