diff --git a/.gitmodules b/.gitmodules index 2049013..00fa7e5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "instructions"] path = instructions url = https://gitea.dsrptlab.com/dsrptlab/instructions +[submodule "graphql-contracts"] + path = graphql-contracts + url = git@gitea.dsrptlab.com:mapflow/mapflow-graphql-contracts.git diff --git a/graphql-contracts b/graphql-contracts new file mode 160000 index 0000000..3340962 --- /dev/null +++ b/graphql-contracts @@ -0,0 +1 @@ +Subproject commit 3340962c024cd33935f8f3669ef86a31ca3e1128 diff --git a/package.json b/package.json index 09de9ca..539762f 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "dev": "node --import tsx ./src/server.ts", "start": "node dist/server.js", "prisma:generate": "prisma generate", - "prisma:migrate:deploy": "prisma migrate deploy" + "prisma:migrate:deploy": "prisma migrate deploy", + "graphql:export-contract": "node --import tsx ./scripts/export-graphql-contract.ts" }, "repository": { "type": "git", diff --git a/scripts/export-graphql-contract.ts b/scripts/export-graphql-contract.ts new file mode 100644 index 0000000..30aaf0c --- /dev/null +++ b/scripts/export-graphql-contract.ts @@ -0,0 +1,10 @@ +import { mkdir, writeFile } from 'node:fs/promises'; +import { dirname, resolve } from 'node:path'; + +import { typeDefs } from '../src/graphql/type-defs.js'; + +const schemaPath = resolve('graphql-contracts/schema.graphql'); +const schema = typeDefs.trim().replace(/^ /gm, ''); + +await mkdir(dirname(schemaPath), { recursive: true }); +await writeFile(schemaPath, `${schema}\n`, 'utf8'); diff --git a/src/graphql/schema.ts b/src/graphql/schema.ts index 4471beb..9ce9792 100644 --- a/src/graphql/schema.ts +++ b/src/graphql/schema.ts @@ -1,4 +1,5 @@ import { GraphQLJSONObject } from './scalars.js'; +import { typeDefs } from './type-defs.js'; import { getOrCreateTelegramLoginUser, getOrCreateTelegramUser, @@ -23,114 +24,7 @@ export type GraphqlContext = { mapflowSessionToken?: string; }; -export const schema = /* GraphQL */ ` - scalar JSON - - enum VoiceExperienceStatus { - UPLOADED - TRANSCRIBING - TRANSCRIBED - ANALYZING - ANALYZED - FAILED - } - - type Place { - id: ID! - googlePlaceId: String! - name: String! - latitude: Float! - longitude: Float! - googlePrimaryType: String - googleTypes: [String!]! - experiences: [VoiceExperience!]! - } - - type User { - id: ID! - telegramId: String! - username: String - firstName: String - lastName: String - photoUrl: String - languageCode: String - isAdmin: Boolean! - } - - type VoiceExperience { - id: ID! - place: Place! - user: User - status: VoiceExperienceStatus! - durationSeconds: Int! - audioObjectKey: String! - transcript: String - analysis: JSON - createdAt: String! - } - - input CreateVoiceExperienceInput { - googlePlaceId: String! - googleName: String! - latitude: Float! - longitude: Float! - durationSeconds: Int! - audioObjectKey: String! - audioContentBase64: String! - audioMimeType: String! - } - - input NearbyPlacesInput { - latitude: Float! - longitude: Float! - radiusMeters: Int! - } - - input AuthenticateTelegramInput { - initData: String! - } - - input AuthenticateTelegramLoginInput { - id: Float! - first_name: String - last_name: String - username: String - photo_url: String - auth_date: Float! - hash: String! - } - - type AuthPayload { - user: User! - } - - type TelegramBotLoginPayload { - token: String! - botUrl: String! - expiresAt: String! - } - - type TelegramBotLoginSession { - sessionToken: String! - user: User! - } - - type Query { - health: String! - me: User! - places: [Place!]! - nearbyPlaces(input: NearbyPlacesInput!): [Place!]! - voiceExperiences: [VoiceExperience!]! - } - - type Mutation { - startTelegramBotLogin: TelegramBotLoginPayload! - completeTelegramBotLogin(token: String!): TelegramBotLoginSession! - authenticateTelegram(input: AuthenticateTelegramInput!): AuthPayload! - authenticateTelegramLogin(input: AuthenticateTelegramLoginInput!): AuthPayload! - createVoiceExperience(input: CreateVoiceExperienceInput!): VoiceExperience! - } -`; +export const schema = typeDefs; export const resolvers = { JSON: GraphQLJSONObject, diff --git a/src/graphql/type-defs.ts b/src/graphql/type-defs.ts new file mode 100644 index 0000000..f30040a --- /dev/null +++ b/src/graphql/type-defs.ts @@ -0,0 +1,108 @@ +export const typeDefs = /* GraphQL */ ` + scalar JSON + + enum VoiceExperienceStatus { + UPLOADED + TRANSCRIBING + TRANSCRIBED + ANALYZING + ANALYZED + FAILED + } + + type Place { + id: ID! + googlePlaceId: String! + name: String! + latitude: Float! + longitude: Float! + googlePrimaryType: String + googleTypes: [String!]! + experiences: [VoiceExperience!]! + } + + type User { + id: ID! + telegramId: String! + username: String + firstName: String + lastName: String + photoUrl: String + languageCode: String + isAdmin: Boolean! + } + + type VoiceExperience { + id: ID! + place: Place! + user: User + status: VoiceExperienceStatus! + durationSeconds: Int! + audioObjectKey: String! + transcript: String + analysis: JSON + createdAt: String! + } + + input CreateVoiceExperienceInput { + googlePlaceId: String! + googleName: String! + latitude: Float! + longitude: Float! + durationSeconds: Int! + audioObjectKey: String! + audioContentBase64: String! + audioMimeType: String! + } + + input NearbyPlacesInput { + latitude: Float! + longitude: Float! + radiusMeters: Int! + } + + input AuthenticateTelegramInput { + initData: String! + } + + input AuthenticateTelegramLoginInput { + id: Float! + first_name: String + last_name: String + username: String + photo_url: String + auth_date: Float! + hash: String! + } + + type AuthPayload { + user: User! + } + + type TelegramBotLoginPayload { + token: String! + botUrl: String! + expiresAt: String! + } + + type TelegramBotLoginSession { + sessionToken: String! + user: User! + } + + type Query { + health: String! + me: User! + places: [Place!]! + nearbyPlaces(input: NearbyPlacesInput!): [Place!]! + voiceExperiences: [VoiceExperience!]! + } + + type Mutation { + startTelegramBotLogin: TelegramBotLoginPayload! + completeTelegramBotLogin(token: String!): TelegramBotLoginSession! + authenticateTelegram(input: AuthenticateTelegramInput!): AuthPayload! + authenticateTelegramLogin(input: AuthenticateTelegramLoginInput!): AuthPayload! + createVoiceExperience(input: CreateVoiceExperienceInput!): VoiceExperience! + } +`;