Skip to content
This repository was archived by the owner on Mar 10, 2024. It is now read-only.

Commit 5e4fd2f

Browse files
committed
refactor: Validate headers and env
1 parent 62cda72 commit 5e4fd2f

File tree

6 files changed

+44
-19
lines changed

6 files changed

+44
-19
lines changed

packages/api/context.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import { cryptoHash, decrypt } from '@supaglue/core/lib';
33
import prisma from '@supaglue/db';
4+
import { createEnv } from '@t3-oss/env-core';
45
import { TRPCError, initTRPC } from '@trpc/server';
56
import type { OpenApiMeta } from '@usevenice/trpc-openapi';
67
import { z } from 'zod';
@@ -12,20 +13,33 @@ extendZodWithOpenApi(z);
1213

1314
export { z };
1415

15-
export function createContext(opts: {
16-
headers: { 'x-api-key': string; 'x-customer-id': string; 'x-provider-name': string };
17-
}) {
18-
return { ...opts, prisma };
16+
export const env = createEnv({
17+
server: {
18+
/** Reqruired for prisma */
19+
SUPAGLUE_DATABASE_URL: z.string().url(),
20+
/* Required for encryption & decryption */
21+
SUPAGLUE_API_ENCRYPTION_SECRET: z.string().min(1),
22+
},
23+
runtimeEnv: process.env,
24+
});
25+
26+
export function createContext(opts: { headers: unknown }) {
27+
const headers = z
28+
.object({
29+
'x-api-key': z.string().optional(),
30+
'x-customer-id': z.string().optional(),
31+
'x-provider-name': z.string().optional(),
32+
})
33+
.parse(opts.headers);
34+
35+
return { headers, env, prisma };
1936
}
2037

2138
/**
2239
* Initialization of tRPC backend
2340
* Should be done only once per backend!
2441
*/
25-
export const t = initTRPC
26-
.context<{ headers: { 'x-api-key': string; 'x-customer-id': string; 'x-provider-name': string } }>()
27-
.meta<OpenApiMeta>()
28-
.create();
42+
export const t = initTRPC.context<ReturnType<typeof createContext>>().meta<OpenApiMeta>().create();
2943

3044
export const authedProcedure = t.procedure.use(async ({ next, ctx }) => {
3145
if (!ctx.headers['x-api-key']) {
@@ -76,6 +90,3 @@ export const remoteProcedure = authedProcedure.use(async ({ next, ctx }) => {
7690

7791
return next({ ctx: { ...ctx, provider, providerName, customerId } });
7892
});
79-
export type RemoteProcedureContext = ReturnType<(typeof remoteProcedure)['query']>['_def']['_ctx_out'];
80-
81-
export type MaybePromise<T> = T | Promise<T>;

packages/api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"dependencies": {
55
"@supaglue/core": "workspace:*",
66
"@supaglue/db": "workspace:*",
7+
"@t3-oss/env-core": "^0.7.1",
78
"@trpc/server": "^10.44.1",
89
"@usevenice/trpc-openapi": "^1.3.8",
910
"trpc-panel": "^1.3.4",

packages/api/providers/apollo.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export const createApolloProvider = z
1313
get: (id) =>
1414
apollo.GET('/v1/contacts/{id}', { params: { path: { id } } }).then(({ data: { contact } }) => contact),
1515
},
16-
logCall: (input) => {
17-
console.log('Call ID:', input);
16+
logCall: async (input) => {
17+
console.log('log call input:', input);
1818
return { id: '1', note: 'test', contact_id: '1' };
1919
},
2020
} satisfies EngagementProvider;

packages/api/router.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createOpenApiHttpHandler, generateOpenApiDocument } from '@usevenice/tr
33
import http from 'http';
44
import { renderTrpcPanel } from 'trpc-panel';
55
import { z } from 'zod';
6-
import { t } from './context';
6+
import { createContext, t } from './context';
77
import { engagementRouter } from './routers/engagement';
88

99
export const metaRouter = t.router({
@@ -33,7 +33,7 @@ if (require.main === module) {
3333
createHTTPServer({
3434
router: appRouter,
3535
// eslint-disable-next-line @typescript-eslint/no-explicit-any
36-
createContext: ({ req }) => ({ headers: req.headers as any }),
36+
createContext: ({ req }) => createContext({ headers: req.headers }),
3737
middleware(req, res, next) {
3838
if (req.url === '/_panel') {
3939
res.end(renderTrpcPanel(appRouter, { url: 'http://localhost:3000' }));
@@ -49,7 +49,7 @@ if (require.main === module) {
4949
createOpenApiHttpHandler({
5050
router: appRouter,
5151
// eslint-disable-next-line @typescript-eslint/no-explicit-any
52-
createContext: ({ req }) => ({ headers: req.headers as any }),
52+
createContext: ({ req }) => createContext({ headers: req.headers }),
5353
})
5454
)
5555
.listen(3001);

packages/api/routers/engagement.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { TRPCError } from '@trpc/server';
2-
import type { MaybePromise } from '../context';
32
import { remoteProcedure, t, z } from '../context';
43

54
const schemas = {
@@ -25,9 +24,9 @@ const schemas = {
2524

2625
export interface EngagementProvider {
2726
contacts: {
28-
get: (id: string) => MaybePromise<z.infer<typeof schemas.contact>>;
27+
get: (id: string) => Promise<z.infer<typeof schemas.contact>>;
2928
};
30-
logCall: (input: z.infer<typeof schemas.logCallInput>) => MaybePromise<z.infer<typeof schemas.call>>;
29+
logCall: (input: z.infer<typeof schemas.logCallInput>) => Promise<z.infer<typeof schemas.call>>;
3130
}
3231

3332
export const engagementRouter = t.router({

yarn.lock

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6339,6 +6339,7 @@ __metadata:
63396339
dependencies:
63406340
"@supaglue/core": "workspace:*"
63416341
"@supaglue/db": "workspace:*"
6342+
"@t3-oss/env-core": ^0.7.1
63426343
"@trpc/server": ^10.44.1
63436344
"@usevenice/trpc-openapi": ^1.3.8
63446345
trpc-panel: ^1.3.4
@@ -6879,6 +6880,19 @@ __metadata:
68796880
languageName: node
68806881
linkType: hard
68816882

6883+
"@t3-oss/env-core@npm:^0.7.1":
6884+
version: 0.7.1
6885+
resolution: "@t3-oss/env-core@npm:0.7.1"
6886+
peerDependencies:
6887+
typescript: ">=4.7.2"
6888+
zod: ^3.0.0
6889+
peerDependenciesMeta:
6890+
typescript:
6891+
optional: true
6892+
checksum: 1a8447f5009931eb24a2e653723acd817585539d882c6c97b1df590df605045dee0e9abb3e6af083ec1492a6c143469947c4e4fef8d6c4a7e64cdf61ee8748d0
6893+
languageName: node
6894+
linkType: hard
6895+
68826896
"@temporalio/activity@npm:1.8.6, @temporalio/activity@npm:^1.8.6":
68836897
version: 1.8.6
68846898
resolution: "@temporalio/activity@npm:1.8.6"

0 commit comments

Comments
 (0)