@kevinmarrec/create-app 0.5.0 → 0.6.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/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { x } from "tinyexec";
8
8
  import fs from "node:fs/promises";
9
9
 
10
10
  //#region package.json
11
- var version = "0.5.0";
11
+ var version = "0.6.0";
12
12
 
13
13
  //#endregion
14
14
  //#region src/utils/fs.ts
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@kevinmarrec/create-app",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
+ "packageManager": "bun@1.2.22",
5
6
  "description": "CLI that scaffolds an opinionated Bun & Vue fullstack application.",
6
7
  "author": "Kevin Marrec <kevin@marrec.io>",
7
8
  "license": "MIT",
@@ -49,7 +50,7 @@
49
50
  },
50
51
  "devDependencies": {
51
52
  "@faker-js/faker": "^10.0.0",
52
- "@kevinmarrec/eslint-config": "^1.4.0",
53
+ "@kevinmarrec/eslint-config": "^1.5.0",
53
54
  "@kevinmarrec/stylelint-config": "^1.2.0",
54
55
  "@kevinmarrec/tsconfig": "^1.1.0",
55
56
  "@types/bun": "^1.2.22",
@@ -59,7 +60,7 @@
59
60
  "knip": "^5.63.1",
60
61
  "stylelint": "^16.24.0",
61
62
  "taze": "^19.7.0",
62
- "tsdown": "^0.15.2",
63
+ "tsdown": "^0.15.4",
63
64
  "typescript": "^5.9.2",
64
65
  "vitest": "^3.2.4",
65
66
  "vue-tsc": "^3.0.7"
@@ -6,13 +6,14 @@
6
6
  "antfu.unocss",
7
7
  "dbaeumer.vscode-eslint",
8
8
  "eamodio.gitlens",
9
- "github.copilot",
9
+ "github.vscode-github-actions",
10
10
  "lokalise.i18n-ally",
11
11
  "mikestead.dotenv",
12
12
  "ms-azuretools.vscode-docker",
13
13
  "pkief.material-icon-theme",
14
14
  "redhat.vscode-yaml",
15
15
  "stylelint.vscode-stylelint",
16
+ "vitest.explorer",
16
17
  "vue.volar",
17
18
  "yoavbls.pretty-ts-errors"
18
19
  ]
@@ -51,6 +51,10 @@
51
51
  "vue"
52
52
  ],
53
53
 
54
+ "material-icon-theme.folders.associations": {
55
+ "orpc": "context"
56
+ },
57
+
54
58
  "javascript.format.semicolons": "remove",
55
59
  "javascript.preferences.quoteStyle": "single",
56
60
  "typescript.format.semicolons": "remove",
@@ -5,14 +5,14 @@
5
5
  "scripts": {
6
6
  "dev": "bun --watch --no-clear-screen src/main.ts",
7
7
  "build": "bun build src/main.ts --compile --minify --sourcemap --outfile dist/server",
8
- "db:generate": "bun --bun run drizzle-kit generate --config src/database/drizzle.config.ts",
9
- "db:migrate": "bun --bun run drizzle-kit migrate --config src/database/drizzle.config.ts"
8
+ "db:generate": "bun --bun run drizzle-kit generate --config src/database/drizzle/config.ts",
9
+ "db:migrate": "bun --bun run drizzle-kit migrate --config src/database/drizzle/config.ts"
10
10
  },
11
11
  "dependencies": {
12
12
  "@orpc/server": "^1.8.9",
13
- "better-auth": "^1.3.12",
13
+ "better-auth": "^1.3.13",
14
14
  "drizzle-orm": "^0.44.5",
15
- "pino": "^9.10.0",
15
+ "pino": "^9.11.0",
16
16
  "valibot": "^1.1.0"
17
17
  },
18
18
  "devDependencies": {
@@ -10,6 +10,7 @@ export function createBetterAuth({ db, logger }: { db: DB, logger: BaseLogger })
10
10
  }),
