Merge pool hall camera claim schema onto gql master

Generated files (schema.gql, index.tsx) resolved arbitrarily here; the next
commit regenerates them from the merged backend via just gql.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dean Wenstrand
2026-07-03 17:02:20 -07:00
3 changed files with 1907 additions and 2254 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
fragment PoolHallFields on PoolHall {
id
name
address
latitude
longitude
timezone
status
createdAt
updatedAt
}
fragment PoolHallCameraFields on PoolHallCamera {
id
poolHallId
name
tableLabel
streamPath
status
lastPublishedAt
lastUnpublishedAt
createdAt
updatedAt
}
fragment PoolHallCameraWithHallFields on PoolHallCamera {
...PoolHallCameraFields
poolHall {
...PoolHallFields
}
}
fragment PoolHallCameraStreamCredentialsFields on PoolHallCameraStreamCredentials {
streamKey
rtmpPath
camera {
...PoolHallCameraWithHallFields
}
}
fragment CameraClaimSessionFields on CameraClaimSession {
id
cameraId
userId
challengeCode
status
expiresAt
detectedAt
failedAt
failureReason
createdAt
updatedAt
camera {
...PoolHallCameraWithHallFields
}
}
fragment CameraLeaseFields on CameraLease {
id
cameraId
claimSessionId
userId
videoId
status
startedAt
endedAt
expiresAt
endReason
createdAt
updatedAt
camera {
...PoolHallCameraWithHallFields
}
}
query GetPoolHalls {
poolHalls {
...PoolHallFields
}
}
query GetClaimablePoolHalls {
claimablePoolHalls {
...PoolHallFields
}
}
query GetPoolHallCameras($poolHallId: ID!) {
poolHallCameras(poolHallId: $poolHallId) {
...PoolHallCameraWithHallFields
}
}
query GetClaimableCameras($poolHallId: ID!) {
claimableCameras(poolHallId: $poolHallId) {
...PoolHallCameraWithHallFields
}
}
query GetCameraClaimSession($id: ID!) {
cameraClaimSession(id: $id) {
...CameraClaimSessionFields
}
}
query GetActiveCameraLease {
activeCameraLease {
...CameraLeaseFields
}
}
mutation CreatePoolHall($input: CreatePoolHallInput!) {
createPoolHall(input: $input) {
...PoolHallFields
}
}
mutation UpdatePoolHall($input: UpdatePoolHallInput!) {
updatePoolHall(input: $input) {
...PoolHallFields
}
}
mutation CreatePoolHallCamera($input: CreatePoolHallCameraInput!) {
createPoolHallCamera(input: $input) {
...PoolHallCameraStreamCredentialsFields
}
}
mutation UpdatePoolHallCamera($input: UpdatePoolHallCameraInput!) {
updatePoolHallCamera(input: $input) {
...PoolHallCameraWithHallFields
}
}
mutation RotatePoolHallCameraStreamKey($cameraId: ID!) {
rotatePoolHallCameraStreamKey(cameraId: $cameraId) {
...PoolHallCameraStreamCredentialsFields
}
}
mutation CreateCameraClaimSession($cameraId: ID!) {
createCameraClaimSession(cameraId: $cameraId) {
...CameraClaimSessionFields
}
}
mutation CancelCameraClaimSession($claimSessionId: ID!) {
cancelCameraClaimSession(claimSessionId: $claimSessionId) {
...CameraClaimSessionFields
}
}

View File

