diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..97a9e37 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = false + +[*.{js,ts}] +indent_style = tab +indent_size = 4 + +[{*.{yml,mjs,json}}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c1623fb..f782dbb 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,12 +1,14 @@ name: PR Checks on: [pull_request] jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - name: build - run: bun run clean && bun run build + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + - name: install + run: bun install + - name: build + run: bun run clean && bun run build diff --git a/bun.lockb b/bun.lockb index 196c00f..061a462 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..438600d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,13 @@ +import pluginJs from '@eslint/js'; +import eslintConfigPrettier from 'eslint-config-prettier'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { files: ['**/*.{js,mjs,cjs,ts}'] }, + { languageOptions: { globals: globals.browser } }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + eslintConfigPrettier, +]; diff --git a/lib/logger/index.ts b/lib/logger/index.ts index 8359612..7dea51d 100644 --- a/lib/logger/index.ts +++ b/lib/logger/index.ts @@ -1,23 +1,23 @@ -import { type YogaLogger } from "graphql-yoga"; -import pino from "pino"; +import { type YogaLogger } from 'graphql-yoga'; +import pino from 'pino'; export const logger = pino(); export const yogaLogger: YogaLogger = { - debug(...args) { - // @ts-ignore - logger.debug(...args); - }, - info(...args) { - // @ts-ignore - logger.info(...args); - }, - warn(...args) { - // @ts-ignore - logger.warn(...args); - }, - error(...args) { - // @ts-ignore - logger.error(...args); - }, + debug(...args) { + // @ts-expect-error types dont match + logger.debug(...args); + }, + info(...args) { + // @ts-expect-error types dont match + logger.info(...args); + }, + warn(...args) { + // @ts-expect-error types dont match + logger.warn(...args); + }, + error(...args) { + // @ts-expect-error types dont match + logger.error(...args); + }, }; diff --git a/package.json b/package.json index 780797a..d7f90dd 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,36 @@ { - "name": "hestia", - "module": "src/index.ts", - "type": "module", - "scripts": { - "build": "bun build ./src/index.ts --outdir ./build", - "clean": "rm -rf ./build", - "dev": "bun --watch src/index.ts | pino-pretty", - "prisma:generate": "prisma generate" - }, - "devDependencies": { - "@types/bun": "latest", - "prisma": "^6.0.1" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "dependencies": { - "@pothos/core": "^4.3.0", - "@pothos/plugin-prisma": "^4.4.0", - "@prisma/client": "6.0.1", - "graphql": "^16.9.0", - "graphql-yoga": "^5.10.4", - "pino": "^9.5.0", - "pino-pretty": "^13.0.0", - "zod": "^3.23.8" - } + "name": "hestia", + "module": "src/index.ts", + "type": "module", + "scripts": { + "build": "bun build ./src/index.ts --outdir ./build", + "clean": "rm -rf ./build", + "dev": "bun --watch src/index.ts | pino-pretty", + "format": "prettier . --write", + "lint": "", + "prisma:generate": "prisma generate" + }, + "devDependencies": { + "@eslint/js": "^9.16.0", + "@types/bun": "latest", + "eslint": "^9.16.0", + "eslint-config-prettier": "^9.1.0", + "globals": "^15.13.0", + "prettier": "3.4.1", + "prisma": "^6.0.1", + "typescript-eslint": "^8.17.0" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@pothos/core": "^4.3.0", + "@pothos/plugin-prisma": "^4.4.0", + "@prisma/client": "6.0.1", + "graphql": "^16.9.0", + "graphql-yoga": "^5.10.4", + "pino": "^9.5.0", + "pino-pretty": "^13.0.0", + "zod": "^3.23.8" + } } diff --git a/prettier.config.mjs b/prettier.config.mjs new file mode 100644 index 0000000..674afc2 --- /dev/null +++ b/prettier.config.mjs @@ -0,0 +1,13 @@ +/** + * @see https://prettier.io/docs/en/configuration.html + * @type {import("prettier").Config} + */ +const config = { + trailingComma: 'es5', + tabWidth: 4, + useTabs: true, + semi: true, + singleQuote: true, +}; + +export default config; diff --git a/src/config/index.ts b/src/config/index.ts index f4c0bc5..ad70abe 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,22 +1,22 @@ -import { logger } from "@lib/logger"; -import { z } from "zod"; +import { logger } from '@lib/logger'; +import { z } from 'zod'; export interface Configuration { - app_version: string; + app_version: string; } export const LoadConfig = (): Configuration => { - const { success, data, error } = z - .object({ - APP_VERSION: z.string().default("development"), - }) - .safeParse(process.env); + const { success, data, error } = z + .object({ + APP_VERSION: z.string().default('development'), + }) + .safeParse(process.env); - if (!success) { - logger.error(error.message); - } + if (!success) { + logger.error(error.message); + } - return { - app_version: data!.APP_VERSION, - }; + return { + app_version: data!.APP_VERSION, + }; }; diff --git a/src/index.ts b/src/index.ts index 897da9b..8d71ef1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,15 @@ -import { logger } from "@lib/logger"; -import { yoga } from "./yoga"; +import { logger } from '@lib/logger'; +import { yoga } from './yoga'; const server = Bun.serve({ - fetch: yoga.fetch, - error: (error) => { - logger.error(error.message); - return new Response("", { - status: 500, - statusText: "You fucked the goose", - }); - }, + fetch: yoga.fetch, + error: (error) => { + logger.error(error.message); + return new Response('', { + status: 500, + statusText: 'You fucked the goose', + }); + }, }); logger.info(`Server is running on: ${server.url}${yoga.graphqlEndpoint}`); diff --git a/src/prisma/index.ts b/src/prisma/index.ts index 901f3a0..9b6c4ce 100644 --- a/src/prisma/index.ts +++ b/src/prisma/index.ts @@ -1,3 +1,3 @@ -import { PrismaClient } from "@prisma/client"; +import { PrismaClient } from '@prisma/client'; export const prisma = new PrismaClient(); diff --git a/src/yoga/builder.ts b/src/yoga/builder.ts index 565bdc3..750955c 100644 --- a/src/yoga/builder.ts +++ b/src/yoga/builder.ts @@ -1,29 +1,29 @@ -import type { Configuration } from "@app/config"; -import { prisma } from "@app/prisma"; -import SchemaBuilder from "@pothos/core"; +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 PrismaTypesFromClient, +} from '@pothos/plugin-prisma'; +import type { YogaInitialContext } from 'graphql-yoga'; type Context = YogaInitialContext & { - config: Configuration; + config: Configuration; }; export const builder = new SchemaBuilder<{ - Context: Context; - PrismaTypes: PrismaTypesFromClient; + Context: Context; + PrismaTypes: PrismaTypesFromClient; }>({ - 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", - }, + 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', + }, }); diff --git a/src/yoga/context.ts b/src/yoga/context.ts index bc85aa7..fac5b95 100644 --- a/src/yoga/context.ts +++ b/src/yoga/context.ts @@ -1,10 +1,10 @@ -import { LoadConfig } from "@app/config"; -import type { YogaInitialContext } from "graphql-yoga"; +import { LoadConfig } from '@app/config'; +import type { YogaInitialContext } from 'graphql-yoga'; export const context = (initialContext: YogaInitialContext) => { - const config = LoadConfig(); - return { - ...initialContext, - config, - }; + const config = LoadConfig(); + return { + ...initialContext, + config, + }; }; diff --git a/src/yoga/index.ts b/src/yoga/index.ts index 8d113ba..35233ab 100644 --- a/src/yoga/index.ts +++ b/src/yoga/index.ts @@ -1,10 +1,10 @@ -import { yogaLogger } from "@lib/logger"; -import { createYoga } from "graphql-yoga"; -import { context } from "./context"; -import { schema } from "./schema"; +import { yogaLogger } from '@lib/logger'; +import { createYoga } from 'graphql-yoga'; +import { context } from './context'; +import { schema } from './schema'; export const yoga = createYoga({ - schema, - context: context, - logging: yogaLogger, + schema, + context: context, + logging: yogaLogger, }); diff --git a/src/yoga/schema.ts b/src/yoga/schema.ts index f72cc19..bb3006e 100644 --- a/src/yoga/schema.ts +++ b/src/yoga/schema.ts @@ -1,43 +1,43 @@ -import { prisma } from "@app/prisma"; -import { builder } from "./builder"; +import { prisma } from '@app/prisma'; +import { builder } from './builder'; -const User = builder.prismaObject("User", { - fields: (t) => ({ - id: t.exposeID("id"), - email: t.exposeString("email"), - name: t.exposeString("name"), - posts: t.relation("posts"), - }), +const User = builder.prismaObject('User', { + fields: (t) => ({ + id: t.exposeID('id'), + email: t.exposeString('email'), + name: t.exposeString('name'), + posts: t.relation('posts'), + }), }); -const Post = builder.prismaObject("Post", { - fields: (t) => ({ - id: t.exposeID("id"), - title: t.exposeString("title"), - content: t.exposeString("content"), - published: t.exposeBoolean("published"), - author: t.relation("author"), - }), +const Post = builder.prismaObject('Post', { + fields: (t) => ({ + id: t.exposeID('id'), + title: t.exposeString('title'), + content: t.exposeString('content'), + published: t.exposeBoolean('published'), + author: t.relation('author'), + }), }); builder.queryType({ - fields: (t) => ({ - version: t.string({ - resolve: (parent, args, context) => context.config.app_version, - }), - users: t.prismaField({ - type: [User], - resolve: async () => { - return await prisma.user.findMany(); - }, - }), - posts: t.prismaField({ - type: [Post], - resolve: async () => { - return await prisma.post.findMany(); - }, - }), - }), + fields: (t) => ({ + version: t.string({ + resolve: (parent, args, context) => context.config.app_version, + }), + users: t.prismaField({ + type: [User], + resolve: async () => { + return await prisma.user.findMany(); + }, + }), + posts: t.prismaField({ + type: [Post], + resolve: async () => { + return await prisma.post.findMany(); + }, + }), + }), }); export const schema = builder.toSchema(); diff --git a/tsconfig.json b/tsconfig.json index c2f3b95..75671cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,36 +1,36 @@ { - "compilerOptions": { - // Enable latest features - "lib": ["ESNext", "DOM"], - "target": "ESNext", - "module": "ESNext", - "moduleDetection": "force", - "jsx": "react-jsx", - "allowJs": true, + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, - // Best practices - "strict": true, - "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false, + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, - // Path mapping - "baseUrl": ".", - "paths": { - "@app": ["./src"], - "@app/*": ["./src/*"], - "@lib": ["./lib"], - "@lib/*": ["./lib/*"] - } - } + // Path mapping + "baseUrl": ".", + "paths": { + "@app": ["./src"], + "@app/*": ["./src/*"], + "@lib": ["./lib"], + "@lib/*": ["./lib/*"] + } + } }