11
11
  logger: {
12
12
  log: (level, message) => {
13
+ if (level === 'error') return
13
14
  logger[level](message)
14
15
  },
15
16
  },
@@ -20,4 +21,3 @@ export function createBetterAuth({ db, logger }: { db: DB, logger: BaseLogger })
20
21
  }
21
22
 
22
23
  export type Auth = ReturnType<typeof createBetterAuth>
23
- export type Session = Auth['$Infer']['Session']
@@ -1,11 +1,13 @@
1
1
  import process from 'node:process'
2
2
 
3
- import { createBetterAuth } from './auth'
4
- import { rpcHandler } from './core'
5
- import { db } from './database'
6
- import { logger } from './utils/logger'
3
+ import { createBetterAuth } from '@backend/auth'
4
+ import { db } from '@backend/database'
5
+ import { createRpcHandler } from '@backend/orpc'
6
+ import { router } from '@backend/orpc/router'
7
+ import { logger } from '@backend/utils/logger'
7
8
 
8
9
  const auth = createBetterAuth({ db, logger })
10
+ const rpcHandler = createRpcHandler(router)
9
11
 
10
12
  const server = Bun.serve({
11
13
  hostname: import.meta.env.HOST ?? '0.0.0.0',
@@ -0,0 +1,65 @@
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,19 +1,15 @@
1
- import type { Session } from '@backend/auth'
2
- import type { Context } from '@backend/core/context'
3
- import { copyHeaders } from '@backend/utils/headers'
1
+ import type { Context } from '@backend/orpc'
4
2
  import { ORPCError, os } from '@orpc/server'
5
3
 
6
4
  export const authMiddleware = os
7
5
  .$context<Context>()
8
6
  .middleware(async ({ context, next }) => {
9
- const response = await context.auth.api.getSession({
7
+ const { headers, response: session } = await context.auth.api.getSession({
10
8
  headers: context.reqHeaders ?? new Headers(),
11
- asResponse: true,
9
+ returnHeaders: true,
12
10
  })
13
11
 
14
- const session = await response.json() as Session | null
15
-
16
- copyHeaders(response.headers, context.resHeaders)
12
+ headers.forEach((v, k) => context.resHeaders?.append(k, v))
17
13
 
18
14
  return next({
19
15
  context: {
@@ -0,0 +1 @@
1
+ export * from './auth'
@@ -1,6 +1,5 @@
1
- import { pub } from '@backend/core/builder'
2
- import { authMiddleware } from '@backend/core/middlewares/auth'
3
- import { copyHeaders } from '@backend/utils/headers'
1
+ import { pub } from '@backend/orpc'
2
+ import { authMiddleware } from '@backend/orpc/middlewares'
4
3
  import * as v from 'valibot'
5
4
 
6
5
  export const getCurrentUser = pub
@@ -20,7 +19,7 @@ export const signUp = pub
20
19
  returnHeaders: true,
21
20
  })
22
21
 
23
- copyHeaders(headers, resHeaders)
22
+ headers.forEach((v, k) => resHeaders?.append(k, v))
24
23
 
25
24
  return response.user
26
25
  })
@@ -37,7 +36,7 @@ export const signIn = pub
37
36
  returnHeaders: true,
38
37
  })
39
38
 
40
- copyHeaders(headers, resHeaders)
39
+ headers.forEach((v, k) => resHeaders?.append(k, v))
41
40
 
42
41
  return response.user
43
42
  })
@@ -49,7 +48,7 @@ export const signOut = pub
49
48
  returnHeaders: true,
50
49
  })
51
50
 
52
- copyHeaders(headers, resHeaders)
51
+ headers.forEach((v, k) => resHeaders?.append(k, v))
53
52
 
54
53
  return response
55
54
  })
@@ -52,8 +52,8 @@ const password = ref('')
52
52
  >
53
53
  </div>
54
54
 
