add zod validated configuration and context
This commit is contained in:
parent
aa2fc6e89a
commit
b645af1337
11 changed files with 76 additions and 27 deletions
2
.env
Normal file
2
.env
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
APP_VERSION=1.0.0-alpha
|
||||||
|
DATABASE_URL="file:./dev.db"
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1 @@
|
||||||
node_modules
|
node_modules
|
||||||
# Keep environment variables out of version control
|
|
||||||
.env
|
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,4 @@ bun run src/index.ts
|
||||||
- **Pothos**
|
- **Pothos**
|
||||||
- **Prisma** Database ORM
|
- **Prisma** Database ORM
|
||||||
- **Pino** Logger
|
- **Pino** Logger
|
||||||
|
- **Zod** Schema validation
|
||||||
|
|
|
||||||
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
|
|
@ -20,6 +20,7 @@
|
||||||
"graphql": "^16.9.0",
|
"graphql": "^16.9.0",
|
||||||
"graphql-yoga": "^5.10.4",
|
"graphql-yoga": "^5.10.4",
|
||||||
"pino": "^9.5.0",
|
"pino": "^9.5.0",
|
||||||
"pino-pretty": "^13.0.0"
|
"pino-pretty": "^13.0.0",
|
||||||
|
"zod": "^3.23.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
src/config/index.ts
Normal file
22
src/config/index.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { logger } from "@lib/logger";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export interface Configuration {
|
||||||
|
app_version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LoadConfig = (): Configuration => {
|
||||||
|
const { success, data, error } = z
|
||||||
|
.object({
|
||||||
|
APP_VERSION: z.string().default("development"),
|
||||||
|
})
|
||||||
|
.safeParse(process.env);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
logger.error(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
app_version: data!.APP_VERSION,
|
||||||
|
};
|
||||||
|
};
|
||||||
3
src/prisma/index.ts
Normal file
3
src/prisma/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
|
||||||
|
export const prisma = new PrismaClient();
|
||||||
29
src/yoga/builder.ts
Normal file
29
src/yoga/builder.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import type { Configuration } from "@app/config";
|
||||||
|
import { prisma } from "@app/prisma";
|
||||||
|
import SchemaBuilder from "@pothos/core";
|
||||||
|
import PrismaPlugin, {
|
||||||
|
type PrismaTypesFromClient,
|
||||||
|
} from "@pothos/plugin-prisma";
|
||||||
|
import type { YogaInitialContext } from "graphql-yoga";
|
||||||
|
|
||||||
|
type Context = YogaInitialContext & {
|
||||||
|
config: Configuration;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const builder = new SchemaBuilder<{
|
||||||
|
Context: Context;
|
||||||
|
PrismaTypes: PrismaTypesFromClient<typeof prisma>;
|
||||||
|
}>({
|
||||||
|
plugins: [PrismaPlugin],
|
||||||
|
prisma: {
|
||||||
|
client: prisma,
|
||||||
|
// defaults to false, uses /// comments from prisma schema as descriptions
|
||||||
|
// for object types, relations and exposed fields.
|
||||||
|
// descriptions can be omitted by setting description to false
|
||||||
|
exposeDescriptions: false,
|
||||||
|
// use where clause from prismaRelatedConnection for totalCount (defaults to true)
|
||||||
|
filterConnectionTotalCount: true,
|
||||||
|
// warn when not using a query parameter correctly
|
||||||
|
onUnusedQuery: process.env.NODE_ENV === "production" ? null : "warn",
|
||||||
|
},
|
||||||
|
});
|
||||||
10
src/yoga/context.ts
Normal file
10
src/yoga/context.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { LoadConfig } from "@app/config";
|
||||||
|
import type { YogaInitialContext } from "graphql-yoga";
|
||||||
|
|
||||||
|
export const context = (initialContext: YogaInitialContext) => {
|
||||||
|
const config = LoadConfig();
|
||||||
|
return {
|
||||||
|
...initialContext,
|
||||||
|
config,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { yogaLogger } from "@lib/logger";
|
import { yogaLogger } from "@lib/logger";
|
||||||
import { createYoga } from "graphql-yoga";
|
import { createYoga } from "graphql-yoga";
|
||||||
|
import { context } from "./context";
|
||||||
import { schema } from "./schema";
|
import { schema } from "./schema";
|
||||||
|
|
||||||
export const yoga = createYoga({
|
export const yoga = createYoga({
|
||||||
schema,
|
schema,
|
||||||
|
context: context,
|
||||||
logging: yogaLogger,
|
logging: yogaLogger,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,5 @@
|
||||||
import SchemaBuilder from "@pothos/core";
|
import { prisma } from "@app/prisma";
|
||||||
import PrismaPlugin, {
|
import { builder } from "./builder";
|
||||||
type PrismaTypesFromClient,
|
|
||||||
} from "@pothos/plugin-prisma";
|
|
||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
const builder = new SchemaBuilder<{
|
|
||||||
PrismaTypes: PrismaTypesFromClient<typeof prisma>;
|
|
||||||
}>({
|
|
||||||
plugins: [PrismaPlugin],
|
|
||||||
prisma: {
|
|
||||||
client: prisma,
|
|
||||||
// defaults to false, uses /// comments from prisma schema as descriptions
|
|
||||||
// for object types, relations and exposed fields.
|
|
||||||
// descriptions can be omitted by setting description to false
|
|
||||||
exposeDescriptions: false,
|
|
||||||
// use where clause from prismaRelatedConnection for totalCount (defaults to true)
|
|
||||||
filterConnectionTotalCount: true,
|
|
||||||
// warn when not using a query parameter correctly
|
|
||||||
onUnusedQuery: process.env.NODE_ENV === "production" ? null : "warn",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const User = builder.prismaObject("User", {
|
const User = builder.prismaObject("User", {
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
|
|
@ -44,6 +22,9 @@ const Post = builder.prismaObject("Post", {
|
||||||
|
|
||||||
builder.queryType({
|
builder.queryType({
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
|
version: t.string({
|
||||||
|
resolve: (parent, args, context) => context.config.app_version,
|
||||||
|
}),
|
||||||
users: t.prismaField({
|
users: t.prismaField({
|
||||||
type: [User],
|
type: [User],
|
||||||
resolve: async () => {
|
resolve: async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue