🧱 Location blocks
Location blocks are reusable hierarchy helpers and MongoDB operations exposed on the blocks namespace from @nodeblocks/backend-sdk. They return neverthrow results; consuming routes map block errors to HTTP responses.
Inventory
| Export | Kind | Inputs | Result / behavior / errors |
|---|---|---|---|
LocationBlockError | Error class | Message, optional data | Base location error. |
LocationNotFoundBlockError | Error class | Message, optional data | Missing location. |
LocationUnexpectedDBError | Error class | Message, optional data | Database or mutation failure. |
LocationConflictError | Error class | Message, optional data | Dependent descendants prevent deletion. |
buildAncestorsFromParent | Async helper | Parent ancestors, parent ID | Copied, stringified ancestor array. |
buildLocationToCreate | Async helper | Location, ancestors (default []) | Creation payload with hierarchy fields. |
buildDescendantsFilter | Async helper | Location ID | Ancestors $in filter. |
assertNoDescendantLocations | Async guard | Child-location array | true or LocationConflictError. |
getLocationById | Async query | Collection, location ID | Projected location or not-found/database error. |
createLocation | Async mutation | Collection, location | Generated location ID or database error. |
updateLocation | Async mutation | Collection, location update, location ID | true or not-found/database error. |
deleteLocation | Async mutation | Collection, location ID | true or database error. |
findLocations | Async query | Collection, filter | Projected array or database error. |
normalizeLocation | Synchronous normalizer | Location document | Public location with parent. |
Details
LocationBlockError
Implementation
Extends BlockError with inherited (message: string, data?: unknown) constructor and no intrinsic HTTP status.
LocationNotFoundBlockError
Implementation
Extends LocationBlockError. getLocationById and updateLocation return this class with Location not found. Get/update routes map it to 404; the delete block itself does not emit it.
Direct SDK route consumers: createLocationRoute, getLocationRoute, updateLocationRoute, deleteLocationRoute, findLocationsRoute.
LocationUnexpectedDBError
Implementation
Extends LocationBlockError. Returned by database blocks for their source-defined failures; Location routes map it to 500.
Direct SDK route consumers: createLocationRoute, getLocationRoute, updateLocationRoute, deleteLocationRoute, findLocationsRoute.
LocationConflictError
Implementation
Extends LocationBlockError. assertNoDescendantLocations returns it with Dependent child locations still exist; the delete route maps it to 409.
Direct SDK route consumers: deleteLocationRoute.
buildAncestorsFromParent
Implementation
Signature: buildAncestorsFromParent( ancestorsOfParent: string[], parentId: string, ): Promise<Result<string[], never>>.
Returns ok([...ancestorsOfParent, parentId].map(String)), preserving order without mutating the input array. The create route uses it for a truthy parent ID.
Direct SDK route consumers: createLocationRoute.
buildLocationToCreate
Implementation
Signature: buildLocationToCreate( location: Record<string, unknown>, ancestors?: string[], ): Promise<Result<Record<string, unknown>, never>>.
Copies the supplied location, overwrites ancestors, and sets parentId to String(location.parentId) when truthy, otherwise null. It does not validate hierarchy or compute ancestors itself.
Direct SDK route consumers: createLocationRoute.
buildDescendantsFilter
Implementation
Signature: buildDescendantsFilter(locationId: string): Promise<Result<Record<string, unknown>, never>>.
Returns ok({ancestors: {$in: [String(locationId)]}}). The delete route supplies it to findLocations to locate all descendants.
Direct SDK route consumers: deleteLocationRoute.
assertNoDescendantLocations
Implementation
Signature: assertNoDescendantLocations( childLocations: Record<string, unknown>[], ): Promise<Result<boolean, LocationBlockError>>.
An empty array returns ok(true); a nonempty array returns LocationConflictError('Dependent child locations still exist'). It does not query the database.
Direct SDK route consumers: deleteLocationRoute.
getLocationById
Implementation
Signature: getLocationById( locationsCollection: Collection, locationId: string, ): Promise<Result<Record<string, unknown>, LocationBlockError>>.
Calls findOne({id: String(locationId)}, {projection: {_id: 0}}). The returned document retains hierarchy fields. Absence returns LocationNotFoundBlockError('Location not found'); exceptions return LocationUnexpectedDBError('Failed to get location by id').
Direct SDK route consumers: createLocationRoute, getLocationRoute, updateLocationRoute.
createLocation
Implementation
Signature: createLocation( locationsCollection: Collection, location: Record<string, unknown>, ): Promise<Result<string, LocationBlockError>>.
Applies createBaseEntity, adding a UUID id and ISO-string timestamps, then inserts the entity. Returns ok(baseEntity.id). Missing insertedId or insertion exceptions return LocationUnexpectedDBError('Failed to create location'). Base-entity creation occurs before the try block.
Direct SDK route consumers: createLocationRoute.
updateLocation
Implementation
Signature: updateLocation( locationsCollection: Collection, location: Record<string, unknown>, locationId: string, ): Promise<Result<boolean, LocationBlockError>>.
Calls updateOne({id: String(locationId)}, {$set: updateBaseEntity(location)}), adding updatedAt. Zero matches return LocationNotFoundBlockError('Location not found'); zero modifications or exceptions return LocationUnexpectedDBError('Failed to update location'). Success is ok(true).
Direct SDK route consumers: updateLocationRoute.
deleteLocation
Implementation
Signature: deleteLocation( locationsCollection: Collection, locationId: string, ): Promise<Result<boolean, LocationBlockError>>.
Calls deleteOne({id: String(locationId)}). Zero deletions return LocationUnexpectedDBError('Location could not be deleted'); exceptions return the same class with Failed to delete location. Success is ok(true). The block does not check descendants or return a not-found error.
Direct SDK route consumers: deleteLocationRoute.
findLocations
Implementation
Signature: findLocations( locationsCollection: Collection, filter: Record<string, unknown>, ): Promise<Result<Record<string, unknown>[], LocationBlockError>>.
Calls find(filter, {projection: {_id: 0}}).toArray() and returns the array unchanged, including hierarchy fields. Exceptions return LocationUnexpectedDBError('Failed to find locations'). It adds no pagination or sorting.
Direct SDK route consumers: deleteLocationRoute, findLocationsRoute.
normalizeLocation
Implementation
Signature: normalizeLocation( location: Record<string, unknown> & { _id: string; parentId: string; ancestors: string[]; }, ): Result<Record<string, unknown>, never>.
Removes _id, parentId, and ancestors, preserving all other fields, then returns ok({...rest, parent: parentId}). The declared input requires _id: string and parentId: string, even though projected database reads omit _id and root locations have parentId: null. Current Location routes do not compose this normalizer.