- TypeScript 99.5%
- Dockerfile 0.5%
| .yaak | ||
| deliverable | ||
| src | ||
| .gitignore | ||
| bun.lock | ||
| compose.yaml | ||
| Dockerfile | ||
| drizzle.config.ts | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
API Development — Cinema
You'll find in this repository my work for this module and my deliverable.
You have been tasked to build the new API for a famous cinema that has multiple places across France. Your goal will be to integrate the overall API for customers to easily browse movies and find places where they can watch a movie.
Information about the API
Each endpoint that forwards a list should handle pagination. Pagination is cursor based. Each entity in the API should have a public identifier which is mapped according to the Stripe style, meaning it is always prefixed with a 3 characters prefix which is unique per entity and that use a snowflake ID, see the attached snowflake.js file. It is up to you to come up with the prefix namings for each entity.
All dates in the API should be formatted using the ISO 8601 standard.
All errors should have the appropriate error code and message. It is your role to come up with the proper HTTP response code and the error code naming. One endpoint can return multiple errors, for instance, for validation purposes. All errors should have the same format, which is as follows:
content-type: application/json
body:
errors:
type: array
items:
type: object
properties:
code: string
message: string
Creating an account
You should be able to create an account using your email & password.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/auth/signup
request:
content-type: application/json
body:
email: string
password: string
response:
content-type: application/json
body:
user:
id: string
email: string
created_at: string
Authentication
You should be able to sign in using your email & password.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/auth/signin
request:
content-type: application/json
body:
email: string
password: string
response:
content-type: application/json
body:
token: string
Analytics
You must implement a tracking system so the company can track who visits what. When you switch from one page to another, an event should be sent to the backend to materialize which page the user visited. This endpoint does not have to be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/analytics/track
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint. If set, the tracking row should have the user identifier.
required: false
body:
tracking_id: string
type: string
page:
type: object
properties:
scheme: string
path: string
query:
type: object
description: Dynamic map of query parameter names to their values.
The type field can either be page_enter or page_exit.
This endpoint does not return a response body.
List of movies
You should be able to list all the movies. Each movie has an identifier, a title, a description, a duration (in minutes), airing dates, which is an interval, from a certain date to another date. Those dates must be inclusive. It also has a rating. Airing dates should be derived from sessions and the rating should be derived from ratings. This endpoint does not have to be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: GET
path: /v1/movies
request:
content-type: application/json
query:
sort: string
limit: integer
cursor: string
response:
content-type: application/json
body:
movies:
type: array
items:
type: object
properties:
id: string
title: string
description: string
poster: string
duration: number
airing_dates:
type: object
properties:
from: string
to: string
rating: number
metadata:
type: object
properties:
has_more: boolean
end_cursor: string
By default, the list should be ordered by rating. There are other sorting
mechanisms such as "new" where the list will be ordered by
airing_dates.from with the most recent first, or "leaving soon", where the
list will be ordered by airing_dates.to with the oldest first. You can choose
those settings using the query param sort. The accepted values are:
rating(default)newleaving_soon
Get a movie
You should be able to get the details of a single movie. This endpoint does not have to be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: GET
path: /v1/movies/{movie_id}
request:
content-type: application/json
path:
movie_id: string
response:
content-type: application/json
body:
movie:
type: object
properties:
id: string
title: string
description: string
poster: string
duration: number
airing_dates:
type: object
properties:
from: string
to: string
rating: number
See where a movie is aired
You should be able, for one movie, to know the places where it will be aired. Each place has an identifier, a name, and an address. Each place also has a number of seats (capacity) which is used for booking limits, but it should not be returned by this endpoint. This endpoint does not have to be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: GET
path: /v1/movies/{movie_id}/places
request:
content-type: application/json
path:
movie_id: string
query:
limit: integer
cursor: string
response:
content-type: application/json
body:
places:
type: array
items:
type: object
properties:
id: string
name: string
address: string
metadata:
type: object
properties:
has_more: boolean
end_cursor: string
See the sessions of a movie in a place
You should be able, for one movie and one place, to know the sessions that are
airing. Each session has an identifier and a starts_at datetime. You should be
able to filter dates, the bounds are inclusive, by default, it should be filtered
by the most recent being returned first.
The specification of this endpoint is as follows:
endpoint:
method: GET
path: /v1/movies/{movie_id}/places/{place_id}/sessions
request:
content-type: application/json
path:
movie_id: string
place_id: string
query:
from: string
to: string
limit: integer
cursor: string
response:
content-type: application/json
body:
sessions:
type: array
items:
type: object
properties:
id: string
starts_at: string
metadata:
type: object
properties:
has_more: boolean
end_cursor: string
Rate a movie
You should be able to rate a movie. Each rating has an identifier and a value from 0 to 5. A user can only rate a movie once, if they rate it again, the previous rating should be overridden. This endpoint should be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/movies/{movie_id}/rate
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint.
required: true
body:
value: number
response:
content-type: application/json
body:
rating:
id: string
value: number
Book a session
You should be able to book a session. Each booking has an identifier, a number of seats, and a date. This endpoint only opens a booking session. You will later be able to select the number of seats and then confirm the booking. Once you have created a booking session, you should make sure to confirm it in the next minute. Once a booking session is expired, it can not be touched anymore. Confirming a booking without any reserved seats should return an error. This endpoint should be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/sessions/{session_id}/book
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint.
required: true
path:
session_id: string
response:
content-type: application/json
body:
booking:
id: string
session_id: string
created_at: string
closes_at: string
Reserve seats from a booking
You should be able to reserve seats from a booking. Each reservation has an identifier, a number of seats, and a date. There should be a limit of seats based on the places. All of our cinemas only have one room. If there is not anymore seats available, the request should be rejected. You can call this endpoint multiple times for the same booking. If an update asks for more seats and they are not available, the request should fail. If an update asks for fewer seats, the difference should be freed up. This endpoint should be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/bookings/{booking_id}/reserve
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint.
required: true
path:
booking_id: string
body:
seats: number
response:
content-type: application/json
body:
booking:
id: string
session_id: string
reserved_seats: number
created_at: string
closes_at: string
Confirm a booking
You should be able to confirm a booking. Once a booking is confirmed, it can not be touched anymore. Confirming a booking without any reserved seats should return an error. This endpoint should be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/bookings/{booking_id}/confirm
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint.
required: true
path:
booking_id: string
response:
content-type: application/json
body:
booking:
id: string
session_id: string
reserved_seats: number
created_at: string
closes_at: string
confirmed_at: string
List my bookings
You should be able to list all your bookings. This endpoint should be authenticated. Each booking should resolve the movie and the place from the session.
The specification of this endpoint is as follows:
endpoint:
method: GET
path: /v1/bookings
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint.
required: true
query:
limit: integer
cursor: string
response:
content-type: application/json
body:
bookings:
type: array
items:
type: object
properties:
id: string
session_id: string
reserved_seats: number
created_at: string
closes_at: string
confirmed_at: string
movie:
type: object
properties:
id: string
title: string
place:
type: object
properties:
id: string
name: string
metadata:
type: object
properties:
has_more: boolean
end_cursor: string
Cancel a booking
You should be able to cancel a booking. Once a booking is confirmed or expired, it can not be cancelled anymore. This endpoint should be authenticated.
The specification of this endpoint is as follows:
endpoint:
method: POST
path: /v1/bookings/{booking_id}/cancel
request:
content-type: application/json
headers:
Authorization:
description: Bearer token obtained from the signin endpoint.
required: true
path:
booking_id: string
response:
content-type: application/json
body:
booking:
id: string
session_id: string
reserved_seats: number
created_at: string
closes_at: string
confirmed_at: string
cancelled_at: string
Deliverable
You must provide the following files alongside your implementation: