Init nuxt-starter

This commit is contained in:
2024-07-23 20:27:33 +02:00
commit 5c96b8eea0
17 changed files with 279 additions and 0 deletions

1
.env.example Normal file
View File

@@ -0,0 +1 @@
NUXT_SESSION_PASSWORD=

9
app/app.config.ts Normal file
View File

@@ -0,0 +1,9 @@
export default defineAppConfig({
ui: {
gray: 'neutral',
primary: 'gray',
icons: {
dynamic: true
}
}
})

72
app/app.vue Normal file
View File

@@ -0,0 +1,72 @@
<template>
<Html
:dir="head.htmlAttrs.dir"
:lang="head.htmlAttrs.lang"
>
<Head>
<template
v-for="link in head.link"
:key="link.id"
>
<Link
:id="link.id"
:href="link.href"
:hreflang="link.hreflang"
:rel="link.rel"
/>
</template>
<template
v-for="meta in head.meta"
:key="meta.id"
>
<Meta
:id="meta.id"
:content="meta.content"
:property="meta.property"
/>
</template>
</Head>
<Body>
<div>
<NuxtLoadingIndicator color="#808080" />
<UContainer>
<NuxtPage />
</UContainer>
</div>
</Body>
</Html>
</template>
<script lang="ts" setup>
useHead({
link: [{ rel: 'icon', type: 'image/png', href: '/favicon.ico' }]
})
const head = useLocaleHead({
addDirAttribute: true,
identifierAttribute: 'id',
addSeoAttributes: true
})
</script>
<style>
body {
font-family: 'DM Sans', sans-serif;
@apply h-full w-full text-neutral-700 dark:text-neutral-300;
}
.page-enter-active,
.page-leave-active {
transition: all 0.2s;
}
.page-leave-to {
opacity: 0;
transform: translateY(-5px);
}
.page-enter-from {
opacity: 0;
transform: translateY(5px);
}
</style>

13
app/pages/index.vue Normal file
View File

@@ -0,0 +1,13 @@
<script setup lang="ts">
</script>
<template>
<div>
<h1>Home</h1>
</div>
</template>
<style scoped>
</style>

7
drizzle.config.ts Normal file
View File

@@ -0,0 +1,7 @@
import type { Config } from 'drizzle-kit'
export default {
dialect: 'sqlite',
schema: './server/database/schema.ts',
out: './server/database/migrations'
} satisfies Config

6
eslint.config.mjs Normal file
View File

@@ -0,0 +1,6 @@
// @ts-check
import withNuxt from './.nuxt/eslint.config.mjs'
export default withNuxt(
// Your custom configs here
)

3
server/api/test.ts Normal file
View File

@@ -0,0 +1,3 @@
export default defineEventHandler(() => {
return { hello: 'API' }
})

View File

@@ -0,0 +1,5 @@
CREATE TABLE `users` (
`id` integer PRIMARY KEY NOT NULL,
`name` text DEFAULT '',
`created_at` text DEFAULT (CURRENT_DATE)
);

View File

@@ -0,0 +1,49 @@
{
"version": "6",
"dialect": "sqlite",
"id": "ef8e28cd-73a1-4801-9a0b-7e80169a57c0",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"users": {
"name": "users",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "''"
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_DATE)"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "6",
"when": 1721758030188,
"tag": "0000_hot_thunderball",
"breakpoints": true
}
]
}

View File

@@ -0,0 +1,8 @@
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
import { sql } from 'drizzle-orm'
export const users = sqliteTable('users', {
id: integer('id').primaryKey(),
name: text('name').default(''),
createdAt: text('created_at').default(sql`(CURRENT_DATE)`)
})

View File

@@ -0,0 +1,16 @@
import { consola } from 'consola'
import { migrate } from 'drizzle-orm/d1/migrator'
export default defineNitroPlugin(async () => {
if (!import.meta.dev) return
onHubReady(async () => {
await migrate(useDB(), { migrationsFolder: 'server/database/migrations' })
.then(() => {
consola.success('Database migrations done')
})
.catch((err) => {
consola.error('Database migrations failed', err)
})
})
})

View File

@@ -0,0 +1,19 @@
export default oauth.githubEventHandler({
config: {
emailRequired: true
},
async onSuccess(event, { user }) {
await setUserSession(event, {
user: {
name: user.name,
imageUrl: user.avatar_url,
email: user.email
}
})
return sendRedirect(event, '/')
},
onError(event, error) {
console.error('GitHub OAuth error:', error)
return sendRedirect(event, '/')
}
})

View File

@@ -0,0 +1,23 @@
export default oauth.googleEventHandler({
config: {
authorizationParams: {
access_type: 'offline'
}
},
async onSuccess(event, { user }) {
await setUserSession(event, {
user: {
name: user.name,
imageUrl: user.picture,
email: user.email
}
})
return sendRedirect(event, '/')
},
// Optional, will return a json error and 401 status code by default
onError(event, error) {
console.error('Google OAuth error:', error)
return sendRedirect(event, '/')
}
})

10
server/utils/db.ts Normal file
View File

@@ -0,0 +1,10 @@
import { drizzle } from 'drizzle-orm/d1'
import * as schema from '../database/schema'
export { sql, eq, and, or, asc, desc, sum } from 'drizzle-orm'
export const tables = schema
export function useDB() {
return drizzle(hubDatabase(), { schema })
}

25
tailwind.config.ts Normal file
View File

@@ -0,0 +1,25 @@
import type { Config } from 'tailwindcss'
import typography from '@tailwindcss/typography'
export default <Partial<Config>>{
content: [
'./components/**/*.{vue,js,ts}',
'./layouts/**/*.vue',
'./pages/**/*.vue',
'./composables/**/*.{js,ts}',
'./plugins/**/*.{js,ts}',
'./utils/**/*.{js,ts}',
'./App.{js,ts,vue}',
'./app.{js,ts,vue}',
'./Error.{js,ts,vue}',
'./error.{js,ts,vue}',
'./app.config.{js,ts}',
'content/**/*.md'
],
theme: {
extend: {
}
},
plugins: [typography]
}

0
types/index.ts Normal file
View File