Initial backend service
This commit is contained in:
4
.env.example
Normal file
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
DATABASE_URL=postgresql://mapflow:mapflow@localhost:5432/mapflow
|
||||
HATCHET_CLIENT_TOKEN=
|
||||
HOST=0.0.0.0
|
||||
PORT=4000
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.env
|
||||
.DS_Store
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "instructions"]
|
||||
path = instructions
|
||||
url = https://gitea.dsrptlab.com/dsrptlab/instructions
|
||||
6
README.md
Normal file
6
README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# MapFlow Backend
|
||||
|
||||
Fastify + Mercurius GraphQL API for MapFlow.
|
||||
|
||||
The backend accepts a user's voice experience, stores a durable record, and
|
||||
enqueues the Hatchet workflow that will transcribe and analyze it.
|
||||
14
graphql/operations/create_voice_experience.graphql
Normal file
14
graphql/operations/create_voice_experience.graphql
Normal file
@@ -0,0 +1,14 @@
|
||||
mutation CreateVoiceExperience($input: CreateVoiceExperienceInput!) {
|
||||
createVoiceExperience(input: $input) {
|
||||
id
|
||||
status
|
||||
durationSeconds
|
||||
place {
|
||||
id
|
||||
googlePlaceId
|
||||
name
|
||||
latitude
|
||||
longitude
|
||||
}
|
||||
}
|
||||
}
|
||||
1
instructions
Submodule
1
instructions
Submodule
Submodule instructions added at 1a85fbbea6
1
instructions.md
Symbolic link
1
instructions.md
Symbolic link
@@ -0,0 +1 @@
|
||||
instructions/instructions.md
|
||||
5474
package-lock.json
generated
Normal file
5474
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
package.json
Normal file
38
package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "mapflow-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Fastify + Mercurius GraphQL backend for MapFlow.",
|
||||
"type": "module",
|
||||
"main": "dist/server.js",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"check": "tsc --noEmit",
|
||||
"dev": "node --import tsx ./src/server.ts",
|
||||
"start": "node dist/server.js",
|
||||
"prisma:generate": "prisma generate",
|
||||
"prisma:migrate:deploy": "prisma migrate deploy"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@gitea.dsrptlab.com:mapflow/backend.git"
|
||||
},
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@hatchet-dev/typescript-sdk": "^1.22.0",
|
||||
"@prisma/adapter-pg": "^7.8.0",
|
||||
"@prisma/client": "^7.8.0",
|
||||
"dotenv": "^17.4.2",
|
||||
"fastify": "^5.8.5",
|
||||
"graphql": "^16.13.2",
|
||||
"mercurius": "^16.9.0",
|
||||
"pg": "^8.20.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/pg": "^8.20.0",
|
||||
"prisma": "^7.8.0",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^6.0.3"
|
||||
}
|
||||
}
|
||||
9
prisma.config.ts
Normal file
9
prisma.config.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import 'dotenv/config';
|
||||
import { defineConfig, env } from 'prisma/config';
|
||||
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
});
|
||||
41
prisma/schema.prisma
Normal file
41
prisma/schema.prisma
Normal file
@@ -0,0 +1,41 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../src/generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
enum VoiceExperienceStatus {
|
||||
UPLOADED
|
||||
TRANSCRIBING
|
||||
TRANSCRIBED
|
||||
ANALYZING
|
||||
ANALYZED
|
||||
FAILED
|
||||
}
|
||||
|
||||
model Place {
|
||||
id String @id @default(cuid())
|
||||
googlePlaceId String @unique
|
||||
name String
|
||||
latitude Float
|
||||
longitude Float
|
||||
experiences VoiceExperience[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model VoiceExperience {
|
||||
id String @id @default(cuid())
|
||||
placeId String
|
||||
place Place @relation(fields: [placeId], references: [id])
|
||||
durationSeconds Int
|
||||
audioObjectKey String
|
||||
status VoiceExperienceStatus @default(UPLOADED)
|
||||
transcript String?
|
||||
analysis Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
8
src/config.ts
Normal file
8
src/config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import 'dotenv/config';
|
||||
|
||||
export const config = {
|
||||
host: process.env.HOST ?? '0.0.0.0',
|
||||
port: Number(process.env.PORT ?? '4000'),
|
||||
databaseUrl: process.env.DATABASE_URL ?? '',
|
||||
hatchetToken: process.env.HATCHET_CLIENT_TOKEN ?? '',
|
||||
};
|
||||
1
src/generated/prisma/client.d.ts
vendored
Normal file
1
src/generated/prisma/client.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./index"
|
||||
5
src/generated/prisma/client.js
Normal file
5
src/generated/prisma/client.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
module.exports = { ...require('.') }
|
||||
1
src/generated/prisma/default.d.ts
vendored
Normal file
1
src/generated/prisma/default.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./index"
|
||||
5
src/generated/prisma/default.js
Normal file
5
src/generated/prisma/default.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
module.exports = { ...require('#main-entry-point') }
|
||||
1
src/generated/prisma/edge.d.ts
vendored
Normal file
1
src/generated/prisma/edge.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./default"
|
||||
187
src/generated/prisma/edge.js
Normal file
187
src/generated/prisma/edge.js
Normal file
File diff suppressed because one or more lines are too long
213
src/generated/prisma/index-browser.js
Normal file
213
src/generated/prisma/index-browser.js
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
|
||||
const {
|
||||
Decimal,
|
||||
DbNull,
|
||||
JsonNull,
|
||||
AnyNull,
|
||||
NullTypes,
|
||||
makeStrictEnum,
|
||||
Public,
|
||||
getRuntime,
|
||||
skip
|
||||
} = require('./runtime/index-browser.js')
|
||||
|
||||
|
||||
const Prisma = {}
|
||||
|
||||
exports.Prisma = Prisma
|
||||
exports.$Enums = {}
|
||||
|
||||
/**
|
||||
* Prisma Client JS version: 7.8.0
|
||||
* Query Engine version: 3c6e192761c0362d496ed980de936e2f3cebcd3a
|
||||
*/
|
||||
Prisma.prismaVersion = {
|
||||
client: "7.8.0",
|
||||
engine: "3c6e192761c0362d496ed980de936e2f3cebcd3a"
|
||||
}
|
||||
|
||||
Prisma.PrismaClientKnownRequestError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientKnownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)};
|
||||
Prisma.PrismaClientUnknownRequestError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientUnknownRequestError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.PrismaClientRustPanicError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientRustPanicError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.PrismaClientInitializationError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientInitializationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.PrismaClientValidationError = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`PrismaClientValidationError is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.Decimal = Decimal
|
||||
|
||||
/**
|
||||
* Re-export of sql-template-tag
|
||||
*/
|
||||
Prisma.sql = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`sqltag is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.empty = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`empty is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.join = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`join is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.raw = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`raw is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.validator = Public.validator
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*/
|
||||
Prisma.getExtensionContext = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`Extensions.getExtensionContext is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
Prisma.defineExtension = () => {
|
||||
const runtimeName = getRuntime().prettyName;
|
||||
throw new Error(`Extensions.defineExtension is unable to run in this browser environment, or has been bundled for the browser (running in ${runtimeName}).
|
||||
In case this error is unexpected for you, please report it in https://pris.ly/prisma-prisma-bug-report`,
|
||||
)}
|
||||
|
||||
/**
|
||||
* Shorthand utilities for JSON filtering
|
||||
*/
|
||||
Prisma.DbNull = DbNull
|
||||
Prisma.JsonNull = JsonNull
|
||||
Prisma.AnyNull = AnyNull
|
||||
|
||||
Prisma.NullTypes = NullTypes
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enums
|
||||
*/
|
||||
|
||||
exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
|
||||
ReadUncommitted: 'ReadUncommitted',
|
||||
ReadCommitted: 'ReadCommitted',
|
||||
RepeatableRead: 'RepeatableRead',
|
||||
Serializable: 'Serializable'
|
||||
});
|
||||
|
||||
exports.Prisma.PlaceScalarFieldEnum = {
|
||||
id: 'id',
|
||||
googlePlaceId: 'googlePlaceId',
|
||||
name: 'name',
|
||||
latitude: 'latitude',
|
||||
longitude: 'longitude',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.VoiceExperienceScalarFieldEnum = {
|
||||
id: 'id',
|
||||
placeId: 'placeId',
|
||||
durationSeconds: 'durationSeconds',
|
||||
audioObjectKey: 'audioObjectKey',
|
||||
status: 'status',
|
||||
transcript: 'transcript',
|
||||
analysis: 'analysis',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
};
|
||||
|
||||
exports.Prisma.SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
};
|
||||
|
||||
exports.Prisma.NullableJsonNullValueInput = {
|
||||
DbNull: Prisma.DbNull,
|
||||
JsonNull: Prisma.JsonNull
|
||||
};
|
||||
|
||||
exports.Prisma.QueryMode = {
|
||||
default: 'default',
|
||||
insensitive: 'insensitive'
|
||||
};
|
||||
|
||||
exports.Prisma.JsonNullValueFilter = {
|
||||
DbNull: Prisma.DbNull,
|
||||
JsonNull: Prisma.JsonNull,
|
||||
AnyNull: Prisma.AnyNull
|
||||
};
|
||||
|
||||
exports.Prisma.NullsOrder = {
|
||||
first: 'first',
|
||||
last: 'last'
|
||||
};
|
||||
exports.VoiceExperienceStatus = exports.$Enums.VoiceExperienceStatus = {
|
||||
UPLOADED: 'UPLOADED',
|
||||
TRANSCRIBING: 'TRANSCRIBING',
|
||||
TRANSCRIBED: 'TRANSCRIBED',
|
||||
ANALYZING: 'ANALYZING',
|
||||
ANALYZED: 'ANALYZED',
|
||||
FAILED: 'FAILED'
|
||||
};
|
||||
|
||||
exports.Prisma.ModelName = {
|
||||
Place: 'Place',
|
||||
VoiceExperience: 'VoiceExperience'
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a stub Prisma Client that will error at runtime if called.
|
||||
*/
|
||||
class PrismaClient {
|
||||
constructor() {
|
||||
return new Proxy(this, {
|
||||
get(target, prop) {
|
||||
let message
|
||||
const runtime = getRuntime()
|
||||
if (runtime.isEdge) {
|
||||
message = `PrismaClient is not configured to run in ${runtime.prettyName}. In order to run Prisma Client on edge runtime, either:
|
||||
- Use Prisma Accelerate: https://pris.ly/d/accelerate
|
||||
- Use Driver Adapters: https://pris.ly/d/driver-adapters
|
||||
`;
|
||||
} else {
|
||||
message = 'PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running in `' + runtime.prettyName + '`).'
|
||||
}
|
||||
|
||||
message += `
|
||||
If this is unexpected, please open an issue: https://pris.ly/prisma-prisma-bug-report`
|
||||
|
||||
throw new Error(message)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exports.PrismaClient = PrismaClient
|
||||
|
||||
Object.assign(exports, Prisma)
|
||||
4541
src/generated/prisma/index.d.ts
vendored
Normal file
4541
src/generated/prisma/index.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
187
src/generated/prisma/index.js
Normal file
187
src/generated/prisma/index.js
Normal file
File diff suppressed because one or more lines are too long
144
src/generated/prisma/package.json
Normal file
144
src/generated/prisma/package.json
Normal file
@@ -0,0 +1,144 @@
|
||||
{
|
||||
"name": "prisma-client-5316d8e66293a4954be6e26169692366997bf25fe9186e98c87e62eed3dc691e",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"browser": "default.js",
|
||||
"exports": {
|
||||
"./client": {
|
||||
"require": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./edge.js",
|
||||
"workerd": "./edge.js",
|
||||
"worker": "./edge.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"import": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./edge.js",
|
||||
"workerd": "./edge.js",
|
||||
"worker": "./edge.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"require": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./edge.js",
|
||||
"workerd": "./edge.js",
|
||||
"worker": "./edge.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"import": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./edge.js",
|
||||
"workerd": "./edge.js",
|
||||
"worker": "./edge.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./extension": {
|
||||
"types": "./extension.d.ts",
|
||||
"require": "./extension.js",
|
||||
"import": "./extension.js",
|
||||
"default": "./extension.js"
|
||||
},
|
||||
"./index-browser": {
|
||||
"types": "./index.d.ts",
|
||||
"require": "./index-browser.js",
|
||||
"import": "./index-browser.js",
|
||||
"default": "./index-browser.js"
|
||||
},
|
||||
"./index": {
|
||||
"types": "./index.d.ts",
|
||||
"require": "./index.js",
|
||||
"import": "./index.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./edge": {
|
||||
"types": "./edge.d.ts",
|
||||
"require": "./edge.js",
|
||||
"import": "./edge.js",
|
||||
"default": "./edge.js"
|
||||
},
|
||||
"./runtime/client": {
|
||||
"types": "./runtime/client.d.ts",
|
||||
"node": {
|
||||
"require": "./runtime/client.js",
|
||||
"default": "./runtime/client.js"
|
||||
},
|
||||
"require": "./runtime/client.js",
|
||||
"import": "./runtime/client.mjs",
|
||||
"default": "./runtime/client.mjs"
|
||||
},
|
||||
"./runtime/wasm-compiler-edge": {
|
||||
"types": "./runtime/wasm-compiler-edge.d.ts",
|
||||
"require": "./runtime/wasm-compiler-edge.js",
|
||||
"import": "./runtime/wasm-compiler-edge.mjs",
|
||||
"default": "./runtime/wasm-compiler-edge.mjs"
|
||||
},
|
||||
"./runtime/index-browser": {
|
||||
"types": "./runtime/index-browser.d.ts",
|
||||
"require": "./runtime/index-browser.js",
|
||||
"import": "./runtime/index-browser.mjs",
|
||||
"default": "./runtime/index-browser.mjs"
|
||||
},
|
||||
"./generator-build": {
|
||||
"require": "./generator-build/index.js",
|
||||
"import": "./generator-build/index.js",
|
||||
"default": "./generator-build/index.js"
|
||||
},
|
||||
"./sql": {
|
||||
"require": {
|
||||
"types": "./sql.d.ts",
|
||||
"node": "./sql.js",
|
||||
"default": "./sql.js"
|
||||
},
|
||||
"import": {
|
||||
"types": "./sql.d.ts",
|
||||
"node": "./sql.mjs",
|
||||
"default": "./sql.mjs"
|
||||
},
|
||||
"default": "./sql.js"
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"version": "7.8.0",
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@prisma/client-runtime-utils": "7.8.0"
|
||||
},
|
||||
"imports": {
|
||||
"#wasm-compiler-loader": {
|
||||
"edge-light": "./wasm-edge-light-loader.mjs",
|
||||
"workerd": "./wasm-worker-loader.mjs",
|
||||
"worker": "./wasm-worker-loader.mjs",
|
||||
"default": "./wasm-worker-loader.mjs"
|
||||
},
|
||||
"#main-entry-point": {
|
||||
"require": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./edge.js",
|
||||
"workerd": "./edge.js",
|
||||
"worker": "./edge.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"import": {
|
||||
"node": "./index.js",
|
||||
"edge-light": "./edge.js",
|
||||
"workerd": "./edge.js",
|
||||
"worker": "./edge.js",
|
||||
"browser": "./index-browser.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"default": "./index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
2
src/generated/prisma/query_compiler_fast_bg.js
Normal file
2
src/generated/prisma/query_compiler_fast_bg.js
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";var h=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var j=Object.prototype.hasOwnProperty;var D=(e,t)=>{for(var n in t)h(e,n,{get:t[n],enumerable:!0})},O=(e,t,n,_)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of M(t))!j.call(e,r)&&r!==n&&h(e,r,{get:()=>t[r],enumerable:!(_=T(t,r))||_.enumerable});return e};var B=e=>O(h({},"__esModule",{value:!0}),e);var xe={};D(xe,{QueryCompiler:()=>F,__wbg_Error_e83987f665cf5504:()=>q,__wbg_Number_bb48ca12f395cd08:()=>C,__wbg_String_8f0eb39a4a4c2f66:()=>k,__wbg___wbindgen_boolean_get_6d5a1ee65bab5f68:()=>W,__wbg___wbindgen_debug_string_df47ffb5e35e6763:()=>V,__wbg___wbindgen_in_bb933bd9e1b3bc0f:()=>z,__wbg___wbindgen_is_object_c818261d21f283a4:()=>L,__wbg___wbindgen_is_string_fbb76cb2940daafd:()=>P,__wbg___wbindgen_is_undefined_2d472862bd29a478:()=>Q,__wbg___wbindgen_jsval_loose_eq_b664b38a2f582147:()=>Y,__wbg___wbindgen_number_get_a20bf9b85341449d:()=>G,__wbg___wbindgen_string_get_e4f06c90489ad01b:()=>J,__wbg___wbindgen_throw_b855445ff6a94295:()=>X,__wbg_entries_e171b586f8f6bdbf:()=>H,__wbg_getTime_14776bfb48a1bff9:()=>K,__wbg_get_7bed016f185add81:()=>Z,__wbg_get_with_ref_key_1dc361bd10053bfe:()=>v,__wbg_instanceof_ArrayBuffer_70beb1189ca63b38:()=>ee,__wbg_instanceof_Uint8Array_20c8e73002f7af98:()=>te,__wbg_isSafeInteger_d216eda7911dde36:()=>ne,__wbg_length_69bca3cb64fc8748:()=>re,__wbg_length_cdd215e10d9dd507:()=>_e,__wbg_new_0_f9740686d739025c:()=>oe,__wbg_new_1acc0b6eea89d040:()=>ce,__wbg_new_5a79be3ab53b8aa5:()=>ie,__wbg_new_68651c719dcda04e:()=>se,__wbg_new_e17d9f43105b08be:()=>ue,__wbg_prototypesetcall_2a6620b6922694b2:()=>fe,__wbg_set_3f1d0b984ed272ed:()=>be,__wbg_set_907fb406c34a251d:()=>de,__wbg_set_c213c871859d6500:()=>ae,__wbg_set_message_82ae475bb413aa5c:()=>ge,__wbg_set_wasm:()=>N,__wbindgen_cast_2241b6af4c4b2941:()=>le,__wbindgen_cast_4625c577ab2ec9ee:()=>we,__wbindgen_cast_9ae0607507abb057:()=>pe,__wbindgen_cast_d6cd19b81560fd6e:()=>ye,__wbindgen_init_externref_table:()=>me});module.exports=B(xe);var A=()=>{};A.prototype=A;let o;function N(e){o=e}let p=null;function a(){return(p===null||p.byteLength===0)&&(p=new Uint8Array(o.memory.buffer)),p}let y=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});y.decode();const U=2146435072;let S=0;function R(e,t){return S+=t,S>=U&&(y=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),y.decode(),S=t),y.decode(a().subarray(e,e+t))}function m(e,t){return e=e>>>0,R(e,t)}let f=0;const g=new TextEncoder;"encodeInto"in g||(g.encodeInto=function(e,t){const n=g.encode(e);return t.set(n),{read:e.length,written:n.length}});function l(e,t,n){if(n===void 0){const i=g.encode(e),d=t(i.length,1)>>>0;return a().subarray(d,d+i.length).set(i),f=i.length,d}let _=e.length,r=t(_,1)>>>0;const s=a();let c=0;for(;c<_;c++){const i=e.charCodeAt(c);if(i>127)break;s[r+c]=i}if(c!==_){c!==0&&(e=e.slice(c)),r=n(r,_,_=c+e.length*3,1)>>>0;const i=a().subarray(r+c,r+_),d=g.encodeInto(e,i);c+=d.written,r=n(r,_,c,1)>>>0}return f=c,r}let b=null;function u(){return(b===null||b.buffer.detached===!0||b.buffer.detached===void 0&&b.buffer!==o.memory.buffer)&&(b=new DataView(o.memory.buffer)),b}function x(e){return e==null}function I(e){const t=typeof e;if(t=="number"||t=="boolean"||e==null)return`${e}`;if(t=="string")return`"${e}"`;if(t=="symbol"){const r=e.description;return r==null?"Symbol":`Symbol(${r})`}if(t=="function"){const r=e.name;return typeof r=="string"&&r.length>0?`Function(${r})`:"Function"}if(Array.isArray(e)){const r=e.length;let s="[";r>0&&(s+=I(e[0]));for(let c=1;c<r;c++)s+=", "+I(e[c]);return s+="]",s}const n=/\[object ([^\]]+)\]/.exec(toString.call(e));let _;if(n&&n.length>1)_=n[1];else return toString.call(e);if(_=="Object")try{return"Object("+JSON.stringify(e)+")"}catch{return"Object"}return e instanceof Error?`${e.name}: ${e.message}
|
||||
${e.stack}`:_}function $(e,t){return e=e>>>0,a().subarray(e/1,e/1+t)}function w(e){const t=o.__wbindgen_externrefs.get(e);return o.__externref_table_dealloc(e),t}const E=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry(e=>o.__wbg_querycompiler_free(e>>>0,1));class F{__destroy_into_raw(){const t=this.__wbg_ptr;return this.__wbg_ptr=0,E.unregister(this),t}free(){const t=this.__destroy_into_raw();o.__wbg_querycompiler_free(t,0)}compileBatch(t){const n=l(t,o.__wbindgen_malloc,o.__wbindgen_realloc),_=f,r=o.querycompiler_compileBatch(this.__wbg_ptr,n,_);if(r[2])throw w(r[1]);return w(r[0])}constructor(t){const n=o.querycompiler_new(t);if(n[2])throw w(n[1]);return this.__wbg_ptr=n[0]>>>0,E.register(this,this.__wbg_ptr,this),this}compile(t){const n=l(t,o.__wbindgen_malloc,o.__wbindgen_realloc),_=f,r=o.querycompiler_compile(this.__wbg_ptr,n,_);if(r[2])throw w(r[1]);return w(r[0])}}Symbol.dispose&&(F.prototype[Symbol.dispose]=F.prototype.free);function q(e,t){return Error(m(e,t))}function C(e){return Number(e)}function k(e,t){const n=String(t),_=l(n,o.__wbindgen_malloc,o.__wbindgen_realloc),r=f;u().setInt32(e+4*1,r,!0),u().setInt32(e+4*0,_,!0)}function W(e){const t=e,n=typeof t=="boolean"?t:void 0;return x(n)?16777215:n?1:0}function V(e,t){const n=I(t),_=l(n,o.__wbindgen_malloc,o.__wbindgen_realloc),r=f;u().setInt32(e+4*1,r,!0),u().setInt32(e+4*0,_,!0)}function z(e,t){return e in t}function L(e){const t=e;return typeof t=="object"&&t!==null}function P(e){return typeof e=="string"}function Q(e){return e===void 0}function Y(e,t){return e==t}function G(e,t){const n=t,_=typeof n=="number"?n:void 0;u().setFloat64(e+8*1,x(_)?0:_,!0),u().setInt32(e+4*0,!x(_),!0)}function J(e,t){const n=t,_=typeof n=="string"?n:void 0;var r=x(_)?0:l(_,o.__wbindgen_malloc,o.__wbindgen_realloc),s=f;u().setInt32(e+4*1,s,!0),u().setInt32(e+4*0,r,!0)}function X(e,t){throw new Error(m(e,t))}function H(e){return Object.entries(e)}function K(e){return e.getTime()}function Z(e,t){return e[t>>>0]}function v(e,t){return e[t]}function ee(e){let t;try{t=e instanceof ArrayBuffer}catch{t=!1}return t}function te(e){let t;try{t=e instanceof Uint8Array}catch{t=!1}return t}function ne(e){return Number.isSafeInteger(e)}function re(e){return e.length}function _e(e){return e.length}function oe(){return new Date}function ce(){return new Object}function ie(e){return new Uint8Array(e)}function se(){return new Map}function ue(){return new Array}function fe(e,t,n){Uint8Array.prototype.set.call($(e,t),n)}function be(e,t,n){e[t]=n}function de(e,t,n){return e.set(t,n)}function ae(e,t,n){e[t>>>0]=n}function ge(e,t){global.PRISMA_WASM_PANIC_REGISTRY.set_message(m(e,t))}function le(e,t){return m(e,t)}function we(e){return BigInt.asUintN(64,e)}function pe(e){return e}function ye(e){return e}function me(){const e=o.__wbindgen_externrefs,t=e.grow(4);e.set(0,void 0),e.set(t+0,void 0),e.set(t+1,null),e.set(t+2,!0),e.set(t+3,!1)}0&&(module.exports={QueryCompiler,__wbg_Error_e83987f665cf5504,__wbg_Number_bb48ca12f395cd08,__wbg_String_8f0eb39a4a4c2f66,__wbg___wbindgen_boolean_get_6d5a1ee65bab5f68,__wbg___wbindgen_debug_string_df47ffb5e35e6763,__wbg___wbindgen_in_bb933bd9e1b3bc0f,__wbg___wbindgen_is_object_c818261d21f283a4,__wbg___wbindgen_is_string_fbb76cb2940daafd,__wbg___wbindgen_is_undefined_2d472862bd29a478,__wbg___wbindgen_jsval_loose_eq_b664b38a2f582147,__wbg___wbindgen_number_get_a20bf9b85341449d,__wbg___wbindgen_string_get_e4f06c90489ad01b,__wbg___wbindgen_throw_b855445ff6a94295,__wbg_entries_e171b586f8f6bdbf,__wbg_getTime_14776bfb48a1bff9,__wbg_get_7bed016f185add81,__wbg_get_with_ref_key_1dc361bd10053bfe,__wbg_instanceof_ArrayBuffer_70beb1189ca63b38,__wbg_instanceof_Uint8Array_20c8e73002f7af98,__wbg_isSafeInteger_d216eda7911dde36,__wbg_length_69bca3cb64fc8748,__wbg_length_cdd215e10d9dd507,__wbg_new_0_f9740686d739025c,__wbg_new_1acc0b6eea89d040,__wbg_new_5a79be3ab53b8aa5,__wbg_new_68651c719dcda04e,__wbg_new_e17d9f43105b08be,__wbg_prototypesetcall_2a6620b6922694b2,__wbg_set_3f1d0b984ed272ed,__wbg_set_907fb406c34a251d,__wbg_set_c213c871859d6500,__wbg_set_message_82ae475bb413aa5c,__wbg_set_wasm,__wbindgen_cast_2241b6af4c4b2941,__wbindgen_cast_4625c577ab2ec9ee,__wbindgen_cast_9ae0607507abb057,__wbindgen_cast_d6cd19b81560fd6e,__wbindgen_init_externref_table});
|
||||
BIN
src/generated/prisma/query_compiler_fast_bg.wasm
Normal file
BIN
src/generated/prisma/query_compiler_fast_bg.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
3386
src/generated/prisma/runtime/client.d.ts
vendored
Normal file
3386
src/generated/prisma/runtime/client.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
86
src/generated/prisma/runtime/client.js
Normal file
86
src/generated/prisma/runtime/client.js
Normal file
File diff suppressed because one or more lines are too long
90
src/generated/prisma/runtime/index-browser.d.ts
vendored
Normal file
90
src/generated/prisma/runtime/index-browser.d.ts
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import { AnyNull } from '@prisma/client-runtime-utils';
|
||||
import { DbNull } from '@prisma/client-runtime-utils';
|
||||
import { Decimal } from '@prisma/client-runtime-utils';
|
||||
import { isAnyNull } from '@prisma/client-runtime-utils';
|
||||
import { isDbNull } from '@prisma/client-runtime-utils';
|
||||
import { isJsonNull } from '@prisma/client-runtime-utils';
|
||||
import { isObjectEnumValue } from '@prisma/client-runtime-utils';
|
||||
import { JsonNull } from '@prisma/client-runtime-utils';
|
||||
import { NullTypes } from '@prisma/client-runtime-utils';
|
||||
|
||||
export { AnyNull }
|
||||
|
||||
declare type Args<T, F extends Operation> = T extends {
|
||||
[K: symbol]: {
|
||||
types: {
|
||||
operations: {
|
||||
[K in F]: {
|
||||
args: any;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} ? T[symbol]['types']['operations'][F]['args'] : any;
|
||||
|
||||
export { DbNull }
|
||||
|
||||
export { Decimal }
|
||||
|
||||
declare type Exact<A, W> = (A extends unknown ? (W extends A ? {
|
||||
[K in keyof A]: Exact<A[K], W[K]>;
|
||||
} : W) : never) | (A extends Narrowable ? A : never);
|
||||
|
||||
export declare function getRuntime(): GetRuntimeOutput;
|
||||
|
||||
declare type GetRuntimeOutput = {
|
||||
id: RuntimeName;
|
||||
prettyName: string;
|
||||
isEdge: boolean;
|
||||
};
|
||||
|
||||
export { isAnyNull }
|
||||
|
||||
export { isDbNull }
|
||||
|
||||
export { isJsonNull }
|
||||
|
||||
export { isObjectEnumValue }
|
||||
|
||||
export { JsonNull }
|
||||
|
||||
/**
|
||||
* Generates more strict variant of an enum which, unlike regular enum,
|
||||
* throws on non-existing property access. This can be useful in following situations:
|
||||
* - we have an API, that accepts both `undefined` and `SomeEnumType` as an input
|
||||
* - enum values are generated dynamically from DMMF.
|
||||
*
|
||||
* In that case, if using normal enums and no compile-time typechecking, using non-existing property
|
||||
* will result in `undefined` value being used, which will be accepted. Using strict enum
|
||||
* in this case will help to have a runtime exception, telling you that you are probably doing something wrong.
|
||||
*
|
||||
* Note: if you need to check for existence of a value in the enum you can still use either
|
||||
* `in` operator or `hasOwnProperty` function.
|
||||
*
|
||||
* @param definition
|
||||
* @returns
|
||||
*/
|
||||
export declare function makeStrictEnum<T extends Record<PropertyKey, string | number>>(definition: T): T;
|
||||
|
||||
declare type Narrowable = string | number | bigint | boolean | [];
|
||||
|
||||
export { NullTypes }
|
||||
|
||||
declare type Operation = 'findFirst' | 'findFirstOrThrow' | 'findUnique' | 'findUniqueOrThrow' | 'findMany' | 'create' | 'createMany' | 'createManyAndReturn' | 'update' | 'updateMany' | 'updateManyAndReturn' | 'upsert' | 'delete' | 'deleteMany' | 'aggregate' | 'count' | 'groupBy' | '$queryRaw' | '$executeRaw' | '$queryRawUnsafe' | '$executeRawUnsafe' | 'findRaw' | 'aggregateRaw' | '$runCommandRaw';
|
||||
|
||||
declare namespace Public {
|
||||
export {
|
||||
validator
|
||||
}
|
||||
}
|
||||
export { Public }
|
||||
|
||||
declare type RuntimeName = 'workerd' | 'deno' | 'netlify' | 'node' | 'bun' | 'edge-light' | '';
|
||||
|
||||
declare function validator<V>(): <S>(select: Exact<S, V>) => S;
|
||||
|
||||
declare function validator<C, M extends Exclude<keyof C, `$${string}`>, O extends keyof C[M] & Operation>(client: C, model: M, operation: O): <S>(select: Exact<S, Args<C[M], O>>) => S;
|
||||
|
||||
declare function validator<C, M extends Exclude<keyof C, `$${string}`>, O extends keyof C[M] & Operation, P extends keyof Args<C[M], O>>(client: C, model: M, operation: O, prop: P): <S>(select: Exact<S, Args<C[M], O>[P]>) => S;
|
||||
|
||||
export { }
|
||||
6
src/generated/prisma/runtime/index-browser.js
Normal file
6
src/generated/prisma/runtime/index-browser.js
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
"use strict";var s=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var a=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},y=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of p(t))!f.call(e,i)&&i!==n&&s(e,i,{get:()=>t[i],enumerable:!(r=g(t,i))||r.enumerable});return e};var x=e=>y(s({},"__esModule",{value:!0}),e);var M={};a(M,{AnyNull:()=>o.AnyNull,DbNull:()=>o.DbNull,Decimal:()=>m.Decimal,JsonNull:()=>o.JsonNull,NullTypes:()=>o.NullTypes,Public:()=>l,getRuntime:()=>c,isAnyNull:()=>o.isAnyNull,isDbNull:()=>o.isDbNull,isJsonNull:()=>o.isJsonNull,isObjectEnumValue:()=>o.isObjectEnumValue,makeStrictEnum:()=>u});module.exports=x(M);var l={};a(l,{validator:()=>d});function d(...e){return t=>t}var b=new Set(["toJSON","$$typeof","asymmetricMatch",Symbol.iterator,Symbol.toStringTag,Symbol.isConcatSpreadable,Symbol.toPrimitive]);function u(e){return new Proxy(e,{get(t,n){if(n in t)return t[n];if(!b.has(n))throw new TypeError("Invalid enum value: ".concat(String(n)))}})}var N=()=>{var e,t;return((t=(e=globalThis.process)==null?void 0:e.release)==null?void 0:t.name)==="node"},E=()=>{var e,t;return!!globalThis.Bun||!!((t=(e=globalThis.process)==null?void 0:e.versions)!=null&&t.bun)},S=()=>!!globalThis.Deno,R=()=>typeof globalThis.Netlify=="object",h=()=>typeof globalThis.EdgeRuntime=="object",C=()=>{var e;return((e=globalThis.navigator)==null?void 0:e.userAgent)==="Cloudflare-Workers"};function k(){var n;return(n=[[R,"netlify"],[h,"edge-light"],[C,"workerd"],[S,"deno"],[E,"bun"],[N,"node"]].flatMap(r=>r[0]()?[r[1]]:[]).at(0))!=null?n:""}var O={node:"Node.js",workerd:"Cloudflare Workers",deno:"Deno and Deno Deploy",netlify:"Netlify Edge Functions","edge-light":"Edge Runtime (Vercel Edge Functions, Vercel Edge Middleware, Next.js (Pages Router) Edge API Routes, Next.js (App Router) Edge Route Handlers or Next.js Middleware)"};function c(){let e=k();return{id:e,prettyName:O[e]||e,isEdge:["workerd","deno","netlify","edge-light"].includes(e)}}var o=require("@prisma/client-runtime-utils"),m=require("@prisma/client-runtime-utils");0&&(module.exports={AnyNull,DbNull,Decimal,JsonNull,NullTypes,Public,getRuntime,isAnyNull,isDbNull,isJsonNull,isObjectEnumValue,makeStrictEnum});
|
||||
//# sourceMappingURL=index-browser.js.map
|
||||
76
src/generated/prisma/runtime/wasm-compiler-edge.js
Normal file
76
src/generated/prisma/runtime/wasm-compiler-edge.js
Normal file
File diff suppressed because one or more lines are too long
41
src/generated/prisma/schema.prisma
Normal file
41
src/generated/prisma/schema.prisma
Normal file
@@ -0,0 +1,41 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../src/generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
enum VoiceExperienceStatus {
|
||||
UPLOADED
|
||||
TRANSCRIBING
|
||||
TRANSCRIBED
|
||||
ANALYZING
|
||||
ANALYZED
|
||||
FAILED
|
||||
}
|
||||
|
||||
model Place {
|
||||
id String @id @default(cuid())
|
||||
googlePlaceId String @unique
|
||||
name String
|
||||
latitude Float
|
||||
longitude Float
|
||||
experiences VoiceExperience[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model VoiceExperience {
|
||||
id String @id @default(cuid())
|
||||
placeId String
|
||||
place Place @relation(fields: [placeId], references: [id])
|
||||
durationSeconds Int
|
||||
audioObjectKey String
|
||||
status VoiceExperienceStatus @default(UPLOADED)
|
||||
transcript String?
|
||||
analysis Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
5
src/generated/prisma/wasm-edge-light-loader.mjs
Normal file
5
src/generated/prisma/wasm-edge-light-loader.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
export default import('./query_compiler_fast_bg.wasm?module')
|
||||
5
src/generated/prisma/wasm-worker-loader.mjs
Normal file
5
src/generated/prisma/wasm-worker-loader.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!!
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
export default import('./query_compiler_fast_bg.wasm')
|
||||
8
src/graphql/scalars.ts
Normal file
8
src/graphql/scalars.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const GraphQLJSONObject = {
|
||||
__serialize(value: unknown) {
|
||||
return value;
|
||||
},
|
||||
__parseValue(value: unknown) {
|
||||
return value;
|
||||
},
|
||||
};
|
||||
64
src/graphql/schema.ts
Normal file
64
src/graphql/schema.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { GraphQLJSONObject } from './scalars.js';
|
||||
import { createVoiceExperience } from './voice-experiences.js';
|
||||
|
||||
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!
|
||||
}
|
||||
|
||||
type VoiceExperience {
|
||||
id: ID!
|
||||
place: Place!
|
||||
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!
|
||||
}
|
||||
|
||||
type Query {
|
||||
health: String!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createVoiceExperience(input: CreateVoiceExperienceInput!): VoiceExperience!
|
||||
}
|
||||
`;
|
||||
|
||||
export const resolvers = {
|
||||
JSON: GraphQLJSONObject,
|
||||
Query: {
|
||||
health: () => 'ok',
|
||||
},
|
||||
Mutation: {
|
||||
createVoiceExperience: async (
|
||||
_: unknown,
|
||||
args: { input: Parameters<typeof createVoiceExperience>[0] },
|
||||
) => createVoiceExperience(args.input),
|
||||
},
|
||||
};
|
||||
46
src/graphql/voice-experiences.ts
Normal file
46
src/graphql/voice-experiences.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { enqueueVoiceExperience } from '../hatchet/enqueue-voice-experience.js';
|
||||
import { prisma } from '../prisma.js';
|
||||
|
||||
export type CreateVoiceExperienceInput = {
|
||||
googlePlaceId: string;
|
||||
googleName: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
durationSeconds: number;
|
||||
audioObjectKey: string;
|
||||
};
|
||||
|
||||
export async function createVoiceExperience(input: CreateVoiceExperienceInput) {
|
||||
if (input.durationSeconds < 60) {
|
||||
throw new Error('Voice experience must be at least 60 seconds.');
|
||||
}
|
||||
|
||||
const place = await prisma.place.upsert({
|
||||
where: { googlePlaceId: input.googlePlaceId },
|
||||
create: {
|
||||
googlePlaceId: input.googlePlaceId,
|
||||
name: input.googleName,
|
||||
latitude: input.latitude,
|
||||
longitude: input.longitude,
|
||||
},
|
||||
update: {
|
||||
name: input.googleName,
|
||||
latitude: input.latitude,
|
||||
longitude: input.longitude,
|
||||
},
|
||||
});
|
||||
|
||||
const experience = await prisma.voiceExperience.create({
|
||||
data: {
|
||||
placeId: place.id,
|
||||
durationSeconds: input.durationSeconds,
|
||||
audioObjectKey: input.audioObjectKey,
|
||||
status: 'UPLOADED',
|
||||
},
|
||||
include: { place: true },
|
||||
});
|
||||
|
||||
await enqueueVoiceExperience({ experienceId: experience.id });
|
||||
|
||||
return experience;
|
||||
}
|
||||
12
src/hatchet/enqueue-voice-experience.ts
Normal file
12
src/hatchet/enqueue-voice-experience.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { hatchet } from './hatchet-client.js';
|
||||
import { workflowNames } from './workflow-names.js';
|
||||
|
||||
export type ProcessVoiceExperienceInput = {
|
||||
experienceId: string;
|
||||
};
|
||||
|
||||
export async function enqueueVoiceExperience(
|
||||
input: ProcessVoiceExperienceInput,
|
||||
) {
|
||||
await hatchet.admin.runWorkflow(workflowNames.processVoiceExperience, input);
|
||||
}
|
||||
7
src/hatchet/hatchet-client.ts
Normal file
7
src/hatchet/hatchet-client.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { HatchetClient } from '@hatchet-dev/typescript-sdk';
|
||||
|
||||
import { config } from '../config.js';
|
||||
|
||||
export const hatchet = HatchetClient.init({
|
||||
token: config.hatchetToken,
|
||||
});
|
||||
3
src/hatchet/workflow-names.ts
Normal file
3
src/hatchet/workflow-names.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const workflowNames = {
|
||||
processVoiceExperience: 'process_voice_experience',
|
||||
} as const;
|
||||
8
src/prisma.ts
Normal file
8
src/prisma.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
import { config } from './config.js';
|
||||
import { PrismaClient } from './generated/prisma/client.js';
|
||||
|
||||
const adapter = new PrismaPg({ connectionString: config.databaseUrl });
|
||||
|
||||
export const prisma = new PrismaClient({ adapter });
|
||||
22
src/server.ts
Normal file
22
src/server.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import Fastify from 'fastify';
|
||||
import mercurius from 'mercurius';
|
||||
|
||||
import { config } from './config.js';
|
||||
import { prisma } from './prisma.js';
|
||||
import { resolvers, schema } from './graphql/schema.js';
|
||||
|
||||
const app = Fastify({ logger: true });
|
||||
|
||||
app.register(mercurius, {
|
||||
schema,
|
||||
resolvers,
|
||||
graphiql: true,
|
||||
});
|
||||
|
||||
app.get('/health', async () => ({ ok: true }));
|
||||
|
||||
app.addHook('onClose', async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
|
||||
await app.listen({ host: config.host, port: config.port });
|
||||
14
tsconfig.json
Normal file
14
tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user