api/config/schema.graphql
scalar Date
scalar ID
scalar JSON
"Our root data resolver. Queries to access data should be RARE. All data is contextual, so start from the context and narrow from there."
type User {
id: ID!
verified: Boolean!
preferredName: String!
weightLog(day: String!): WeightLogConnection!
weightLogSummary(input: WeightLogSummaryInput): WeightLogSummary!
foodLog(day: String!): FoodLogConnection!
foods(input: FoodQueryInput): FoodConnection!
activities(input: ActivityQueryInput): ActivityConnection!
activitySummary(input: ActivityVisualizationInput): [TileMapDataPoint!]!
popularActivities: [Activity!]!
popularFoods: [Food!]!
foodLogStats: FoodLogStats!
preferences: [UserPreference!]!
}
type Query {
currentUser: User
upload(input: UploadInput): Upload!
"Fast, auto-complete ready search for foods"
searchFoods(input: SearchFoodsInput!): [Food!]!
}
type Mutation {
# Uploads
getUploadTokens(input: UploadTokenInput!): UploadTokenMutationPayload!
saveUploadData(input: UploadInput!): UploadMutationPayload!
# Authentication
login(input: LoginInput!): LoginMutationPayload!
logout: LogoutMutationPayload!
register(input: RegisterInput!): LoginMutationPayload!
resetPassword(input: ResetPasswordInput!): ResetPasswordMutationPayload!
requestPasswordResetToken(
input: RequestPasswordResetTokenInput!
): RequestResetTokenMutationPayload!
verifyEmail(input: VerifyEmailInput!): VerifyEmailMutationPayload!
requestEmailLoginLink(
input: RequestEmailLoginLinkInput!
): RequestEmailLoginLinkMutationPayload!
loginWithToken(input: LoginWithTokenInput!): LoginWithTokenMutationPayload!
# User
saveUserPreferences(
input: SaveUserPreferencesInput!
): UserPreferencesMutationPayload!
# Food Log
saveFoodLog(input: SaveFoodLogInput!): FoodLogMutationPayload!
deleteFoodLog(input: DeleteFoodLogInput!): FoodLogMutationPayload!
# Food
saveFood(input: FoodInput!): FoodMutationPayload!
deleteFoodMeasurement(input: FoodMeasurementInput!): FoodMutationPayload!
# Activities
saveActivity(input: ActivityInput!): ActivityMutationPayload!
deleteActivity(input: DeleteActivityInput!): ActivityMutationPayload!
# Activity Log
saveActivityLog(input: SaveActivityLogInput!): ActivityLogMutationPayload!
deleteActivityLog(input: DeleteActivityLogInput!): ActivityLogMutationPayload!
# Weight Log
saveWeightLog(input: SaveWeightLogInput!): WeightLogMutationPayload!
deleteWeightLog(input: DeleteWeightLogInput!): WeightLogMutationPayload!
}
#################
# Enums #
#################
enum UploadEntityType {
FOOD_IMAGE
}
enum UploadUrlType {
"384x384"
MEDIUM_SQUARE
"width: 64x64"
SMALL
"width: 24x24"
PREVIEW
}
enum ActivityType {
"Reps and weight (e.g., 3 reps at 50lbs)"
WEIGHT
"e.g., 20 minutes of running"
TIMED
"Exercise measured in distance (e.g., 5 miles)"
DISTANCE
"Exercise measured in the number of repetitions (e.g., push ups)"
REPETITIVE
}
enum Muscle {
ABS
ADDUCTORS
BICEPS
CALVES
DELTOIDS
FOREARMS
GLUTES
HAMSTRINGS
LATS
OBLIQUES
PECTORALS
QUADS
TRAPEZIUS
TRICEPS
}
enum Unit {
# Weight
GRAMS # Default
G
KG
KILOGRAMS
LB
LBS
OUNCES
OZ
# Time
MILLISECONDS
MS
SECONDS # Default
MINUTES
HOURS
DAYS
# Distance
CENTIMETERS
CM
KILOMETERS
KM
K
METERS
MILES
MI
MILLIMETERS # Default
MM
FEET
FT
YARDS
YDS
}
enum UserPreferenceType {
BIRTHDAY
HEIGHT
DEFAULT_UNIT
FATURDAYS
FATURDAY_CALORIES
FATURDAY_FAT
FATURDAY_CARBS
FATURDAY_PROTEIN
}
#################
# Inputs #
#################
input SaveUserPreferencesInput {
preferences: [UserPreferenceInput!]!
}
input UserPreferenceInput {
key: UserPreferenceType!
"The JSON.stringified value of the preference"
value: String!
}
input SearchFoodsInput {
searchTerm: String!
page: Int
}
input RequestEmailLoginLinkInput {
email: String!
}
input LoginWithTokenInput {
loginToken: String!
}
input VerifyEmailInput {
token: String!
}
input RequestPasswordResetTokenInput {
email: String!
}
input ResetPasswordInput {
password: String!
passwordConfirmation: String!
resetToken: String!
}
input ActivityInput {
id: ID
name: String
description: String
intensity: Int
"Activity's ExRx.net link"
exrx: String
type: ActivityType
"Muscle groups targeted with this exercise"
muscleGroups: [Muscle!]
}
input DeleteActivityInput {
id: ID!
}
input FoodMeasurementInput {
id: String!
}
input UploadInput {
id: String
publicId: String
entityId: String
entityType: UploadEntityType
extension: String
}
input UploadTokenInput {
count: Int!
}
input LoginInput {
email: String!
password: String!
}
input RegisterInput {
email: String!
password: String!
passwordConfirmation: String!
}
input FoodLogConnectionInput {
before: String
after: String
first: Int
last: Int
day: String
}
input SaveFoodLogInput {
day: String!
foodLogs: [FoodLogInput!]!
}
input SaveActivityLogInput {
day: String!
activityId: ID!
activityLogs: [ActivityLogInput!]!
}
input FoodLogInput {
id: ID
description: String!
calories: Int
fat: Int
carbs: Int
protein: Int
foodId: ID
measurementId: ID
}
input ActivityLogInput {
id: ID
reps: String
work: String
}
input WeightLogInput {
id: ID
weight: String!
}
input SaveWeightLogInput {
day: String!
weightLogs: [WeightLogInput!]!
}
input DeleteWeightLogInput {
id: ID!
}
input DeleteActivityLogInput {
id: ID!
}
input DeleteFoodLogInput {
id: ID!
}
input FoodInput {
id: ID
name: String
description: String
imageUploadId: String
measurements: [MeasurementInput!]
}
input MeasurementInput {
id: ID
measurement: String
amount: Int
calories: Int
fat: Int
carbs: Int
protein: Int
}
input FoodQueryInput {
before: String
after: String
first: Int
last: Int
filter: FoodQueryFilters
}
input ActivityQueryInput {
before: String
after: String
first: Int
last: Int
filter: ActivityQueryFilters
}
input FoodQueryFilters {
id: ID
searchString: String
}
input ActivityQueryFilters {
id: ID
muscleGroups: [Muscle!]
searchString: String
}
input UploadUrlInput {
type: UploadUrlType!
}
input ActivityVisualizationInput {
from: Date
to: Date
}
input WeightLogSummaryInput {
from: Date
to: Date
}
#################
# Types #
#################
type RequestEmailLoginLinkMutationPayload {
errors: [String!]!
}
type LoginWithTokenMutationPayload {
currentUser: User
errors: [String!]!
}
type ResetPasswordMutationPayload {
currentUser: User
errors: [String!]!
}
type RequestResetTokenMutationPayload {
errors: [String!]!
}
type WeightLogVisualizationDataPoint {
day: String!
dayLabel: String!
weight: Int!
weightLabel: String!
}
type WeightLogSummary {
currentWeight: Int
currentWeightLabel: String
dailyAverage: [WeightLogVisualizationDataPoint!]
}
type FoodLogMutationPayload {
errors: [String!]!
logs: FoodLogConnection!
}
type ActivityStats {
personalRecord: ActivityPersonalRecord
lastLog: ActivityLastLog
visualizationData: ActivityVisualizationData!
}
type ActivityLastLog {
logs: [ActivityLog!]!
day: String!
ago: String!
}
type TileMapDataPoint {
day: String!
labelData: JSON!
intensity: Int!
}
type VerifyEmailMutationPayload {
errors: [String!]!
}
type ActivityVisualizationData {
maximumWork(
input: ActivityVisualizationInput
): [ActivityVisualizationWorkDataPoint!]!
averageWork(
input: ActivityVisualizationInput
): [ActivityVisualizationWorkDataPoint!]!
maximumReps(
input: ActivityVisualizationInput
): [ActivityVisualizationRepsDataPoint!]!
averageReps(
input: ActivityVisualizationInput
): [ActivityVisualizationRepsDataPoint!]!
scatterPlot(
input: ActivityVisualizationInput
): [ActivityVisualizationDataPoint!]!
}
type ActivityVisualizationRepsDataPoint {
day: String!
reps: Int!
}
type ActivityVisualizationWorkDataPoint {
day: String!
dayLabel: String!
work: Float!
workLabel: String!
}
type ActivityVisualizationDataPoint {
day: String!
reps: Int!
work: Float!
workLabel: String!
}
type ActivityPersonalRecord {
reps: Int
work: String
ago: String!
link: String!
}
type ActivityLogConnection {
pageInfo: PageInfo!
day: String!
edges: [ActivityLogEdge!]!
}
type ActivityLogEdge {
cursor: String!
node: ActivityLog!
}
type ActivityLog {
id: ID!
reps: Int
work(unit: Unit): String
activity: Activity!
activityId: String!
}
type ActivityLogMutationPayload {
errors: [String!]!
logs: ActivityLogConnection!
}
type ActivityMutationPayload {
errors: [String!]!
activity: Activity
}
type WeightLogMutationPayload {
errors: [String!]!
logs: WeightLogConnection
}
type ActivityConnection {
pageInfo: PageInfo!
edges: [ActivityEdge!]!
}
type ActivityEdge {
cursor: String!
node: Activity!
}
type Activity {
id: ID!
createdAt: Date!
updatedAt: Date!
name: String!
description: String
"Activity's ExRx.net link"
exrx: String
type: ActivityType!
"Muscle groups targeted with this exercise"
muscleGroups: [Muscle!]!
intensity: Int!
logs(day: String): ActivityLogConnection!
stats: ActivityStats!
permissions: GenericObjectPermissions!
}
type GenericObjectPermissions {
edit: Boolean!
delete: Boolean!
}
type Upload {
id: ID!
publicId: String!
entity: String!
entityType: UploadEntityType!
publicUrl(input: UploadUrlInput): String!
}
type UploadMutationPayload {
upload: Upload!
}
type UploadTokenMutationPayload {
tokens: [UploadTokenPayload!]!
errors: [String!]!
}
type UploadTokenPayload {
uploadId: String!
postUrl: String!
signature: String!
publicId: String!
apiKey: String!
timestamp: String!
folder: String!
}
type FoodMeasurementConnection {
pageInfo: PageInfo!
edges: [FoodMeasurementEdge!]!
}
type FoodMeasurementEdge {
cursor: String!
node: FoodMeasurement!
}
type FoodConnection {
pageInfo: PageInfo!
edges: [FoodEdge!]!
}
type FoodEdge {
cursor: String!
node: Food!
}
type FoodMutationPayload {
errors: [String!]
food: Food
}
type LogoutMutationPayload {
expiredTokens: [String!]!
}
type LoginMutationPayload {
token: String!
rememberToken: String!
}
type WeightLogConnection {
day: String!
pageInfo: PageInfo!
edges: [WeightLogEdge!]!
}
type WeightLogEdge {
cursor: String!
node: WeightLog!
}
type WeightLog {
id: ID!
ago: String!
createdAt: Date!
updatedAt: Date!
weight(unit: Unit): Float!
weightString(unit: Unit): String!
}
type FoodLogConnection {
pageInfo: PageInfo!
day: String!
edges: [FoodLogEdge!]!
}
type FoodLogEdge {
cursor: String!
node: FoodLog!
}
type FoodLog {
id: ID!
createdAt: Date!
updatedAt: Date!
description: String!
calories: Int
fat: Int
carbs: Int
protein: Int
food: Food
}
type PageInfo {
totalCount: Int!
hasPreviousPage: Boolean!
hasNextPage: Boolean!
}
type Food {
id: ID!
createdAt: Date!
updatedAt: Date!
name: String!
description: String
measurements: FoodMeasurementConnection!
image: Upload
}
type FoodMeasurement {
id: ID!
createdAt: Date!
updatedAt: Date!
measurement: String!
amount: Float!
calories: Int!
fat: Int!
carbs: Int!
protein: Int!
}
type FoodLogStats {
summary: FoodLogStatSummary!
visualizationData: [FoodLogDataPoint!]!
}
type FoodLogStatSummary {
totalFoodsLogged: Int!
averageDailyCalories: Float!
averageDailyFat: Float!
averageDailyCarbs: Float!
averageDailyProtein: Float!
}
type FoodLogDataPoint {
day: Date!
dayLabel: String!
calories: Float
fat: Float
carbs: Float
protein: Float
}
type UserPreference {
id: ID!
}
type UserPreferencesMutationPayload {
errors: [String!]!
user: User!
}
type UserPreference {
key: UserPreferenceType!
"The JSON.parsed value of the preference"
value: JSON
}