@kevinmarrec/create-app 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.js +1 -3
- package/package.json +21 -19
- package/template/.docker/traefik/dynamic/tls.yml +4 -0
- package/template/.github/scripts/build-stats.md.ts +71 -0
- package/template/.github/workflows/ci.yml +19 -3
- package/template/{gitignore → .gitignore} +2 -0
- package/template/{npmrc → .npmrc} +0 -1
- package/template/.vscode/settings.json +1 -1
- package/template/api/.env.development +4 -0
- package/template/{backend → api}/package.json +9 -9
- package/template/{backend → api}/src/auth/index.ts +2 -0
- package/template/{backend → api}/src/database/index.ts +1 -1
- package/template/{backend → api}/src/env.d.ts +2 -2
- package/template/{backend → api}/src/main.ts +10 -20
- package/template/api/src/orpc/context.ts +11 -0
- package/template/api/src/orpc/index.ts +27 -0
- package/template/api/src/orpc/middlewares/auth.ts +24 -0
- package/template/api/src/orpc/plugins/error.ts +17 -0
- package/template/api/src/orpc/router/index.ts +31 -0
- package/template/api/src/utils/cors.ts +26 -0
- package/template/app/.env +1 -0
- package/template/{frontend → app}/package.json +13 -12
- package/template/{frontend → app}/src/App.vue +10 -2
- package/template/app/src/composables/auth.ts +39 -0
- package/template/app/src/composables/content.ts +13 -0
- package/template/{frontend → app}/src/composables/index.ts +1 -0
- package/template/{frontend → app}/src/lib/orpc.ts +3 -2
- package/template/{frontend → app}/src/main.ts +1 -1
- package/template/{frontend → app}/vite.config.ts +1 -1
- package/template/compose.yaml +65 -12
- package/template/docs/local-tls.md +152 -0
- package/template/knip.config.ts +5 -4
- package/template/package.json +14 -13
- package/template/tsconfig.json +2 -2
- package/template/backend/.env.development +0 -4
- package/template/backend/src/orpc/index.ts +0 -65
- package/template/backend/src/orpc/middlewares/auth.ts +0 -33
- package/template/backend/src/orpc/middlewares/index.ts +0 -1
- package/template/backend/src/orpc/router/auth.ts +0 -54
- package/template/backend/src/orpc/router/index.ts +0 -9
- package/template/frontend/.env.development +0 -1
- package/template/frontend/src/composables/auth.ts +0 -31
- package/template/scripts/dev.ts +0 -8
- /package/template/{backend → api}/src/database/drizzle/config.ts +0 -0
- /package/template/{backend → api}/src/database/migrations/0000_init.sql +0 -0
- /package/template/{backend → api}/src/database/migrations/meta/0000_snapshot.json +0 -0
- /package/template/{backend → api}/src/database/migrations/meta/_journal.json +0 -0
- /package/template/{backend → api}/src/database/schema/accounts.ts +0 -0
- /package/template/{backend → api}/src/database/schema/index.ts +0 -0
- /package/template/{backend → api}/src/database/schema/sessions.ts +0 -0
- /package/template/{backend → api}/src/database/schema/users.ts +0 -0
- /package/template/{backend → api}/src/database/schema/verifications.ts +0 -0
- /package/template/{backend → api}/src/utils/logger.ts +0 -0
- /package/template/{backend → api}/tsconfig.json +0 -0
- /package/template/{frontend → app}/index.html +0 -0
- /package/template/{frontend → app}/public/favicon.svg +0 -0
- /package/template/{frontend → app}/public/robots.txt +0 -0
- /package/template/{frontend → app}/src/components/.gitkeep +0 -0
- /package/template/{frontend → app}/src/env.d.ts +0 -0
- /package/template/{frontend → app}/src/locales/en.yml +0 -0
- /package/template/{frontend → app}/src/locales/fr.yml +0 -0
- /package/template/{frontend → app}/tsconfig.json +0 -0
- /package/template/{frontend → app}/uno.config.ts +0 -0
- /package/template/{frontend → app}/wrangler.json +0 -0
|
@@ -3,9 +3,9 @@ import process from 'node:process'
|
|
|
3
3
|
import darkMode from '@kevinmarrec/vite-plugin-dark-mode'
|
|
4
4
|
import yaml from '@modyfi/vite-plugin-yaml'
|
|
5
5
|
import unhead from '@unhead/addons/vite'
|
|
6
|
-
import unocss from '@unocss/vite'
|
|
7
6
|
import vue from '@vitejs/plugin-vue'
|
|
8
7
|
import { visualizer } from 'rollup-plugin-visualizer'
|
|
8
|
+
import unocss from 'unocss/vite'
|
|
9
9
|
import { defineConfig } from 'vite'
|
|
10
10
|
import devtools from 'vite-plugin-vue-devtools'
|
|
11
11
|
import tsconfigPaths from 'vite-tsconfig-paths'
|
package/template/compose.yaml
CHANGED
|
@@ -1,22 +1,75 @@
|
|
|
1
1
|
x-common: &common
|
|
2
|
-
working_dir: /app
|
|
3
2
|
volumes:
|
|
4
|
-
- ./:/
|
|
3
|
+
- ./:/code
|
|
4
|
+
working_dir: /code
|
|
5
5
|
user: 1000:1000
|
|
6
6
|
|
|
7
7
|
services:
|
|
8
|
-
|
|
8
|
+
traefik:
|
|
9
|
+
image: traefik:v3.6
|
|
10
|
+
container_name: traefik
|
|
11
|
+
restart: unless-stopped
|
|
12
|
+
security_opt:
|
|
13
|
+
- no-new-privileges:true
|
|
14
|
+
command:
|
|
15
|
+
# General configuration
|
|
16
|
+
- --log.level=INFO
|
|
17
|
+
- --api.dashboard=true
|
|
18
|
+
# Entrypoints for HTTP and HTTPS
|
|
19
|
+
- --entrypoints.websecure.address=:443
|
|
20
|
+
- --entrypoints.web.address=:80
|
|
21
|
+
# Redirect HTTP to HTTPS
|
|
22
|
+
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
|
23
|
+
- --entrypoints.web.http.redirections.entrypoint.scheme=https
|
|
24
|
+
# Providers (Docker & File for dynamic config)
|
|
25
|
+
- --providers.docker=true
|
|
26
|
+
- --providers.docker.exposedbydefault=false
|
|
27
|
+
- --providers.file.directory=/etc/traefik/dynamic
|
|
28
|
+
- --providers.file.watch=true
|
|
29
|
+
labels:
|
|
30
|
+
traefik.enable: 'true'
|
|
31
|
+
traefik.http.routers.traefik.rule: Host(`traefik.dev.localhost`)
|
|
32
|
+
traefik.http.routers.traefik.entrypoints: websecure
|
|
33
|
+
traefik.http.routers.traefik.tls: 'true'
|
|
34
|
+
traefik.http.routers.traefik.service: api@internal
|
|
35
|
+
ports:
|
|
36
|
+
- 80:80
|
|
37
|
+
- 443:443
|
|
38
|
+
volumes:
|
|
39
|
+
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
40
|
+
- ./.docker/traefik/dynamic:/etc/traefik/dynamic:ro # Mount the dynamic config directory
|
|
41
|
+
- ./.docker/traefik/certs:/certs:ro # Mount the certs directory
|
|
42
|
+
|
|
43
|
+
api:
|
|
9
44
|
<<: *common
|
|
45
|
+
depends_on:
|
|
46
|
+
- traefik
|
|
47
|
+
container_name: api
|
|
10
48
|
image: oven/bun:1-alpine
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
49
|
+
init: true
|
|
50
|
+
command: [bun, --cwd, api, dev]
|
|
51
|
+
environment:
|
|
52
|
+
- FORCE_COLOR=1
|
|
53
|
+
labels:
|
|
54
|
+
traefik.enable: 'true'
|
|
55
|
+
traefik.http.routers.api.rule: Host(`api.dev.localhost`)
|
|
56
|
+
traefik.http.routers.api.entrypoints: websecure
|
|
57
|
+
traefik.http.routers.api.tls: 'true'
|
|
58
|
+
traefik.http.services.api.loadbalancer.server.port: '4000'
|
|
14
59
|
|
|
15
|
-
|
|
60
|
+
app:
|
|
16
61
|
<<: *common
|
|
17
62
|
depends_on:
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
63
|
+
- api
|
|
64
|
+
container_name: app
|
|
65
|
+
image: imbios/bun-node:24-alpine
|
|
66
|
+
init: true
|
|
67
|
+
command: [bun, --cwd, app, dev, --host, 0.0.0.0]
|
|
68
|
+
environment:
|
|
69
|
+
- FORCE_COLOR=1
|
|
70
|
+
labels:
|
|
71
|
+
traefik.enable: 'true'
|
|
72
|
+
traefik.http.routers.app.rule: Host(`app.dev.localhost`)
|
|
73
|
+
traefik.http.routers.app.entrypoints: websecure
|
|
74
|
+
traefik.http.routers.app.tls: 'true'
|
|
75
|
+
traefik.http.services.app.loadbalancer.server.port: '5173'
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# **Local TLS Setup Guide**
|
|
2
|
+
|
|
3
|
+
This guide provides the essential steps to install mkcert and generate trusted TLS certificates for your Traefik-secured local development environment.
|
|
4
|
+
|
|
5
|
+
Certificates are expected in `.docker/traefik/certs/`.
|
|
6
|
+
|
|
7
|
+
## **Prerequisites**
|
|
8
|
+
|
|
9
|
+
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed
|
|
10
|
+
- Ports 80 and 443 available on your system
|
|
11
|
+
- Administrator/sudo access for installing mkcert
|
|
12
|
+
|
|
13
|
+
## **1. Install mkcert (Ubuntu/WSL)**
|
|
14
|
+
|
|
15
|
+
Download, install, and clean up the executable:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
curl -JLO "https://dl.filippo.io/mkcert/latest?for=linux/amd64"
|
|
19
|
+
chmod +x mkcert-v*-linux-amd64
|
|
20
|
+
sudo cp mkcert-v*-linux-amd64 /usr/local/bin/mkcert
|
|
21
|
+
rm mkcert-v*-linux-amd64
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Verify the installation:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
mkcert -version
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## **2. Install the mkcert Root CA**
|
|
31
|
+
|
|
32
|
+
Install the local root CA to trust generated certificates:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
mkcert -install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### **Firefox and Zen Browser (Manual Import)**
|
|
39
|
+
|
|
40
|
+
Browsers like Firefox and Firefox-based Zen Browser require manual import into their internal trust stores.
|
|
41
|
+
|
|
42
|
+
1. **Find Root CA File Path:**
|
|
43
|
+
Run the appropriate command below to get the full path to the rootCA.pem file:
|
|
44
|
+
- **Linux Native (or WSL for Linux Apps):**
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
echo "$(mkcert -CAROOT)/rootCA.pem"
|
|
48
|
+
# /home/user/.local/share/mkcert/rootCA.pem
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- **WSL for Windows Host Applications:** Use wslpath to get the Windows-formatted path.
|
|
52
|
+
```sh
|
|
53
|
+
wslpath -w "$(mkcert -CAROOT)/rootCA.pem"
|
|
54
|
+
# \\wsl.localhost\Ubuntu\home\user\.local\share\mkcert\rootCA.pem
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
2. **Import:** In the browser's settings:
|
|
58
|
+
- **Settings** -> **Privacy & Security**.
|
|
59
|
+
- **Certificates** -> **View Certificates...**
|
|
60
|
+
- **Authorities** tab -> **Import...**
|
|
61
|
+
- Select the rootCA.pem file (using the path found above)
|
|
62
|
+
- Check **"Trust this CA to identify websites"**
|
|
63
|
+
- Click **OK**
|
|
64
|
+
|
|
65
|
+
## **3. Generate the `dev.localhost` Certificate**
|
|
66
|
+
|
|
67
|
+
Generate the wildcard certificate for `*.dev.localhost` and place the files where Traefik is configured to look (See [`tls.yml`](../.docker/traefik/dynamic/tls.yml)).
|
|
68
|
+
|
|
69
|
+
1. **Create Directory:**
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
mkdir -p .docker/traefik/certs
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
2. **Generate Certificate:**
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
mkcert \
|
|
79
|
+
-cert-file .docker/traefik/certs/dev.localhost.crt \
|
|
80
|
+
-key-file .docker/traefik/certs/dev.localhost.key \
|
|
81
|
+
"dev.localhost" "*.dev.localhost"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
3. **Verify Certificate:**
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
openssl x509 -in .docker/traefik/certs/dev.localhost.crt -text -noout | grep -A 2 "Subject Alternative Name"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## **4. Validate Setup**
|
|
91
|
+
|
|
92
|
+
1. **Start Services:**
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
docker compose up -d
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
2. **Test in Browser:**
|
|
99
|
+
|
|
100
|
+
- Visit **https://traefik.dev.localhost** — you should see the Traefik dashboard
|
|
101
|
+
- Visit **https://app.dev.localhost** — you should see your app
|
|
102
|
+
- Both should load without SSL warnings
|
|
103
|
+
|
|
104
|
+
## **5. Troubleshooting**
|
|
105
|
+
|
|
106
|
+
### **Certificate Files Missing**
|
|
107
|
+
|
|
108
|
+
If Traefik fails to start or shows TLS errors, verify the certificate files exist:
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
ls -la .docker/traefik/certs/
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### **Browser Shows SSL Warning**
|
|
115
|
+
|
|
116
|
+
- Ensure mkcert root CA is installed (`mkcert -install`)
|
|
117
|
+
- For Firefox/Zen Browser, manually import the root CA (see section 2)
|
|
118
|
+
- Clear browser cache and restart the browser
|
|
119
|
+
|
|
120
|
+
### **Certificate Expiration**
|
|
121
|
+
|
|
122
|
+
mkcert certificates are valid for a long time, but if you need to regenerate:
|
|
123
|
+
|
|
124
|
+
1. **Remove old certificates:**
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
rm .docker/traefik/certs/dev.localhost.*
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
2. **Regenerate (see section 3)**
|
|
131
|
+
|
|
132
|
+
## **6. Clean Up**
|
|
133
|
+
|
|
134
|
+
1. **Stop Services:**
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
docker compose down
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
2. **Remove Certificates (Optional):**
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
rm -rf .docker/traefik/certs
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
3. **Uninstall mkcert Root CA (Optional):**
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
mkcert -uninstall
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
> **Note:** Removing the root CA will cause SSL warnings in browsers until you reinstall it or regenerate certificates.
|
package/template/knip.config.ts
CHANGED
|
@@ -10,15 +10,16 @@ export default {
|
|
|
10
10
|
'.': {
|
|
11
11
|
entry: ['*.config.ts'],
|
|
12
12
|
},
|
|
13
|
-
'
|
|
13
|
+
'api': {
|
|
14
14
|
drizzle: {
|
|
15
15
|
config: 'src/database/drizzle/config.ts',
|
|
16
16
|
},
|
|
17
|
-
ignoreDependencies: ['pino-pretty'],
|
|
18
17
|
},
|
|
19
|
-
'
|
|
18
|
+
'app': {
|
|
20
19
|
entry: ['src/main.ts'],
|
|
21
|
-
ignoreDependencies: [
|
|
20
|
+
ignoreDependencies: [
|
|
21
|
+
'@vueuse/core',
|
|
22
|
+
],
|
|
22
23
|
},
|
|
23
24
|
},
|
|
24
25
|
} satisfies KnipConfig
|
package/template/package.json
CHANGED
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "project",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"private": true,
|
|
5
|
-
"packageManager": "bun@1.3.
|
|
5
|
+
"packageManager": "bun@1.3.2",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "lts/*"
|
|
8
8
|
},
|
|
9
9
|
"workspaces": [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"api",
|
|
11
|
+
"app"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"check": "bun run check:
|
|
14
|
+
"check": "bun run check:eslint && bun run check:stylelint && bun run check:unused && bun run check:types",
|
|
15
15
|
"check:eslint": "eslint . --cache",
|
|
16
16
|
"check:stylelint": "stylelint '**/*.{css,scss,vue}' --ignorePath .gitignore --cache",
|
|
17
17
|
"check:types": "vue-tsc --noEmit",
|
|
18
18
|
"check:unused": "knip -n",
|
|
19
|
-
"dev": "bun scripts/dev.ts",
|
|
20
19
|
"lint": "bun run check:eslint && bun run check:stylelint",
|
|
21
20
|
"lint:inspect": "bunx @eslint/config-inspector",
|
|
22
21
|
"update": "bunx taze -I -rwi"
|
|
23
22
|
},
|
|
24
23
|
"devDependencies": {
|
|
25
|
-
"@kevinmarrec/eslint-config": "^1.5.
|
|
26
|
-
"@kevinmarrec/stylelint-config": "^1.
|
|
27
|
-
"@kevinmarrec/tsconfig": "^1.
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"knip": "^5.
|
|
24
|
+
"@kevinmarrec/eslint-config": "^1.5.6",
|
|
25
|
+
"@kevinmarrec/stylelint-config": "^1.5.6",
|
|
26
|
+
"@kevinmarrec/tsconfig": "^1.5.6",
|
|
27
|
+
"eslint": "^9.39.1",
|
|
28
|
+
"filesize": "^11.0.13",
|
|
29
|
+
"knip": "^5.69.1",
|
|
31
30
|
"stylelint": "^16.25.0",
|
|
31
|
+
"tinyexec": "^1.0.2",
|
|
32
|
+
"tinyglobby": "^0.2.15",
|
|
32
33
|
"typescript": "~5.9.3",
|
|
33
|
-
"vue-tsc": "^3.1.
|
|
34
|
+
"vue-tsc": "^3.1.3"
|
|
34
35
|
}
|
|
35
36
|
}
|
package/template/tsconfig.json
CHANGED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { Auth } from '@backend/auth'
|
|
2
|
-
import type { Database } from '@backend/database'
|
|
3
|
-
import { requiredAuthMiddleware } from '@backend/orpc/middlewares'
|
|
4
|
-
import type { Logger } from '@backend/utils/logger'
|
|
5
|
-
import { onError, ORPCError, os, type Router } from '@orpc/server'
|
|
6
|
-
import { RPCHandler } from '@orpc/server/fetch'
|
|
7
|
-
import {
|
|
8
|
-
CORSPlugin,
|
|
9
|
-
RequestHeadersPlugin,
|
|
10
|
-
type RequestHeadersPluginContext,
|
|
11
|
-
ResponseHeadersPlugin,
|
|
12
|
-
type ResponseHeadersPluginContext,
|
|
13
|
-
} from '@orpc/server/plugins'
|
|
14
|
-
import { APIError } from 'better-auth/api'
|
|
15
|
-
|
|
16
|
-
/* Context */
|
|
17
|
-
|
|
18
|
-
export interface Context extends RequestHeadersPluginContext, ResponseHeadersPluginContext {
|
|
19
|
-
auth: Auth
|
|
20
|
-
db: Database
|
|
21
|
-
logger: Logger
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* RPC Handler */
|
|
25
|
-
|
|
26
|
-
export function createRpcHandler<T extends Context>(router: Router<any, T>) {
|
|
27
|
-
return new RPCHandler<T>(router, {
|
|
28
|
-
plugins: [
|
|
29
|
-
new CORSPlugin({
|
|
30
|
-
credentials: true,
|
|
31
|
-
maxAge: 7200, // 2 hours https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Max-Age
|
|
32
|
-
}),
|
|
33
|
-
new RequestHeadersPlugin(),
|
|
34
|
-
new ResponseHeadersPlugin(),
|
|
35
|
-
],
|
|
36
|
-
clientInterceptors: [
|
|
37
|
-
onError((error, { context }) => {
|
|
38
|
-
if (error instanceof APIError) {
|
|
39
|
-
throw new ORPCError(error.body?.code ?? 'INTERNAL_SERVER_ERROR', {
|
|
40
|
-
status: error.statusCode,
|
|
41
|
-
message: error.body?.message,
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (error instanceof ORPCError) {
|
|
46
|
-
throw error
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
context.logger.error(error)
|
|
50
|
-
}),
|
|
51
|
-
],
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/* Builder */
|
|
56
|
-
|
|
57
|
-
export const pub = os
|
|
58
|
-
.$context<Context>()
|
|
59
|
-
.errors({
|
|
60
|
-
UNAUTHORIZED: { status: 401 },
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
/** @beta */
|
|
64
|
-
export const authed = pub
|
|
65
|
-
.use(requiredAuthMiddleware)
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { Context } from '@backend/orpc'
|
|
2
|
-
import { ORPCError, os } from '@orpc/server'
|
|
3
|
-
|
|
4
|
-
export const authMiddleware = os
|
|
5
|
-
.$context<Context>()
|
|
6
|
-
.middleware(async ({ context, next }) => {
|
|
7
|
-
const { headers, response: session } = await context.auth.api.getSession({
|
|
8
|
-
headers: context.reqHeaders ?? new Headers(),
|
|
9
|
-
returnHeaders: true,
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
headers.forEach((v, k) => context.resHeaders?.append(k, v))
|
|
13
|
-
|
|
14
|
-
return next({
|
|
15
|
-
context: {
|
|
16
|
-
user: session ? session.user : null,
|
|
17
|
-
},
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
export const requiredAuthMiddleware = authMiddleware
|
|
22
|
-
.concat(async ({ context, next }) => {
|
|
23
|
-
if (!context.user) {
|
|
24
|
-
throw new ORPCError('UNAUTHORIZED')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return next({
|
|
28
|
-
context: {
|
|
29
|
-
user: context.user,
|
|
30
|
-
},
|
|
31
|
-
})
|
|
32
|
-
},
|
|
33
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './auth'
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { pub } from '@backend/orpc'
|
|
2
|
-
import { authMiddleware } from '@backend/orpc/middlewares'
|
|
3
|
-
import * as v from 'valibot'
|
|
4
|
-
|
|
5
|
-
export const getCurrentUser = pub
|
|
6
|
-
.use(authMiddleware)
|
|
7
|
-
.handler(async ({ context }) => context.user)
|
|
8
|
-
|
|
9
|
-
export const signUp = pub
|
|
10
|
-
.input(v.object({
|
|
11
|
-
name: v.string(),
|
|
12
|
-
email: v.pipe(v.string(), v.email()),
|
|
13
|
-
password: v.string(),
|
|
14
|
-
rememberMe: v.optional(v.boolean(), true),
|
|
15
|
-
}))
|
|
16
|
-
.handler(async ({ input, context: { resHeaders, auth } }) => {
|
|
17
|
-
const { headers, response } = await auth.api.signUpEmail({
|
|
18
|
-
body: input,
|
|
19
|
-
returnHeaders: true,
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
headers.forEach((v, k) => resHeaders?.append(k, v))
|
|
23
|
-
|
|
24
|
-
return response.user
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export const signIn = pub
|
|
28
|
-
.input(v.object({
|
|
29
|
-
email: v.pipe(v.string(), v.email()),
|
|
30
|
-
password: v.string(),
|
|
31
|
-
rememberMe: v.optional(v.boolean(), true),
|
|
32
|
-
}))
|
|
33
|
-
.handler(async ({ input, context: { resHeaders, auth } }) => {
|
|
34
|
-
const { headers, response } = await auth.api.signInEmail({
|
|
35
|
-
body: input,
|
|
36
|
-
returnHeaders: true,
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
headers.forEach((v, k) => resHeaders?.append(k, v))
|
|
40
|
-
|
|
41
|
-
return response.user
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
export const signOut = pub
|
|
45
|
-
.handler(async ({ context: { auth, reqHeaders, resHeaders } }) => {
|
|
46
|
-
const { headers, response } = await auth.api.signOut({
|
|
47
|
-
headers: reqHeaders ?? new Headers(),
|
|
48
|
-
returnHeaders: true,
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
headers.forEach((v, k) => resHeaders?.append(k, v))
|
|
52
|
-
|
|
53
|
-
return response
|
|
54
|
-
})
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VITE_API_URL=http://localhost:4000/rpc
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { orpc } from '@frontend/lib/orpc'
|
|
2
|
-
import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'
|
|
3
|
-
|
|
4
|
-
export function useAuth() {
|
|
5
|
-
const qc = useQueryClient()
|
|
6
|
-
|
|
7
|
-
const { data: user } = useQuery(orpc.auth.getCurrentUser.queryOptions({
|
|
8
|
-
retry: false,
|
|
9
|
-
}))
|
|
10
|
-
|
|
11
|
-
const signUp = useMutation(orpc.auth.signUp.mutationOptions({
|
|
12
|
-
onSuccess: () => qc.invalidateQueries({ queryKey: orpc.auth.getCurrentUser.queryKey() }),
|
|
13
|
-
}))
|
|
14
|
-
|
|
15
|
-
const signIn = useMutation(orpc.auth.signIn.mutationOptions({
|
|
16
|
-
onSuccess: () => qc.invalidateQueries({ queryKey: orpc.auth.getCurrentUser.queryKey() }),
|
|
17
|
-
}))
|
|
18
|
-
|
|
19
|
-
const signOut = useMutation(orpc.auth.signOut.mutationOptions({
|
|
20
|
-
onSuccess: () => {
|
|
21
|
-
qc.setQueryData<null>(orpc.auth.getCurrentUser.queryKey(), null)
|
|
22
|
-
},
|
|
23
|
-
}))
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
user,
|
|
27
|
-
signUp,
|
|
28
|
-
signIn,
|
|
29
|
-
signOut,
|
|
30
|
-
}
|
|
31
|
-
}
|
package/template/scripts/dev.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import concurrently, { type ConcurrentlyCommandInput } from 'concurrently'
|
|
2
|
-
|
|
3
|
-
const commandInputs: ConcurrentlyCommandInput[] = [
|
|
4
|
-
{ name: 'backend', command: `bun --cwd backend dev | pino-pretty`, prefixColor: 'blue' },
|
|
5
|
-
{ name: 'frontend', command: `bun --cwd frontend dev`, prefixColor: 'green' },
|
|
6
|
-
]
|
|
7
|
-
|
|
8
|
-
concurrently(commandInputs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|