55
- <div v-if="signIn.error" class="text-sm text-red-600 dark:text-red-400">
56
- {{ signIn.error }}
55
+ <div v-if="signIn.error.value || signUp.error.value" class="text-sm text-red-600 dark:text-red-400">
56
+ {{ signIn.error.value || signUp.error.value }}
57
57
  </div>
58
58
 
59
59
  <div class="flex space-x-3">
@@ -1,4 +1,4 @@
1
- import type { Router, RouterClient } from '@backend/core/router'
1
+ import type { Router, RouterClient } from '@backend/orpc/router'
2
2
  import { createORPCClient } from '@orpc/client'
3
3
  import { RPCLink } from '@orpc/client/fetch'
4
4
  import { createTanstackQueryUtils } from '@orpc/tanstack-query'
@@ -12,7 +12,7 @@ export default {
12
12
  },
13
13
  'backend': {
14
14
  drizzle: {
15
- config: 'src/database/drizzle.config.ts',
15
+ config: 'src/database/drizzle/config.ts',
16
16
  },
17
17
  ignoreDependencies: ['pino-pretty'],
18
18
  },
@@ -21,7 +21,7 @@
21
21
  "lint:inspect": "bunx @eslint/config-inspector"
22
22
  },
23
23
  "devDependencies": {
24
- "@kevinmarrec/eslint-config": "^1.4.0",
24
+ "@kevinmarrec/eslint-config": "^1.5.0",
25
25
  "@kevinmarrec/stylelint-config": "^1.2.0",
26
26
  "@kevinmarrec/tsconfig": "^1.1.0",
27
27
  "concurrently": "^9.2.1",
@@ -1,14 +0,0 @@
1
- import { os } from '@orpc/server'
2
-
3
- import type { Context } from './context'
4
- import { requiredAuthMiddleware } from './middlewares/auth'
5
-
6
- export const pub = os
7
- .$context<Context>()
8
- .errors({
9
- UNAUTHORIZED: { status: 401 },
10
- })
11
-
12
- /** @beta */
13
- export const authed = pub
14
- .use(requiredAuthMiddleware)
@@ -1,10 +0,0 @@
1
- import type { Auth } from '@backend/auth'
2
- import type { Database } from '@backend/database'
3
- import type { Logger } from '@backend/utils/logger'
4
- import type { RequestHeadersPluginContext, ResponseHeadersPluginContext } from '@orpc/server/plugins'
5
-
6
- export interface Context extends RequestHeadersPluginContext, ResponseHeadersPluginContext {
7
- auth: Auth
8
- db: Database
9
- logger: Logger
10
- }
@@ -1,33 +0,0 @@
1
- import { onError, ORPCError } from '@orpc/server'
2
- import { RPCHandler } from '@orpc/server/fetch'
3
- import { CORSPlugin, RequestHeadersPlugin, ResponseHeadersPlugin } from '@orpc/server/plugins'
4
- import { APIError } from 'better-auth/api'
5
-
6
- import { router } from './router'
7
-
8
- export const rpcHandler = new RPCHandler(router, {
9
- plugins: [
10
- new CORSPlugin({
11
- credentials: true,
12
- maxAge: 7200, // 2 hours https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Max-Age
13
- }),
14
- new RequestHeadersPlugin(),
15
- new ResponseHeadersPlugin(),
16
- ],
17
- clientInterceptors: [
18
- onError((error, { context }) => {
19
- if (error instanceof APIError) {
20
- throw new ORPCError(error.body?.code ?? 'INTERNAL_SERVER_ERROR', {
21
- status: error.statusCode,
22
- message: error.body?.message,
23
- })
24
- }
25
-
26
- if (error instanceof ORPCError) {
27
- throw error
28
- }
29
-
30
- context.logger.error(error)
31
- }),
32
- ],
33
- })
@@ -1,7 +0,0 @@
1
- function copyHeaders(source: Headers, destination?: Headers) {
2
- source.forEach((value, key) => {
3
- destination?.append(key, value)
4
- })
5
- }
6
-
7
- export { copyHeaders }