diff --git a/.env b/.env index c98868d..02ba082 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -APP_VERSION=1.0.0-alpha -DATABASE_URL="file:./dev.db" +VITE_APP_VERSION=1.0.0-alpha +DATABASE_URL="file:./dev.db" \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml deleted file mode 100644 index f782dbb..0000000 --- a/.github/workflows/pr.yml +++ /dev/null @@ -1,14 +0,0 @@ -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: install - run: bun install - - name: build - run: bun run clean && bun run build diff --git a/.gitignore b/.gitignore index dd87e2d..ce55f38 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,20 @@ +test-results node_modules -build + +# Output +.output +.vercel +.netlify +.wrangler +/.svelte-kit +/build + +# OS +.DS_Store +Thumbs.db + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* + +*storybook.log \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ab78a95 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..7ebb855 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ] +} diff --git a/.storybook/main.js b/.storybook/main.js new file mode 100644 index 0000000..f073993 --- /dev/null +++ b/.storybook/main.js @@ -0,0 +1,16 @@ +/** @type { import('@storybook/sveltekit').StorybookConfig } */ +const config = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|ts|svelte)'], + addons: [ + '@storybook/addon-svelte-csf', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + 'storybook-dark-mode' + ], + framework: { + name: '@storybook/sveltekit', + options: {} + } +}; +export default config; \ No newline at end of file diff --git a/.storybook/preview.js b/.storybook/preview.js new file mode 100644 index 0000000..747af9c --- /dev/null +++ b/.storybook/preview.js @@ -0,0 +1,13 @@ +/** @type { import('@storybook/svelte').Preview } */ +const preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i + } + } + } +}; + +export default preview; \ No newline at end of file diff --git a/README.md b/README.md index 9bfae56..8aff12f 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,38 @@ -# Hestia +# sv -To install dependencies: +Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli). + +## Creating a project + +If you're seeing this, you've probably already done this step. Congrats! ```bash -bun install +# create a new project in the current directory +bunx sv create + +# create a new project in my-app +bunx sv create my-app ``` -To run: +## Developing + +Once you've created a project and installed dependencies with `bun install`, start a development server: ```bash -bun run src/index.ts +bun run dev + +# or start the server and open the app in a new browser tab +bun run dev -- --open ``` -## Stack +## Building -- **Bun** Package manager -- **Yoga** GraphQL Server -- **Pothos** GraphQL Schema Builder -- **Prisma** Database ORM -- **Pino** Logger -- **Zod** Schema validation +To create a production version of your app: + +```bash +bun run build +``` + +You can preview the production build with `bun run preview`. + +> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment. diff --git a/bun.lockb b/bun.lockb index e9ebac8..37b9108 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/e2e/demo.test.ts b/e2e/demo.test.ts new file mode 100644 index 0000000..9985ce1 --- /dev/null +++ b/e2e/demo.test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('home page has expected h1', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('h1')).toBeVisible(); +}); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..aa5987f --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,34 @@ +import prettier from 'eslint-config-prettier'; +import js from '@eslint/js'; +import { includeIgnoreFile } from '@eslint/compat'; +import svelte from 'eslint-plugin-svelte'; +import globals from 'globals'; +import { fileURLToPath } from 'node:url'; +import ts from 'typescript-eslint'; +const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url)); + +export default ts.config( + includeIgnoreFile(gitignorePath), + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs['flat/recommended'], + prettier, + ...svelte.configs['flat/prettier'], + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + } + }, + { + files: ['**/*.svelte'], + + languageOptions: { + parserOptions: { + parser: ts.parser + } + } + } +); diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 9add6b6..0000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check - -import eslint from '@eslint/js'; -import tseslint from 'typescript-eslint'; -// @ts-expect-error No type-def -import eslintConfigPrettier from 'eslint-config-prettier'; - -export default tseslint.config( - { files: ['{app,src}/**/*.{js,mjs,ts}'] }, - { ignores: ['build/*'] }, - eslint.configs.recommended, - tseslint.configs.recommended, - eslintConfigPrettier -); \ No newline at end of file diff --git a/package.json b/package.json index 8d56df0..ecc37ab 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,66 @@ { "name": "hestia", - "module": "src/index.ts", + "version": "0.0.1", "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": "", + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "format": "prettier --write .", + "lint": "prettier --check . && eslint .", + "test:unit": "vitest", + "test": "npm run test:unit -- --run && npm run test:e2e", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build", + "test:e2e": "playwright test", "prisma:generate": "prisma generate" }, "devDependencies": { - "@eslint/js": "^9.16.0", - "@types/bun": "latest", - "eslint": "^9.16.0", + "@chromatic-com/storybook": "^3.2.2", + "@eslint/compat": "^1.2.3", + "@playwright/test": "^1.45.3", + "@storybook/addon-essentials": "^8.4.7", + "@storybook/addon-interactions": "^8.4.7", + "@storybook/addon-svelte-csf": "^5.0.0-next.13", + "@storybook/blocks": "^8.4.7", + "@storybook/svelte": "^8.4.7", + "@storybook/sveltekit": "^8.4.7", + "@storybook/test": "^8.4.7", + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/kit": "^2.9.0", + "@sveltejs/vite-plugin-svelte": "^5.0.0", + "autoprefixer": "^10.4.20", + "eslint": "^9.7.0", "eslint-config-prettier": "^9.1.0", - "prettier": "3.4.1", + "eslint-plugin-svelte": "^2.36.0", + "globals": "^15.0.0", + "prettier": "^3.3.2", + "prettier-plugin-svelte": "^3.2.6", + "prettier-plugin-tailwindcss": "^0.6.5", "prisma": "^6.0.1", - "typescript-eslint": "^8.17.0" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "storybook": "^8.4.7", + "svelte": "^5.0.0", + "svelte-check": "^4.0.0", + "tailwindcss": "^3.4.9", + "typescript": "^5.0.0", + "typescript-eslint": "^8.0.0", + "vite": "^6.0.0", + "vitest": "^2.0.4" }, "dependencies": { "@pothos/core": "^4.3.0", "@pothos/plugin-prisma": "^4.4.0", "@prisma/client": "6.0.1", + "@tailwindcss/typography": "^0.5.15", + "@types/bun": "^1.1.14", "graphql": "^16.9.0", "graphql-yoga": "^5.10.4", "lucia": "^3.2.2", "pino": "^9.5.0", "pino-pretty": "^13.0.0", - "zod": "^3.23.8" + "storybook-dark-mode": "^4.0.2", + "zod": "^3.24.0" } -} +} \ No newline at end of file diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..d76ea26 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + webServer: { + command: 'npm run build && npm run preview', + port: 4173 + }, + + testDir: 'e2e' +}); diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..0f77216 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/prettier.config.mjs b/prettier.config.mjs deleted file mode 100644 index 674afc2..0000000 --- a/prettier.config.mjs +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @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/prisma/dev.db b/prisma/dev.db index 33bbdb7..14dfc11 100644 Binary files a/prisma/dev.db and b/prisma/dev.db differ diff --git a/prisma/dev.db-journal b/prisma/dev.db-journal index 8c85613..be0024e 100644 Binary files a/prisma/dev.db-journal and b/prisma/dev.db-journal differ diff --git a/prisma/migrations/20241202163245_init/migration.sql b/prisma/migrations/20241210153750_init/migration.sql similarity index 100% rename from prisma/migrations/20241202163245_init/migration.sql rename to prisma/migrations/20241210153750_init/migration.sql diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 0f11436..0cd53f5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -28,4 +28,4 @@ model Post { published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int -} +} \ No newline at end of file diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..a31e444 --- /dev/null +++ b/src/app.css @@ -0,0 +1,3 @@ +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; +@import 'tailwindcss/utilities'; diff --git a/src/app.d.ts b/src/app.d.ts new file mode 100644 index 0000000..da08e6d --- /dev/null +++ b/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://svelte.dev/docs/kit/types#app.d.ts +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..77a5ff5 --- /dev/null +++ b/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/src/demo.spec.ts b/src/demo.spec.ts new file mode 100644 index 0000000..e07cbbd --- /dev/null +++ b/src/demo.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest'; + +describe('sum test', () => { + it('adds 1 + 2 to equal 3', () => { + expect(1 + 2).toBe(3); + }); +}); diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 8d71ef1..0000000 --- a/src/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -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', - }); - }, -}); - -logger.info(`Server is running on: ${server.url}${yoga.graphqlEndpoint}`); diff --git a/src/lib/components/Button.stories.svelte b/src/lib/components/Button.stories.svelte new file mode 100644 index 0000000..9403409 --- /dev/null +++ b/src/lib/components/Button.stories.svelte @@ -0,0 +1,30 @@ + + + \ No newline at end of file diff --git a/src/lib/components/Button.svelte b/src/lib/components/Button.svelte new file mode 100644 index 0000000..995f0a7 --- /dev/null +++ b/src/lib/components/Button.svelte @@ -0,0 +1,51 @@ + + + + + \ No newline at end of file diff --git a/src/lib/components/Loader.stories.svelte b/src/lib/components/Loader.stories.svelte new file mode 100644 index 0000000..27ef46b --- /dev/null +++ b/src/lib/components/Loader.stories.svelte @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/lib/components/Loader.svelte b/src/lib/components/Loader.svelte new file mode 100644 index 0000000..b855fec --- /dev/null +++ b/src/lib/components/Loader.svelte @@ -0,0 +1,51 @@ + + + + + \ No newline at end of file diff --git a/src/lib/components/Navbar.stories.svelte b/src/lib/components/Navbar.stories.svelte new file mode 100644 index 0000000..fe5c161 --- /dev/null +++ b/src/lib/components/Navbar.stories.svelte @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/src/lib/components/Navbar.svelte b/src/lib/components/Navbar.svelte new file mode 100644 index 0000000..757b744 --- /dev/null +++ b/src/lib/components/Navbar.svelte @@ -0,0 +1,31 @@ + + +
+ +
+ + \ No newline at end of file diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts new file mode 100644 index 0000000..1689ba6 --- /dev/null +++ b/src/lib/components/index.ts @@ -0,0 +1 @@ +export * from './Navbar.svelte'; \ No newline at end of file diff --git a/src/config/index.ts b/src/lib/config/index.ts similarity index 56% rename from src/config/index.ts rename to src/lib/config/index.ts index ad70abe..b87d270 100644 --- a/src/config/index.ts +++ b/src/lib/config/index.ts @@ -1,4 +1,4 @@ -import { logger } from '@lib/logger'; +import { logger } from '$lib/logger'; import { z } from 'zod'; export interface Configuration { @@ -8,15 +8,17 @@ export interface Configuration { export const LoadConfig = (): Configuration => { const { success, data, error } = z .object({ - APP_VERSION: z.string().default('development'), + VITE_APP_VERSION: z.string().default('development') }) - .safeParse(process.env); + .safeParse(import.meta.env); if (!success) { logger.error(error.message); } return { - app_version: data!.APP_VERSION, + app_version: data!.VITE_APP_VERSION }; }; + +export const Config = LoadConfig(); \ No newline at end of file diff --git a/src/lib/index.ts b/src/lib/index.ts new file mode 100644 index 0000000..e5efcb2 --- /dev/null +++ b/src/lib/index.ts @@ -0,0 +1,2 @@ +// place files you want to import through the `$lib` alias in this folder. +export * from './components'; \ No newline at end of file diff --git a/lib/logger/index.ts b/src/lib/logger/index.ts similarity index 98% rename from lib/logger/index.ts rename to src/lib/logger/index.ts index 7dea51d..38ed4aa 100644 --- a/lib/logger/index.ts +++ b/src/lib/logger/index.ts @@ -19,5 +19,5 @@ export const yogaLogger: YogaLogger = { error(...args) { // @ts-expect-error types dont match logger.error(...args); - }, -}; + } +}; \ No newline at end of file diff --git a/src/lib/pothos/index.ts b/src/lib/pothos/index.ts new file mode 100644 index 0000000..c8ee3d6 --- /dev/null +++ b/src/lib/pothos/index.ts @@ -0,0 +1,65 @@ +import { prisma } from '$lib/prisma'; +import { Context } from '$lib/yoga/context'; +import SchemaBuilder from '@pothos/core'; +import PrismaPlugin, { type PrismaTypesFromClient } from '@pothos/plugin-prisma'; + +type ContextType = ReturnType; + +export const builder = new SchemaBuilder<{ + Context: ContextType; + 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' + } +}); + +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') + }) +}); + +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(); + } + }) + }) +}); + +export const Schema = builder.toSchema(); \ No newline at end of file diff --git a/src/prisma/index.ts b/src/lib/prisma/index.ts similarity index 53% rename from src/prisma/index.ts rename to src/lib/prisma/index.ts index 9b6c4ce..fbb7b51 100644 --- a/src/prisma/index.ts +++ b/src/lib/prisma/index.ts @@ -1,3 +1,3 @@ import { PrismaClient } from '@prisma/client'; -export const prisma = new PrismaClient(); +export const prisma = new PrismaClient(); \ No newline at end of file diff --git a/src/lib/yoga/context.ts b/src/lib/yoga/context.ts new file mode 100644 index 0000000..d9a6a68 --- /dev/null +++ b/src/lib/yoga/context.ts @@ -0,0 +1,7 @@ +import { Config } from '$lib/config'; +import type { YogaInitialContext } from 'graphql-yoga'; + +export const Context = (initialContext: YogaInitialContext) => ({ + ...initialContext, + config: Config +}); \ No newline at end of file diff --git a/src/lib/yoga/index.ts b/src/lib/yoga/index.ts new file mode 100644 index 0000000..b008b24 --- /dev/null +++ b/src/lib/yoga/index.ts @@ -0,0 +1,14 @@ +import { yogaLogger } from '$lib/logger'; +import { Schema } from '$lib/pothos'; +import type { RequestEvent } from '@sveltejs/kit'; +import { createYoga } from 'graphql-yoga'; +import { Context } from './context'; + +export const Yoga = createYoga({ + context: Context, + schema: Schema, + graphqlEndpoint: '/api/graphql', + // Let Yoga use sveltekit's Response object + fetchAPI: { Response }, + logging: yogaLogger +}); \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..9b776b7 --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,6 @@ + + +{@render children()} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte new file mode 100644 index 0000000..fa25cf6 --- /dev/null +++ b/src/routes/+page.svelte @@ -0,0 +1,27 @@ + + +
+

Hestia

+ +
+ + \ No newline at end of file diff --git a/src/routes/api/graphql/+server.ts b/src/routes/api/graphql/+server.ts new file mode 100644 index 0000000..72aab8c --- /dev/null +++ b/src/routes/api/graphql/+server.ts @@ -0,0 +1,3 @@ +import { Yoga } from '$lib/yoga'; + +export { Yoga as GET, Yoga as POST }; \ No newline at end of file diff --git a/src/routes/app/+layout.svelte b/src/routes/app/+layout.svelte new file mode 100644 index 0000000..b0005e0 --- /dev/null +++ b/src/routes/app/+layout.svelte @@ -0,0 +1,8 @@ + + + +{@render children()} \ No newline at end of file diff --git a/src/routes/app/+page.svelte b/src/routes/app/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/yoga/builder.ts b/src/yoga/builder.ts deleted file mode 100644 index 750955c..0000000 --- a/src/yoga/builder.ts +++ /dev/null @@ -1,29 +0,0 @@ -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; -}>({ - 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 deleted file mode 100644 index fac5b95..0000000 --- a/src/yoga/context.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { LoadConfig } from '@app/config'; -import type { YogaInitialContext } from 'graphql-yoga'; - -export const context = (initialContext: YogaInitialContext) => { - const config = LoadConfig(); - return { - ...initialContext, - config, - }; -}; diff --git a/src/yoga/index.ts b/src/yoga/index.ts deleted file mode 100644 index 9dd62c3..0000000 --- a/src/yoga/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { yogaLogger } from "@lib/logger"; -import { createYoga } from "graphql-bun "; -import { context } from "./context"; -import { schema } from "./schema"; - -export const yoga = createYoga({ - schema, - context: context, - logging: yogaLogger, -}); diff --git a/src/yoga/schema.ts b/src/yoga/schema.ts deleted file mode 100644 index bb3006e..0000000 --- a/src/yoga/schema.ts +++ /dev/null @@ -1,43 +0,0 @@ -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 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(); - }, - }), - }), -}); - -export const schema = builder.toSchema(); diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..825b9e6 Binary files /dev/null and b/static/favicon.png differ diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..1295460 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,18 @@ +import adapter from '@sveltejs/adapter-auto'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + // Consult https://svelte.dev/docs/kit/integrations + // for more information about preprocessors + preprocess: vitePreprocess(), + + kit: { + // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. + // If your environment is not supported, or you settled on a specific environment, switch out the adapter. + // See https://svelte.dev/docs/kit/adapters for more information about adapters. + adapter: adapter() + } +}; + +export default config; diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..228b779 --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,16 @@ +import typography from '@tailwindcss/typography'; +import type { Config } from 'tailwindcss'; + +export default { + content: ['./src/**/*.{html,js,svelte,ts}'], + + theme: { + extend: { + fontFamily: { + display: ['Baskervville SC'] + } + } + }, + + plugins: [typography] +} satisfies Config; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 75671cb..0b2d886 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,36 +1,19 @@ { + "extends": "./.svelte-kit/tsconfig.json", "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, - - // Best practices - "strict": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false, - - // Path mapping - "baseUrl": ".", - "paths": { - "@app": ["./src"], - "@app/*": ["./src/*"], - "@lib": ["./lib"], - "@lib/*": ["./lib/*"] - } + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" } + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in } diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..d76fc8a --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; +import { sveltekit } from '@sveltejs/kit/vite'; + +export default defineConfig({ + plugins: [sveltekit()], + + test: { + include: ['src/**/*.{test,spec}.{js,ts}'] + } +});