@@ -31,16 +31,6 @@ type Query {
limit: Int! = 50 limit: Int! = 50
requiredTags: [String!] = null requiredTags: [String!] = null
): RunLeaderboardGQL! ): RunLeaderboardGQL!
getDrillRunLeaderboard(
drillTag: String!
interval: TimeInterval = null
limit: Int! = 50
tableSizeMin: Float = null
tableSizeMax: Float = null
pocketSizeMin: Float = null
pocketSizeMax: Float = null
): DrillRunLeaderboardGQL!
getMyDrillRuns(drillTag: String!, limit: Int! = 50): [RunGQL!]!
getMakesLeaderboard( getMakesLeaderboard(
interval: TimeInterval = null interval: TimeInterval = null
when: DateTime = null when: DateTime = null
@@ -52,6 +42,12 @@ type Query {
filters: NotificationFilters = null filters: NotificationFilters = null
): NotificationConnection! ): NotificationConnection!
unreadNotificationCount: Int! unreadNotificationCount: Int!
poolHalls: [PoolHall!]!
claimablePoolHalls: [PoolHall!]!
poolHallCameras(poolHallId: ID!): [PoolHallCamera!]!
claimableCameras(poolHallId: ID!): [PoolHallCamera!]!
cameraClaimSession(id: ID!): CameraClaimSession
activeCameraLease: CameraLease
getRuns( getRuns(
filterInput: RunFilterInput! filterInput: RunFilterInput!
runIds: [Int!] = null runIds: [Int!] = null
@@ -66,12 +62,6 @@ type Query {
tableSize: Float = 100 tableSize: Float = 100
useHomography: HomographyInputGQL = null useHomography: HomographyInputGQL = null
): TableStateGQL! ): TableStateGQL!
simulateShot(simulationInput: SimulateShotInputGQL!): ShotProjectionGQL!
computePotAim(
simulationInput: SimulateShotInputGQL!
targetBallId: Int!
pocket: PocketIdentifier!
): PotAimGQL!
getOrderedShots( getOrderedShots(
filterInput: FilterInput! filterInput: FilterInput!
ids: [Int!] = null ids: [Int!] = null
@@ -114,10 +104,7 @@ type Query {
): UserRelationshipsResult! ): UserRelationshipsResult!
getAvailableSubscriptionOptions: StripeSubscriptionOptionsGQL! getAvailableSubscriptionOptions: StripeSubscriptionOptionsGQL!
getUserSubscriptionStatus: UserSubscriptionStatusGQL! getUserSubscriptionStatus: UserSubscriptionStatusGQL!
getResolvedTier: ResolvedTierGQL!
getAppleAppAccountToken: String!
getQuotaStatus: QuotaStatusGQL! getQuotaStatus: QuotaStatusGQL!
getStorageStatus: StorageStatusGQL
getPlayTime(userId: Int!, filters: VideoFilterInput = null): UserPlayTimeGQL! getPlayTime(userId: Int!, filters: VideoFilterInput = null): UserPlayTimeGQL!
getUserVideos( getUserVideos(
userId: Int = null userId: Int = null
@@ -127,8 +114,6 @@ type Query {
): VideoHistoryGQL! ): VideoHistoryGQL!
getUserTags(includeRetiredTags: Boolean = false): [TagGQL!]! getUserTags(includeRetiredTags: Boolean = false): [TagGQL!]!
getGameTypeTagMetrics(input: GameTypeTagMetricsInput!): [GameTypeTagMetric!]! getGameTypeTagMetrics(input: GameTypeTagMetricsInput!): [GameTypeTagMetric!]!
videoExportJob(jobId: Int!): VideoExportJobGQL
myVideoExports(limit: Int! = 30, offset: Int! = 0): [VideoExportJobGQL!]!
getVideo(videoId: Int!, debuggingJson: JSON = null): VideoGQL! getVideo(videoId: Int!, debuggingJson: JSON = null): VideoGQL!
getVideos(videoIds: [Int!]!): [VideoGQL!]! getVideos(videoIds: [Int!]!): [VideoGQL!]!
} }
@@ -366,7 +351,6 @@ type UserGQL {
activeVideoId: Int activeVideoId: Int
stripeCustomerId: String stripeCustomerId: String
profileImageUri: String profileImageUri: String
bio: String
createdAt: DateTime createdAt: DateTime
updatedAt: DateTime updatedAt: DateTime
videosPrivateByDefault: Boolean videosPrivateByDefault: Boolean
@@ -540,7 +524,6 @@ type UploadStreamGQL {
initPlaylistUploadStatus: InitPlaylistUploadStatusEnum initPlaylistUploadStatus: InitPlaylistUploadStatusEnum
lowestUnuploadedSegmentIndex: Int! lowestUnuploadedSegmentIndex: Int!
uploadCompletionCursor: Int! uploadCompletionCursor: Int!
lastSegmentUploadedAt: DateTime
errors: [StreamErrorGQL!]! errors: [StreamErrorGQL!]!
createdAt: DateTime! createdAt: DateTime!
updatedAt: DateTime! updatedAt: DateTime!
@@ -700,18 +683,10 @@ type PlayerSummaryGQL {
makePercentage: Float! makePercentage: Float!
score: Int score: Int
longestRun: Int! longestRun: Int!
runLengths: [Int!]!
spinTypeBreakdown: SpinTypeBreakdownGQL!
averageDifficulty: Float averageDifficulty: Float
averageTimeBetweenShots: Float averageTimeBetweenShots: Float
} }
type SpinTypeBreakdownGQL {
draw: Int!
center: Int!
follow: Int!
}
type DeployedConfigGQL { type DeployedConfigGQL {
allowNewUsers: Boolean! allowNewUsers: Boolean!
firebase: Boolean! firebase: Boolean!
@@ -720,8 +695,6 @@ type DeployedConfigGQL {
minimumAllowedAppVersion: String! minimumAllowedAppVersion: String!
subscriptionGatingEnabled: Boolean! subscriptionGatingEnabled: Boolean!
quotaEnforcementEnabled: Boolean! quotaEnforcementEnabled: Boolean!
storageLimitEnforcementEnabled: Boolean!
capabilityEnforcementEnabled: Boolean!
bannerMessages: [BannerGQL!]! bannerMessages: [BannerGQL!]!
defaultAndroidRecordingFormat: StreamSegmentTypeEnum! defaultAndroidRecordingFormat: StreamSegmentTypeEnum!
bucketUrl: String! bucketUrl: String!
@@ -746,7 +719,6 @@ type VideoHistoryGQL {
videos: [VideoGQL!]! videos: [VideoGQL!]!
pageInfo: PageInfoGQL! pageInfo: PageInfoGQL!
hasFollowing: Boolean! hasFollowing: Boolean!
followingCount: Int!
} }
type PageInfoGQL { type PageInfoGQL {
@@ -783,13 +755,6 @@ type RunLeaderboardGQL {
entries: [RunGQL!]! entries: [RunGQL!]!
} }
type DrillRunLeaderboardGQL {
entries: [RunGQL!]!
youRun: RunGQL
youRank: Int
totalPlayers: Int!
}
type CountLeaderboardGQL { type CountLeaderboardGQL {
entries: [UserShotCountEntry!]! entries: [UserShotCountEntry!]!
} }
@@ -874,7 +839,6 @@ enum NotificationTypeEnum {
REACTION REACTION
FOLLOW FOLLOW
CHALLENGE_INVITE CHALLENGE_INVITE
EXPORT_READY
} }
input NotificationFilters { input NotificationFilters {
@@ -882,6 +846,63 @@ input NotificationFilters {
notificationTypes: [NotificationTypeEnum!] = null notificationTypes: [NotificationTypeEnum!] = null
} }
type PoolHall {
id: ID!
name: String!
address: String
latitude: Float
longitude: Float
timezone: String
status: String!
createdAt: DateTime!
updatedAt: DateTime!
}
type PoolHallCamera {
id: ID!
poolHallId: ID!
name: String!
tableLabel: String
streamPath: String!
status: String!
lastPublishedAt: DateTime
lastUnpublishedAt: DateTime
createdAt: DateTime!
updatedAt: DateTime!
poolHall: PoolHall!
}
type CameraClaimSession {
id: ID!
cameraId: ID!
userId: ID!
challengeCode: String!
status: String!
expiresAt: DateTime!
detectedAt: DateTime
failedAt: DateTime
failureReason: String
createdAt: DateTime!
updatedAt: DateTime!
camera: PoolHallCamera!
}
type CameraLease {
id: ID!
cameraId: ID!
claimSessionId: ID
userId: ID!
videoId: ID
status: String!
startedAt: DateTime!
endedAt: DateTime
expiresAt: DateTime
endReason: String
createdAt: DateTime!
updatedAt: DateTime!
camera: PoolHallCamera!
}
type GetRunsResult { type GetRunsResult {
runs: [RunGQL!]! runs: [RunGQL!]!
count: Int count: Int
@@ -977,76 +998,6 @@ input IntPoint2DInput {
y: Int! y: Int!
} }
type ShotProjectionGQL {
trajectories: [BallTrajectoryGQL!]!
events: [SimulationEventGQL!]!
finalState: [SimulationBallStateGQL!]!
pottedBallIds: [Int!]!
}
type BallTrajectoryGQL {
ballId: Int!
points: [TrajectoryPointGQL!]!
}
type TrajectoryPointGQL {
time: Float!
position: [Float!]!
}
type SimulationEventGQL {
eventType: SimulationEventType!
time: Float!
ballIds: [Int!]!
position: [Float!]
}
enum SimulationEventType {
STICK_BALL
BALL_BALL
BALL_CUSHION
BALL_POCKET
BALL_STOP
}
type SimulationBallStateGQL {
ballId: Int!
position: [Float!]!
}
input SimulateShotInputGQL {
cueBallId: Int!
strike: CueStrikeInputGQL!
balls: [SimulationBallStateInputGQL!] = null
b64Image: String = null
useHomography: HomographyInputGQL = null
tableSize: Float = null
}
input CueStrikeInputGQL {
v0: Float!
phi: Float!
theta: Float! = 0
a: Float! = 0
b: Float! = 0
}
input SimulationBallStateInputGQL {
ballId: Int!
position: [Float!]!
}
type PotAimGQL {
phi: Float!
geometricPhi: Float!
cutAngle: Float!
requiredPrecision: Float!
feasible: Boolean!
potted: Boolean!
converged: Boolean!
occludingBallIds: [Int!]!
}
type GetShotsResult { type GetShotsResult {
shots: [ShotGQL!]! shots: [ShotGQL!]!
count: Int count: Int
@@ -1095,7 +1046,6 @@ type UserRelationship {
type StripeSubscriptionOptionsGQL { type StripeSubscriptionOptionsGQL {
products: [StripeProductGQL!]! products: [StripeProductGQL!]!
trialPeriodDays: Int trialPeriodDays: Int
appleIap: AppleIapSubscriptionOptionsGQL!
} }
type StripeProductGQL { type StripeProductGQL {
@@ -1116,12 +1066,6 @@ type StripePriceGQL {
active: Boolean! active: Boolean!
} }
type AppleIapSubscriptionOptionsGQL {
enabled: Boolean!
proMonthlyProductId: String
productIds: [String!]!
}
type UserSubscriptionStatusGQL { type UserSubscriptionStatusGQL {
hasActiveSubscription: Boolean! hasActiveSubscription: Boolean!
entitlementSource: EntitlementSourceTypeEnum entitlementSource: EntitlementSourceTypeEnum
@@ -1139,7 +1083,6 @@ enum EntitlementSourceTypeEnum {
ADMIN ADMIN
MANUAL MANUAL
STRIPE STRIPE
APPLE
ALPHA_LEGACY ALPHA_LEGACY
} }
@@ -1154,17 +1097,6 @@ enum StripeSubscriptionStatusEnum {
PAUSED PAUSED
} }
type ResolvedTierGQL {
tierName: String!
tierDisplayName: String!
hasActiveSubscription: Boolean!
entitlementSource: EntitlementSourceTypeEnum
entitlementStatus: String
entitlementStartsAt: DateTime
entitlementEndsAt: DateTime
capabilities: [String!]!
}
type QuotaStatusGQL { type QuotaStatusGQL {
tierName: String! tierName: String!
periodStart: DateTime! periodStart: DateTime!
@@ -1189,27 +1121,6 @@ type QuotaBucketStatusGQL {
canUpload: Boolean! canUpload: Boolean!
} }
type StorageStatusGQL {
userId: Int!
tierName: String!
retainedStorageUsedBytes: BigInt!
retainedStorageLimitBytes: BigInt
isUnlimited: Boolean!
policyConfigured: Boolean!
remainingStorageBytes: BigInt
storageUsageRatio: Float
isNearLimit: Boolean!
isOverLimit: Boolean!
usageCalculated: Boolean!
usageSource: String
lastCalculatedAt: DateTime
}
"""
Integer value that can exceed GraphQL Int's 32-bit range.
"""
scalar BigInt
type UserPlayTimeGQL { type UserPlayTimeGQL {
totalSeconds: Float! totalSeconds: Float!
} }
@@ -1245,36 +1156,6 @@ input GameTypeTagMetricsInput {
includePrivate: IncludePrivateEnum! = MINE includePrivate: IncludePrivateEnum! = MINE
} }
type VideoExportJobGQL {
id: Int!
videoId: Int!
mode: VideoExportModeEnum!
status: VideoExportStatusEnum!
videoName: String
videoThumbnailUri: String
shotIds: [Int!]
runId: Int
downloadUrl: String
fileSizeBytes: Int
expiresAt: DateTime
createdAt: DateTime
}
enum VideoExportModeEnum {
FULL_SESSION
SHOTS
RUN
}
enum VideoExportStatusEnum {
CREATED
QUEUED
RUNNING
SUCCEEDED
FAILED
EXPIRED
}
""" """
The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf).
""" """
@@ -1331,6 +1212,15 @@ type Mutation {
markAllNotificationsAsRead: Boolean! markAllNotificationsAsRead: Boolean!
markNotificationsAsRead(notificationIds: [Int!]!): Boolean! markNotificationsAsRead(notificationIds: [Int!]!): Boolean!
deleteNotification(notificationId: Int!): Boolean! deleteNotification(notificationId: Int!): Boolean!
createPoolHall(input: CreatePoolHallInput!): PoolHall!
updatePoolHall(input: UpdatePoolHallInput!): PoolHall!
createPoolHallCamera(
input: CreatePoolHallCameraInput!
): PoolHallCameraStreamCredentials!
updatePoolHallCamera(input: UpdatePoolHallCameraInput!): PoolHallCamera!
rotatePoolHallCameraStreamKey(cameraId: ID!): PoolHallCameraStreamCredentials!
createCameraClaimSession(cameraId: ID!): CameraClaimSession!
cancelCameraClaimSession(claimSessionId: ID!): CameraClaimSession!
finalizePlayerAssignments( finalizePlayerAssignments(
input: FinalizePlayerAssignmentsInput! input: FinalizePlayerAssignmentsInput!
): [PlayerClusterGQL!]! ): [PlayerClusterGQL!]!
@@ -1357,9 +1247,6 @@ type Mutation {
retireTags(tagIds: [Int!]!): Boolean! retireTags(tagIds: [Int!]!): Boolean!
ensureStripeCustomerExists: UserGQL! ensureStripeCustomerExists: UserGQL!
deleteUser: Boolean! deleteUser: Boolean!
syncAppleSubscription(
input: SyncAppleSubscriptionInputGQL!
): SyncAppleSubscriptionResultGQL!
createSubscription(priceId: String!): CreateSubscriptionResultGQL! createSubscription(priceId: String!): CreateSubscriptionResultGQL!
createCustomerPortalSession: CreateCustomerPortalSessionResultGQL! createCustomerPortalSession: CreateCustomerPortalSessionResultGQL!
cancelSubscription: UserSubscriptionStatusGQL! cancelSubscription: UserSubscriptionStatusGQL!
@@ -1376,8 +1263,6 @@ type Mutation {
feedback: String = null feedback: String = null
metadata: CancellationFeedbackMetadataInput = null metadata: CancellationFeedbackMetadataInput = null
): Boolean! ): Boolean!
requestVideoExport(input: RequestVideoExportInput!): VideoExportJobGQL!
dismissVideoExport(jobId: Int!): Boolean!
findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL
createUploadStream( createUploadStream(
videoMetadata: VideoMetadataInput! videoMetadata: VideoMetadataInput!
@@ -1410,6 +1295,44 @@ enum ReportReasonEnum {
OTHER OTHER
} }
input CreatePoolHallInput {
name: String!
address: String = null
latitude: Float = null
longitude: Float = null
timezone: String = null
}
input UpdatePoolHallInput {
id: ID!
name: String = null
address: String = null
latitude: Float = null
longitude: Float = null
timezone: String = null
status: String = null
}
type PoolHallCameraStreamCredentials {
camera: PoolHallCamera!
streamKey: String!
rtmpPath: String!
}
input CreatePoolHallCameraInput {
poolHallId: ID!
name: String!
tableLabel: String = null
streamPath: String = null
}
input UpdatePoolHallCameraInput {
id: ID!
name: String = null
tableLabel: String = null
status: String = null
}
input FinalizePlayerAssignmentsInput { input FinalizePlayerAssignmentsInput {
videoId: Int! videoId: Int!
clusterAssignments: [ClusterAssignmentInput!]! = [] clusterAssignments: [ClusterAssignmentInput!]! = []
@@ -1513,27 +1436,6 @@ input EditUserInputGQL {
fargoRating: Int = null fargoRating: Int = null
videosPrivateByDefault: Boolean = null videosPrivateByDefault: Boolean = null
agreesToMarketing: Boolean = null agreesToMarketing: Boolean = null
bio: String = null
}
type SyncAppleSubscriptionResultGQL {
ok: Boolean!
errorCode: String
errorMessage: String
hasActiveSubscription: Boolean!
entitlementSource: EntitlementSourceTypeEnum
entitlementStartsAt: DateTime
entitlementEndsAt: DateTime
appleStatus: Int
originalTransactionId: String
latestTransactionId: String
productId: String
expiresAt: DateTime
}
input SyncAppleSubscriptionInputGQL {
signedTransactionInfo: String!
signedRenewalInfo: String = null
} }
type CreateSubscriptionResultGQL { type CreateSubscriptionResultGQL {
@@ -1560,13 +1462,6 @@ input CancellationFeedbackMetadataInput {
platform: String = null platform: String = null
} }
input RequestVideoExportInput {
videoId: Int!
mode: VideoExportModeEnum!
shotIds: [Int!] = null
runId: Int = null
}
type CreateUploadStreamReturn { type CreateUploadStreamReturn {
videoId: Int! videoId: Int!
} }
@@ -1606,10 +1501,10 @@ type GetUploadLinkReturn {
union UploadLinkGetUploadLinkErrors = UploadLink | GetUploadLinkErrors union UploadLinkGetUploadLinkErrors = UploadLink | GetUploadLinkErrors
type GetUploadLinkErrors { type GetUploadLinkErrors {
error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr! error: MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr!
} }
union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErrStorageLimitExceededErr = union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr =
MustHaveSetForUploadLinkErr MustHaveSetForUploadLinkErr
| SegmentAlreadyUploadedErr | SegmentAlreadyUploadedErr
| ProcessingFailedErr | ProcessingFailedErr
@@ -1617,7 +1512,6 @@ union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoI
| TooManyProfileImageUploadsErr | TooManyProfileImageUploadsErr
| InitUploadAlreadyCompletedErr | InitUploadAlreadyCompletedErr
| TooManyInitUploadsErr | TooManyInitUploadsErr
| StorageLimitExceededErr
type MustHaveSetForUploadLinkErr { type MustHaveSetForUploadLinkErr {
resolution: Boolean resolution: Boolean
@@ -1643,11 +1537,3 @@ type InitUploadAlreadyCompletedErr {
type TooManyInitUploadsErr { type TooManyInitUploadsErr {
linksRequested: Int! linksRequested: Int!
} }
type StorageLimitExceededErr {
reason: String!
tierName: String!
retainedStorageUsedBytes: BigInt!
retainedStorageLimitBytes: BigInt
remainingStorageBytes: BigInt
}