Add checkCache and report routes
This commit is contained in:
2
app/@types/nextjs-routes.d.ts
vendored
2
app/@types/nextjs-routes.d.ts
vendored
@@ -12,8 +12,10 @@ declare module "nextjs-routes" {
|
|||||||
|
|
||||||
export type Route =
|
export type Route =
|
||||||
| StaticRoute<"/account/signin">
|
| StaticRoute<"/account/signin">
|
||||||
|
| DynamicRoute<"/api/[...trpc]", { "trpc": string[] }>
|
||||||
| DynamicRoute<"/api/auth/[...nextauth]", { "nextauth": string[] }>
|
| DynamicRoute<"/api/auth/[...nextauth]", { "nextauth": string[] }>
|
||||||
| StaticRoute<"/api/experiments/og-image">
|
| StaticRoute<"/api/experiments/og-image">
|
||||||
|
| StaticRoute<"/api/openapi">
|
||||||
| StaticRoute<"/api/sentry-example-api">
|
| StaticRoute<"/api/sentry-example-api">
|
||||||
| DynamicRoute<"/api/trpc/[trpc]", { "trpc": string }>
|
| DynamicRoute<"/api/trpc/[trpc]", { "trpc": string }>
|
||||||
| DynamicRoute<"/data/[id]", { "id": string }>
|
| DynamicRoute<"/data/[id]", { "id": string }>
|
||||||
|
|||||||
@@ -66,6 +66,7 @@
|
|||||||
"next": "^13.4.2",
|
"next": "^13.4.2",
|
||||||
"next-auth": "^4.22.1",
|
"next-auth": "^4.22.1",
|
||||||
"next-query-params": "^4.2.3",
|
"next-query-params": "^4.2.3",
|
||||||
|
"nextjs-cors": "^2.1.2",
|
||||||
"nextjs-routes": "^2.0.1",
|
"nextjs-routes": "^2.0.1",
|
||||||
"openai": "4.0.0-beta.7",
|
"openai": "4.0.0-beta.7",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
@@ -87,6 +88,7 @@
|
|||||||
"socket.io": "^4.7.1",
|
"socket.io": "^4.7.1",
|
||||||
"socket.io-client": "^4.7.1",
|
"socket.io-client": "^4.7.1",
|
||||||
"superjson": "1.12.2",
|
"superjson": "1.12.2",
|
||||||
|
"trpc-openapi": "^1.2.0",
|
||||||
"tsx": "^3.12.7",
|
"tsx": "^3.12.7",
|
||||||
"type-fest": "^4.0.0",
|
"type-fest": "^4.0.0",
|
||||||
"use-query-params": "^2.2.1",
|
"use-query-params": "^2.2.1",
|
||||||
|
|||||||
117
app/pnpm-lock.yaml
generated
117
app/pnpm-lock.yaml
generated
@@ -1,4 +1,4 @@
|
|||||||
lockfileVersion: '6.1'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
@@ -137,6 +137,9 @@ dependencies:
|
|||||||
next-query-params:
|
next-query-params:
|
||||||
specifier: ^4.2.3
|
specifier: ^4.2.3
|
||||||
version: 4.2.3(next@13.4.2)(react@18.2.0)(use-query-params@2.2.1)
|
version: 4.2.3(next@13.4.2)(react@18.2.0)(use-query-params@2.2.1)
|
||||||
|
nextjs-cors:
|
||||||
|
specifier: ^2.1.2
|
||||||
|
version: 2.1.2(next@13.4.2)
|
||||||
nextjs-routes:
|
nextjs-routes:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.0.1(next@13.4.2)
|
version: 2.0.1(next@13.4.2)
|
||||||
@@ -200,6 +203,9 @@ dependencies:
|
|||||||
superjson:
|
superjson:
|
||||||
specifier: 1.12.2
|
specifier: 1.12.2
|
||||||
version: 1.12.2
|
version: 1.12.2
|
||||||
|
trpc-openapi:
|
||||||
|
specifier: ^1.2.0
|
||||||
|
version: 1.2.0(@trpc/server@10.26.0)(zod@3.21.4)
|
||||||
tsx:
|
tsx:
|
||||||
specifier: ^3.12.7
|
specifier: ^3.12.7
|
||||||
version: 3.12.7
|
version: 3.12.7
|
||||||
@@ -4144,6 +4150,15 @@ packages:
|
|||||||
wrap-ansi: 7.0.0
|
wrap-ansi: 7.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/co-body@6.1.0:
|
||||||
|
resolution: {integrity: sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==}
|
||||||
|
dependencies:
|
||||||
|
inflation: 2.0.0
|
||||||
|
qs: 6.11.0
|
||||||
|
raw-body: 2.5.1
|
||||||
|
type-is: 1.6.18
|
||||||
|
dev: false
|
||||||
|
|
||||||
/color-convert@1.9.3:
|
/color-convert@1.9.3:
|
||||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4235,6 +4250,10 @@ packages:
|
|||||||
/convert-source-map@1.9.0:
|
/convert-source-map@1.9.0:
|
||||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||||
|
|
||||||
|
/cookie-es@1.0.0:
|
||||||
|
resolution: {integrity: sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cookie-signature@1.0.6:
|
/cookie-signature@1.0.6:
|
||||||
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
|
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -4462,11 +4481,20 @@ packages:
|
|||||||
has-property-descriptors: 1.0.0
|
has-property-descriptors: 1.0.0
|
||||||
object-keys: 1.1.1
|
object-keys: 1.1.1
|
||||||
|
|
||||||
|
/defu@6.1.2:
|
||||||
|
resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/delayed-stream@1.0.0:
|
/delayed-stream@1.0.0:
|
||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/depd@1.1.2:
|
||||||
|
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/depd@2.0.0:
|
/depd@2.0.0:
|
||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -4477,6 +4505,10 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/destr@2.0.1:
|
||||||
|
resolution: {integrity: sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/destroy@1.2.0:
|
/destroy@1.2.0:
|
||||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
@@ -5636,6 +5668,18 @@ packages:
|
|||||||
- pg-native
|
- pg-native
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/h3@1.7.1:
|
||||||
|
resolution: {integrity: sha512-A9V2NEDNHet7v1gCg7CMwerSigLi0SRbhTy7C3lGb0N4YKIpPmLDjedTUopqp4dnn7COHfqUjjaz3zbtz4QduA==}
|
||||||
|
dependencies:
|
||||||
|
cookie-es: 1.0.0
|
||||||
|
defu: 6.1.2
|
||||||
|
destr: 2.0.1
|
||||||
|
iron-webcrypto: 0.7.1
|
||||||
|
radix3: 1.0.1
|
||||||
|
ufo: 1.1.2
|
||||||
|
uncrypto: 0.1.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/has-bigints@1.0.2:
|
/has-bigints@1.0.2:
|
||||||
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
|
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -5782,6 +5826,11 @@ packages:
|
|||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/inflation@2.0.0:
|
||||||
|
resolution: {integrity: sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==}
|
||||||
|
engines: {node: '>= 0.8.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/inflight@1.0.6:
|
/inflight@1.0.6:
|
||||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5811,6 +5860,10 @@ packages:
|
|||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/iron-webcrypto@0.7.1:
|
||||||
|
resolution: {integrity: sha512-K/UmlEhPCPXEHV5hAtH5C0tI5JnFuOrv4yO/j7ODPl3HaiiHBLbOLTde+ieUaAyfCATe4LoAnclyF+hmSCOVmQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-alphabetical@1.0.4:
|
/is-alphabetical@1.0.4:
|
||||||
resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
|
resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -6568,6 +6621,15 @@ packages:
|
|||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/nextjs-cors@2.1.2(next@13.4.2):
|
||||||
|
resolution: {integrity: sha512-2yOVivaaf2ILe4f/qY32hnj3oC77VCOsUQJQfhVMGsXE/YMEWUY2zy78sH9FKUCM7eG42/l3pDofIzMD781XGA==}
|
||||||
|
peerDependencies:
|
||||||
|
next: ^8.1.1-canary.54 || ^9.0.0 || ^10.0.0-0 || ^11.0.0 || ^12.0.0 || ^13.0.0
|
||||||
|
dependencies:
|
||||||
|
cors: 2.8.5
|
||||||
|
next: 13.4.2(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/nextjs-routes@2.0.1(next@13.4.2):
|
/nextjs-routes@2.0.1(next@13.4.2):
|
||||||
resolution: {integrity: sha512-pBGRm6uR44zwUjWWYn6+gwz08BhBbqUYlIzsbNHAh1TWohHYKWFaa2YVsj8BxEo726MZYg87OJPnHpaaY1ia0w==}
|
resolution: {integrity: sha512-pBGRm6uR44zwUjWWYn6+gwz08BhBbqUYlIzsbNHAh1TWohHYKWFaa2YVsj8BxEo726MZYg87OJPnHpaaY1ia0w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -6595,6 +6657,22 @@ packages:
|
|||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-mocks-http@1.12.2:
|
||||||
|
resolution: {integrity: sha512-xhWwC0dh35R9rf0j3bRZXuISXdHxxtMx0ywZQBwjrg3yl7KpRETzogfeCamUIjltpn0Fxvs/ZhGJul1vPLrdJQ==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
dependencies:
|
||||||
|
accepts: 1.3.8
|
||||||
|
content-disposition: 0.5.4
|
||||||
|
depd: 1.1.2
|
||||||
|
fresh: 0.5.2
|
||||||
|
merge-descriptors: 1.0.1
|
||||||
|
methods: 1.1.2
|
||||||
|
mime: 1.6.0
|
||||||
|
parseurl: 1.3.3
|
||||||
|
range-parser: 1.2.1
|
||||||
|
type-is: 1.6.18
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-releases@2.0.13:
|
/node-releases@2.0.13:
|
||||||
resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}
|
resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}
|
||||||
|
|
||||||
@@ -6754,6 +6832,10 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/openapi-types@12.1.3:
|
||||||
|
resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/openapi-typescript@5.4.1:
|
/openapi-typescript@5.4.1:
|
||||||
resolution: {integrity: sha512-AGB2QiZPz4rE7zIwV3dRHtoUC/CWHhUjuzGXvtmMQN2AFV8xCTLKcZUHLcdPQmt/83i22nRE7+TxXOXkK+gf4Q==}
|
resolution: {integrity: sha512-AGB2QiZPz4rE7zIwV3dRHtoUC/CWHhUjuzGXvtmMQN2AFV8xCTLKcZUHLcdPQmt/83i22nRE7+TxXOXkK+gf4Q==}
|
||||||
engines: {node: '>= 14.0.0'}
|
engines: {node: '>= 14.0.0'}
|
||||||
@@ -7203,6 +7285,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/radix3@1.0.1:
|
||||||
|
resolution: {integrity: sha512-y+AcwZ3HcUIGc9zGsNVf5+BY/LxL+z+4h4J3/pp8jxSmy1STaCocPS3qrj4tA5ehUSzqtqK+0Aygvz/r/8vy4g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/randombytes@2.1.0:
|
/randombytes@2.1.0:
|
||||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8180,6 +8266,22 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/trpc-openapi@1.2.0(@trpc/server@10.26.0)(zod@3.21.4):
|
||||||
|
resolution: {integrity: sha512-pfYoCd/3KYXWXvUPZBKJw455OOwngKN/6SIcj7Yit19OMLJ+8yVZkEvGEeg5wUSwfsiTdRsKuvqkRPXVSwV7ew==}
|
||||||
|
peerDependencies:
|
||||||
|
'@trpc/server': ^10.0.0
|
||||||
|
zod: ^3.14.4
|
||||||
|
dependencies:
|
||||||
|
'@trpc/server': 10.26.0
|
||||||
|
co-body: 6.1.0
|
||||||
|
h3: 1.7.1
|
||||||
|
lodash.clonedeep: 4.5.0
|
||||||
|
node-mocks-http: 1.12.2
|
||||||
|
openapi-types: 12.1.3
|
||||||
|
zod: 3.21.4
|
||||||
|
zod-to-json-schema: 3.21.4(zod@3.21.4)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tsconfck@2.1.2(typescript@5.0.4):
|
/tsconfck@2.1.2(typescript@5.0.4):
|
||||||
resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==}
|
resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==}
|
||||||
engines: {node: ^14.13.1 || ^16 || >=18}
|
engines: {node: ^14.13.1 || ^16 || >=18}
|
||||||
@@ -8322,7 +8424,6 @@ packages:
|
|||||||
|
|
||||||
/ufo@1.1.2:
|
/ufo@1.1.2:
|
||||||
resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
|
resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/unbox-primitive@1.0.2:
|
/unbox-primitive@1.0.2:
|
||||||
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
|
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
|
||||||
@@ -8333,6 +8434,10 @@ packages:
|
|||||||
which-boxed-primitive: 1.0.2
|
which-boxed-primitive: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/uncrypto@0.1.3:
|
||||||
|
resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/undici@5.22.1:
|
/undici@5.22.1:
|
||||||
resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==}
|
resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==}
|
||||||
engines: {node: '>=14.0'}
|
engines: {node: '>=14.0'}
|
||||||
@@ -8861,6 +8966,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==}
|
resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/zod-to-json-schema@3.21.4(zod@3.21.4):
|
||||||
|
resolution: {integrity: sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw==}
|
||||||
|
peerDependencies:
|
||||||
|
zod: ^3.21.4
|
||||||
|
dependencies:
|
||||||
|
zod: 3.21.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/zod@3.21.4:
|
/zod@3.21.4:
|
||||||
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LoggedCall" (
|
||||||
|
"id" UUID NOT NULL,
|
||||||
|
"startTime" TIMESTAMP(3) NOT NULL,
|
||||||
|
"cacheHit" BOOLEAN NOT NULL,
|
||||||
|
"modelResponseId" UUID NOT NULL,
|
||||||
|
"organizationId" UUID NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "LoggedCall_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LoggedCallModelResponse" (
|
||||||
|
"id" UUID NOT NULL,
|
||||||
|
"reqPayload" JSONB NOT NULL,
|
||||||
|
"respStatus" INTEGER,
|
||||||
|
"respPayload" JSONB,
|
||||||
|
"error" TEXT,
|
||||||
|
"startTime" TIMESTAMP(3) NOT NULL,
|
||||||
|
"endTime" TIMESTAMP(3) NOT NULL,
|
||||||
|
"cacheKey" TEXT,
|
||||||
|
"durationMs" INTEGER,
|
||||||
|
"inputTokens" INTEGER,
|
||||||
|
"outputTokens" INTEGER,
|
||||||
|
"finishReason" TEXT,
|
||||||
|
"completionId" TEXT,
|
||||||
|
"totalCost" DECIMAL(18,12),
|
||||||
|
"originalLoggedCallId" UUID NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "LoggedCallModelResponse_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LoggedCallTag" (
|
||||||
|
"id" UUID NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"value" TEXT,
|
||||||
|
"loggedCallId" UUID NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "LoggedCallTag_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "ApiKey" (
|
||||||
|
"id" UUID NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"apiKey" TEXT NOT NULL,
|
||||||
|
"organizationId" UUID NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "ApiKey_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LoggedCall_startTime_idx" ON "LoggedCall"("startTime");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "LoggedCallModelResponse_originalLoggedCallId_key" ON "LoggedCallModelResponse"("originalLoggedCallId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LoggedCallModelResponse_cacheKey_idx" ON "LoggedCallModelResponse"("cacheKey");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LoggedCallTag_name_idx" ON "LoggedCallTag"("name");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LoggedCallTag_name_value_idx" ON "LoggedCallTag"("name", "value");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "ApiKey_apiKey_key" ON "ApiKey"("apiKey");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LoggedCall" ADD CONSTRAINT "LoggedCall_modelResponseId_fkey" FOREIGN KEY ("modelResponseId") REFERENCES "LoggedCallModelResponse"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LoggedCall" ADD CONSTRAINT "LoggedCall_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LoggedCallModelResponse" ADD CONSTRAINT "LoggedCallModelResponse_originalLoggedCallId_fkey" FOREIGN KEY ("originalLoggedCallId") REFERENCES "LoggedCall"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LoggedCallTag" ADD CONSTRAINT "LoggedCallTag_loggedCallId_fkey" FOREIGN KEY ("loggedCallId") REFERENCES "LoggedCall"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "ApiKey" ADD CONSTRAINT "ApiKey_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@@ -260,13 +260,13 @@ model LoggedCall {
|
|||||||
cacheHit Boolean
|
cacheHit Boolean
|
||||||
|
|
||||||
// A LoggedCall is always associated with a LoggedCallModelResponse. If this
|
// A LoggedCall is always associated with a LoggedCallModelResponse. If this
|
||||||
// is a cache miss, it's a new LoggedCallModelResponse we created for this.
|
// is a cache miss, we create a new LoggedCallModelResponse.
|
||||||
// If it's a cache hit, it's the existing LoggedCallModelResponse we served.
|
// If it's a cache hit, it's a pre-existing LoggedCallModelResponse.
|
||||||
modelResponseId String @db.Uuid
|
modelResponseId String @db.Uuid
|
||||||
modelResponse LoggedCallModelResponse @relation(fields: [modelResponseId], references: [id], onDelete: Cascade)
|
modelResponse LoggedCallModelResponse @relation(fields: [modelResponseId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
// The response created by this LoggedCall. Will be null if this LoggedCall is a cache hit.
|
// The response created by this LoggedCall. Will be null if this LoggedCall is a cache hit.
|
||||||
createdResponse LoggedCallModelResponse[] @relation(name: "ModelResponseCreatedBy")
|
createdResponse LoggedCallModelResponse[] @relation(name: "ModelResponseOriginalCall")
|
||||||
|
|
||||||
organizationId String @db.Uuid
|
organizationId String @db.Uuid
|
||||||
organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||||
@@ -309,8 +309,8 @@ model LoggedCallModelResponse {
|
|||||||
totalCost Decimal? @db.Decimal(18, 12)
|
totalCost Decimal? @db.Decimal(18, 12)
|
||||||
|
|
||||||
// The LoggedCall that created this LoggedCallModelResponse
|
// The LoggedCall that created this LoggedCallModelResponse
|
||||||
createdById String @unique @db.Uuid
|
originalLoggedCallId String @unique @db.Uuid
|
||||||
createdBy LoggedCall @relation(name: "ModelResponseCreatedBy", fields: [createdById], references: [id], onDelete: Cascade)
|
originalLoggedCall LoggedCall @relation(name: "ModelResponseOriginalCall", fields: [originalLoggedCallId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
@@ -320,11 +320,11 @@ model LoggedCallModelResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model LoggedCallTag {
|
model LoggedCallTag {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid()) @db.Uuid
|
||||||
name String
|
name String
|
||||||
value String?
|
value String?
|
||||||
|
|
||||||
loggedCallId String
|
loggedCallId String @db.Uuid
|
||||||
loggedCall LoggedCall @relation(fields: [loggedCallId], references: [id], onDelete: Cascade)
|
loggedCall LoggedCall @relation(fields: [loggedCallId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@index([name])
|
@@index([name])
|
||||||
|
|||||||
22
app/src/pages/api/[...trpc].ts
Normal file
22
app/src/pages/api/[...trpc].ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { type NextApiRequest, type NextApiResponse } from "next";
|
||||||
|
import cors from "nextjs-cors";
|
||||||
|
import { createOpenApiNextHandler } from "trpc-openapi";
|
||||||
|
import { createProcedureCache } from "trpc-openapi/dist/adapters/node-http/procedures";
|
||||||
|
import { appRouter } from "~/server/api/root.router";
|
||||||
|
import { createTRPCContext } from "~/server/api/trpc";
|
||||||
|
|
||||||
|
const openApiHandler = createOpenApiNextHandler({
|
||||||
|
router: appRouter,
|
||||||
|
createContext: createTRPCContext,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cache = createProcedureCache(appRouter);
|
||||||
|
|
||||||
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
// Setup CORS
|
||||||
|
await cors(req, res);
|
||||||
|
|
||||||
|
return openApiHandler(req, res);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handler;
|
||||||
16
app/src/pages/api/openapi.json.ts
Normal file
16
app/src/pages/api/openapi.json.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { type NextApiRequest, type NextApiResponse } from "next";
|
||||||
|
import { generateOpenApiDocument } from "trpc-openapi";
|
||||||
|
import { appRouter } from "~/server/api/root.router";
|
||||||
|
|
||||||
|
export const openApiDocument = generateOpenApiDocument(appRouter, {
|
||||||
|
title: "OpenPipe API",
|
||||||
|
description: "The public API for reporting API calls to OpenPipe",
|
||||||
|
version: "0.1.0",
|
||||||
|
baseUrl: "https://app.openpipe.ai/api",
|
||||||
|
});
|
||||||
|
// Respond with our OpenAPI schema
|
||||||
|
const hander = (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
res.status(200).send(openApiDocument);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default hander;
|
||||||
197
app/src/server/api/routers/externalApi.router.ts
Normal file
197
app/src/server/api/routers/externalApi.router.ts
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
import { type Prisma } from "@prisma/client";
|
||||||
|
import { type JsonValue } from "type-fest";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
|
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||||
|
import { prisma } from "~/server/db";
|
||||||
|
import { hashRequest } from "~/server/utils/hashObject";
|
||||||
|
|
||||||
|
const reqValidator = z.object({
|
||||||
|
model: z.string(),
|
||||||
|
messages: z.array(z.any()),
|
||||||
|
});
|
||||||
|
|
||||||
|
const respValidator = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
model: z.string(),
|
||||||
|
usage: z.object({
|
||||||
|
total_tokens: z.number(),
|
||||||
|
prompt_tokens: z.number(),
|
||||||
|
completion_tokens: z.number(),
|
||||||
|
}),
|
||||||
|
choices: z.array(
|
||||||
|
z.object({
|
||||||
|
finish_reason: z.string(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const externalApiRouter = createTRPCRouter({
|
||||||
|
checkCache: publicProcedure
|
||||||
|
.meta({
|
||||||
|
openapi: {
|
||||||
|
method: "POST",
|
||||||
|
path: "/v1/check-cache",
|
||||||
|
description: "Check if a prompt is cached",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
startTime: z.number().describe("Unix timestamp in milliseconds"),
|
||||||
|
reqPayload: z.unknown().describe("JSON-encoded request payload"),
|
||||||
|
tags: z
|
||||||
|
.record(z.string())
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
'Extra tags to attach to the call for filtering. Eg { "userId": "123", "promptId": "populate-title" }',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.output(
|
||||||
|
z.object({
|
||||||
|
respPayload: z.unknown().optional().describe("JSON-encoded response payload"),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const apiKey = ctx.apiKey;
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new Error("Missing API key");
|
||||||
|
}
|
||||||
|
const key = await prisma.apiKey.findUnique({
|
||||||
|
where: { apiKey },
|
||||||
|
});
|
||||||
|
if (!key) {
|
||||||
|
throw new Error("Invalid API key");
|
||||||
|
}
|
||||||
|
const reqPayload = await reqValidator.spa(input.reqPayload);
|
||||||
|
const cacheKey = hashRequest(key.organizationId, reqPayload as JsonValue);
|
||||||
|
|
||||||
|
const existingResponse = await prisma.loggedCallModelResponse.findFirst({
|
||||||
|
where: {
|
||||||
|
cacheKey,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
originalLoggedCall: true,
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
startTime: "desc",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!existingResponse) return { respPayload: null };
|
||||||
|
|
||||||
|
await prisma.loggedCall.create({
|
||||||
|
data: {
|
||||||
|
organizationId: key.organizationId,
|
||||||
|
startTime: new Date(input.startTime),
|
||||||
|
cacheHit: false,
|
||||||
|
modelResponseId: existingResponse.id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
respPayload: existingResponse.respPayload,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
report: publicProcedure
|
||||||
|
.meta({
|
||||||
|
openapi: {
|
||||||
|
method: "POST",
|
||||||
|
path: "/v1/report",
|
||||||
|
description: "Report an API call",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
startTime: z.number().describe("Unix timestamp in milliseconds"),
|
||||||
|
endTime: z.number().describe("Unix timestamp in milliseconds"),
|
||||||
|
reqPayload: z.unknown().describe("JSON-encoded request payload"),
|
||||||
|
respPayload: z.unknown().optional().describe("JSON-encoded response payload"),
|
||||||
|
respStatus: z.number().optional().describe("HTTP status code of response"),
|
||||||
|
error: z.string().optional().describe("User-friendly error message"),
|
||||||
|
tags: z
|
||||||
|
.record(z.string())
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
'Extra tags to attach to the call for filtering. Eg { "userId": "123", "promptId": "populate-title" }',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.output(z.void())
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const apiKey = ctx.apiKey;
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new Error("Missing API key");
|
||||||
|
}
|
||||||
|
const key = await prisma.apiKey.findUnique({
|
||||||
|
where: { apiKey },
|
||||||
|
});
|
||||||
|
if (!key) {
|
||||||
|
throw new Error("Invalid API key");
|
||||||
|
}
|
||||||
|
const reqPayload = await reqValidator.spa(input.reqPayload);
|
||||||
|
const respPayload = await respValidator.spa(input.respPayload);
|
||||||
|
|
||||||
|
const requestHash = hashRequest(key.organizationId, reqPayload as JsonValue);
|
||||||
|
|
||||||
|
const newLoggedCallId = uuidv4();
|
||||||
|
const newModelResponseId = uuidv4();
|
||||||
|
|
||||||
|
const usage = respPayload.success ? respPayload.data.usage : undefined;
|
||||||
|
|
||||||
|
await prisma.$transaction([
|
||||||
|
prisma.loggedCall.create({
|
||||||
|
data: {
|
||||||
|
id: newLoggedCallId,
|
||||||
|
organizationId: key.organizationId,
|
||||||
|
startTime: new Date(input.startTime),
|
||||||
|
cacheHit: false,
|
||||||
|
modelResponseId: newModelResponseId,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
prisma.loggedCallModelResponse.create({
|
||||||
|
data: {
|
||||||
|
id: newModelResponseId,
|
||||||
|
originalLoggedCallId: newLoggedCallId,
|
||||||
|
startTime: new Date(input.startTime),
|
||||||
|
endTime: new Date(input.endTime),
|
||||||
|
reqPayload: input.reqPayload as Prisma.InputJsonValue,
|
||||||
|
respPayload: input.respPayload as Prisma.InputJsonValue,
|
||||||
|
respStatus: input.respStatus,
|
||||||
|
error: input.error,
|
||||||
|
durationMs: input.endTime - input.startTime,
|
||||||
|
...(respPayload.success
|
||||||
|
? {
|
||||||
|
cacheKey: requestHash,
|
||||||
|
inputTokens: usage ? usage.prompt_tokens : undefined,
|
||||||
|
outputTokens: usage ? usage.completion_tokens : undefined,
|
||||||
|
model: respPayload.data.model,
|
||||||
|
}
|
||||||
|
: null),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (input.tags) {
|
||||||
|
const tagsToCreate = Object.entries(input.tags).map(([name, value]) => ({
|
||||||
|
loggedCallId: newLoggedCallId,
|
||||||
|
// sanitize tags
|
||||||
|
name: name.replaceAll(/[^a-zA-Z0-9_]/g, "_"),
|
||||||
|
value,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (reqPayload.success) {
|
||||||
|
tagsToCreate.push({
|
||||||
|
loggedCallId: newLoggedCallId,
|
||||||
|
name: "$model",
|
||||||
|
value: reqPayload.data.model,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await prisma.loggedCallTag.createMany({
|
||||||
|
data: tagsToCreate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
});
|
||||||
@@ -11,6 +11,7 @@ import { initTRPC, TRPCError } from "@trpc/server";
|
|||||||
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
|
import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
|
||||||
import { type Session } from "next-auth";
|
import { type Session } from "next-auth";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
|
import { type OpenApiMeta } from "trpc-openapi";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
import { getServerAuthSession } from "~/server/auth";
|
import { getServerAuthSession } from "~/server/auth";
|
||||||
import { prisma } from "~/server/db";
|
import { prisma } from "~/server/db";
|
||||||
@@ -26,6 +27,7 @@ import { capturePath } from "~/utils/analytics/serverAnalytics";
|
|||||||
|
|
||||||
type CreateContextOptions = {
|
type CreateContextOptions = {
|
||||||
session: Session | null;
|
session: Session | null;
|
||||||
|
apiKey: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
@@ -44,6 +46,7 @@ const noOp = () => {};
|
|||||||
export const createInnerTRPCContext = (opts: CreateContextOptions) => {
|
export const createInnerTRPCContext = (opts: CreateContextOptions) => {
|
||||||
return {
|
return {
|
||||||
session: opts.session,
|
session: opts.session,
|
||||||
|
apiKey: opts.apiKey,
|
||||||
prisma,
|
prisma,
|
||||||
markAccessControlRun: noOp,
|
markAccessControlRun: noOp,
|
||||||
};
|
};
|
||||||
@@ -61,8 +64,13 @@ export const createTRPCContext = async (opts: CreateNextContextOptions) => {
|
|||||||
// Get the session from the server using the getServerSession wrapper function
|
// Get the session from the server using the getServerSession wrapper function
|
||||||
const session = await getServerAuthSession({ req, res });
|
const session = await getServerAuthSession({ req, res });
|
||||||
|
|
||||||
|
const apiKey = req.headers["x-openpipe-api-key"] as string | null;
|
||||||
|
|
||||||
|
console.log('api key is', apiKey)
|
||||||
|
|
||||||
return createInnerTRPCContext({
|
return createInnerTRPCContext({
|
||||||
session,
|
session,
|
||||||
|
apiKey,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,7 +84,10 @@ export const createTRPCContext = async (opts: CreateNextContextOptions) => {
|
|||||||
|
|
||||||
export type TRPCContext = Awaited<ReturnType<typeof createTRPCContext>>;
|
export type TRPCContext = Awaited<ReturnType<typeof createTRPCContext>>;
|
||||||
|
|
||||||
const t = initTRPC.context<typeof createTRPCContext>().create({
|
const t = initTRPC
|
||||||
|
.context<typeof createTRPCContext>()
|
||||||
|
.meta<OpenApiMeta>()
|
||||||
|
.create({
|
||||||
transformer: superjson,
|
transformer: superjson,
|
||||||
errorFormatter({ shape, error }) {
|
errorFormatter({ shape, error }) {
|
||||||
return {
|
return {
|
||||||
@@ -87,7 +98,7 @@ const t = initTRPC.context<typeof createTRPCContext>().create({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
|
* 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { type Prisma } from "@prisma/client";
|
import { type Prisma } from "@prisma/client";
|
||||||
import { type JsonObject } from "type-fest";
|
import { JsonValue, type JsonObject } from "type-fest";
|
||||||
import modelProviders from "~/modelProviders/modelProviders";
|
import modelProviders from "~/modelProviders/modelProviders";
|
||||||
import { prisma } from "~/server/db";
|
import { prisma } from "~/server/db";
|
||||||
import { wsConnection } from "~/utils/wsConnection";
|
import { wsConnection } from "~/utils/wsConnection";
|
||||||
import { runEvalsForOutput } from "../utils/evaluations";
|
import { runEvalsForOutput } from "../utils/evaluations";
|
||||||
import hashPrompt from "../utils/hashPrompt";
|
import hashObject from "../utils/hashObject";
|
||||||
import defineTask from "./defineTask";
|
import defineTask from "./defineTask";
|
||||||
import parsePromptConstructor from "~/promptConstructor/parse";
|
import parsePromptConstructor from "~/promptConstructor/parse";
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ export const queryModel = defineTask<QueryModelJob>("queryModel", async (task) =
|
|||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const inputHash = hashPrompt(prompt);
|
const inputHash = hashObject(prompt as JsonValue);
|
||||||
|
|
||||||
let modelResponse = await prisma.modelResponse.create({
|
let modelResponse = await prisma.modelResponse.create({
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { prisma } from "../db";
|
import { prisma } from "../db";
|
||||||
import { type JsonObject } from "type-fest";
|
import { type JsonObject } from "type-fest";
|
||||||
import hashPrompt from "./hashPrompt";
|
import hashObject from "./hashObject";
|
||||||
import { omit } from "lodash-es";
|
import { omit } from "lodash-es";
|
||||||
import { queueQueryModel } from "../tasks/queryModel.task";
|
import { queueQueryModel } from "../tasks/queryModel.task";
|
||||||
import parsePromptConstructor from "~/promptConstructor/parse";
|
import parsePromptConstructor from "~/promptConstructor/parse";
|
||||||
@@ -57,7 +57,7 @@ export const generateNewCell = async (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputHash = hashPrompt(parsedConstructFn);
|
const inputHash = hashObject(parsedConstructFn);
|
||||||
|
|
||||||
cell = await prisma.scenarioVariantCell.create({
|
cell = await prisma.scenarioVariantCell.create({
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
import { type JsonValue } from "type-fest";
|
import { type JsonValue } from "type-fest";
|
||||||
import { ParsedPromptConstructor } from "~/promptConstructor/parse";
|
|
||||||
|
|
||||||
function sortKeys(obj: JsonValue): JsonValue {
|
function sortKeys(obj: JsonValue): JsonValue {
|
||||||
if (typeof obj !== "object" || obj === null) {
|
if (typeof obj !== "object" || obj === null) {
|
||||||
@@ -25,9 +24,17 @@ function sortKeys(obj: JsonValue): JsonValue {
|
|||||||
return sortedObj;
|
return sortedObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function hashPrompt(prompt: ParsedPromptConstructor<any>): string {
|
export function hashRequest(organizationId: string, reqPayload: JsonValue): string {
|
||||||
|
const obj = {
|
||||||
|
organizationId,
|
||||||
|
reqPayload,
|
||||||
|
};
|
||||||
|
return hashObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function hashObject(obj: JsonValue): string {
|
||||||
// Sort object keys recursively
|
// Sort object keys recursively
|
||||||
const sortedObj = sortKeys(prompt as unknown as JsonValue);
|
const sortedObj = sortKeys(obj);
|
||||||
|
|
||||||
// Convert to JSON and hash it
|
// Convert to JSON and hash it
|
||||||
const str = JSON.stringify(sortedObj);
|
const str = JSON.stringify(sortedObj);
|
||||||
Reference in New Issue
Block a user