create-kuckit-app 0.4.0 → 0.4.1
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/bin.js +1 -1
- package/dist/{create-project-geQBZ0Ru.js → create-project-CAsuZMK5.js} +2 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/base/.claude/CLAUDE.md +83 -0
- package/templates/base/AGENTS.md +86 -0
- package/templates/base/apps/server/AGENTS.md +42 -85
- package/templates/base/apps/server/package.json +2 -14
- package/templates/base/apps/server/src/config.ts +12 -0
- package/templates/base/apps/server/src/modules.ts +66 -0
- package/templates/base/apps/server/src/server.ts +4 -46
- package/templates/base/apps/web/AGENTS.md +63 -85
- package/templates/base/apps/web/package.json +2 -6
- package/templates/base/apps/web/src/components/KuckitModuleRoute.tsx +29 -7
- package/templates/base/apps/web/src/components/dashboard/dashboard-overview.tsx +2 -2
- package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +2 -2
- package/templates/base/apps/web/src/main.tsx +12 -22
- package/templates/base/apps/web/src/modules.client.ts +43 -9
- package/templates/base/apps/web/src/routes/__root.tsx +1 -1
- package/templates/base/apps/web/src/routes/dashboard.tsx +1 -1
- package/templates/base/apps/web/src/routes/index.tsx +2 -2
- package/templates/base/apps/web/src/routes/login.tsx +2 -2
- package/templates/base/drizzle.config.ts +2 -6
- package/templates/base/kuckit.config.ts +30 -0
- package/templates/base/packages/items-module/AGENTS.md +83 -0
- package/templates/base/apps/server/src/app.ts +0 -20
- package/templates/base/apps/server/src/auth.ts +0 -10
- package/templates/base/apps/server/src/config/modules.ts +0 -21
- package/templates/base/apps/server/src/container.ts +0 -83
- package/templates/base/apps/server/src/health.ts +0 -27
- package/templates/base/apps/server/src/middleware/container.ts +0 -41
- package/templates/base/apps/server/src/module-rest-routes.ts +0 -47
- package/templates/base/apps/server/src/rest-router-registry.ts +0 -32
- package/templates/base/apps/server/src/rpc-router-registry.ts +0 -26
- package/templates/base/apps/server/src/rpc.ts +0 -31
- package/templates/base/apps/web/src/providers/KuckitProvider.tsx +0 -123
- package/templates/base/apps/web/src/providers/ServicesProvider.tsx +0 -47
- package/templates/base/apps/web/src/services/auth-client.ts +0 -12
- package/templates/base/apps/web/src/services/index.ts +0 -3
- package/templates/base/apps/web/src/services/rpc.ts +0 -29
- package/templates/base/apps/web/src/services/types.ts +0 -14
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { AwilixContainer } from 'awilix'
|
|
2
|
-
import {
|
|
3
|
-
createKuckitContainer,
|
|
4
|
-
loadKuckitModules,
|
|
5
|
-
type CoreConfig,
|
|
6
|
-
type CoreCradle,
|
|
7
|
-
} from '@kuckit/sdk'
|
|
8
|
-
import type { Pool } from 'pg'
|
|
9
|
-
import { ensureDatabaseUrl } from '@kuckit/db/connection'
|
|
10
|
-
import { getModuleSpecs } from './config/modules'
|
|
11
|
-
import { wireModuleRpcRouters } from './rpc-router-registry'
|
|
12
|
-
import { collectModuleRestRouters } from './rest-router-registry'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Server configuration
|
|
16
|
-
*/
|
|
17
|
-
export interface ServerConfig extends CoreConfig {
|
|
18
|
-
port: number
|
|
19
|
-
corsOrigin: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Server DI container cradle
|
|
24
|
-
*/
|
|
25
|
-
export interface ServerCradle extends CoreCradle {
|
|
26
|
-
config: ServerConfig
|
|
27
|
-
dbPool: Pool
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export type AppContainer = AwilixContainer<ServerCradle>
|
|
31
|
-
export type { ServerConfig as Config, ServerCradle as Cradle }
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Load configuration from environment
|
|
35
|
-
*/
|
|
36
|
-
const loadConfig = (): ServerConfig => {
|
|
37
|
-
const databaseUrl = ensureDatabaseUrl()
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
databaseUrl,
|
|
41
|
-
enableFileLogging: process.env.ENABLE_FILE_LOGGING === 'true',
|
|
42
|
-
logDir: process.env.LOG_DIR || './logs',
|
|
43
|
-
logLevel: (process.env.LOG_LEVEL || 'INFO') as 'DEBUG' | 'INFO' | 'WARN' | 'ERROR',
|
|
44
|
-
env: process.env.NODE_ENV || 'development',
|
|
45
|
-
port: parseInt(process.env.PORT || '3000', 10),
|
|
46
|
-
corsOrigin: process.env.CORS_ORIGIN || 'http://localhost:3001',
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Build root container with all modules
|
|
52
|
-
*/
|
|
53
|
-
export const buildRootContainer = async (): Promise<AppContainer> => {
|
|
54
|
-
const config = loadConfig()
|
|
55
|
-
|
|
56
|
-
const container = await createKuckitContainer({ config })
|
|
57
|
-
|
|
58
|
-
await loadKuckitModules({
|
|
59
|
-
container,
|
|
60
|
-
env: config.env,
|
|
61
|
-
modules: getModuleSpecs(),
|
|
62
|
-
onApiRegistrations: (registrations) => {
|
|
63
|
-
wireModuleRpcRouters(registrations)
|
|
64
|
-
collectModuleRestRouters(registrations)
|
|
65
|
-
console.log(`Loaded ${registrations.length} API registrations from modules`)
|
|
66
|
-
},
|
|
67
|
-
onComplete: () => {
|
|
68
|
-
console.log('All modules loaded successfully')
|
|
69
|
-
},
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
return container as AppContainer
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Cleanup container resources
|
|
77
|
-
*/
|
|
78
|
-
export const disposeContainer = async (container: AppContainer): Promise<void> => {
|
|
79
|
-
const { dbPool } = container.cradle
|
|
80
|
-
if (dbPool && typeof dbPool.end === 'function') {
|
|
81
|
-
await dbPool.end()
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { Express } from 'express'
|
|
2
|
-
import type { AppContainer } from './container'
|
|
3
|
-
|
|
4
|
-
export const setupHealth = (app: Express, container: AppContainer) => {
|
|
5
|
-
app.get('/health', async (_req, res) => {
|
|
6
|
-
const { dbPool } = container.cradle
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
const client = await dbPool.connect()
|
|
10
|
-
await client.query('SELECT 1')
|
|
11
|
-
client.release()
|
|
12
|
-
|
|
13
|
-
res.status(200).json({
|
|
14
|
-
status: 'healthy',
|
|
15
|
-
timestamp: new Date().toISOString(),
|
|
16
|
-
checks: { database: 'ok' },
|
|
17
|
-
})
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.error('[Health] Database check failed:', error)
|
|
20
|
-
res.status(503).json({
|
|
21
|
-
status: 'unhealthy',
|
|
22
|
-
timestamp: new Date().toISOString(),
|
|
23
|
-
checks: { database: 'failed' },
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Express, Request, Response, NextFunction } from 'express'
|
|
2
|
-
import { asValue } from 'awilix'
|
|
3
|
-
import { buildRootContainer, type AppContainer } from '../container'
|
|
4
|
-
|
|
5
|
-
let rootContainer: AppContainer
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Initialize and setup container middleware
|
|
9
|
-
* Must be awaited before using the container
|
|
10
|
-
*/
|
|
11
|
-
export const setupContainerMiddleware = async (app: Express): Promise<void> => {
|
|
12
|
-
rootContainer = await buildRootContainer()
|
|
13
|
-
|
|
14
|
-
app.use((req: Request, res: Response, next: NextFunction) => {
|
|
15
|
-
req.scope = rootContainer.createScope()
|
|
16
|
-
|
|
17
|
-
req.scope.register({
|
|
18
|
-
requestId: asValue(crypto.randomUUID()),
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
res.on('finish', () => {
|
|
22
|
-
req.scope?.dispose()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
res.on('close', () => {
|
|
26
|
-
req.scope?.dispose()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
next()
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get root container (for graceful shutdown)
|
|
35
|
-
*/
|
|
36
|
-
export const getRootContainer = (): AppContainer => {
|
|
37
|
-
if (!rootContainer) {
|
|
38
|
-
throw new Error('Container not initialized')
|
|
39
|
-
}
|
|
40
|
-
return rootContainer
|
|
41
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { Express, Request, Response, NextFunction } from 'express'
|
|
2
|
-
import express from 'express'
|
|
3
|
-
import { asValue } from 'awilix'
|
|
4
|
-
import { fromNodeHeaders } from 'better-auth/node'
|
|
5
|
-
import { auth } from '@kuckit/auth'
|
|
6
|
-
import { getRestRouters } from './rest-router-registry'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Middleware to add session to request scope for REST routes.
|
|
10
|
-
* Similar to createContext for RPC, but for Express routes.
|
|
11
|
-
*/
|
|
12
|
-
const sessionMiddleware = async (req: Request, _res: Response, next: NextFunction) => {
|
|
13
|
-
if (!req.scope) {
|
|
14
|
-
return next(new Error('Request scope not initialized'))
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const session = await auth.api.getSession({
|
|
19
|
-
headers: fromNodeHeaders(req.headers),
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
req.scope.register({
|
|
23
|
-
session: asValue(session),
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
next()
|
|
27
|
-
} catch (error) {
|
|
28
|
-
console.error('[REST Auth] Failed to get session:', error)
|
|
29
|
-
req.scope.register({
|
|
30
|
-
session: asValue(null),
|
|
31
|
-
})
|
|
32
|
-
next()
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Setup REST routers from modules.
|
|
38
|
-
* Must be called after container middleware is initialized.
|
|
39
|
-
*/
|
|
40
|
-
export const setupModuleRestRouters = (app: Express): void => {
|
|
41
|
-
const routers = getRestRouters()
|
|
42
|
-
|
|
43
|
-
for (const { name, router, basePath } of routers) {
|
|
44
|
-
app.use(`/api${basePath}`, express.json(), sessionMiddleware, router)
|
|
45
|
-
console.log(`[REST] Mounted module router: /api${basePath} (${name})`)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { Router } from 'express'
|
|
2
|
-
import type { ApiRegistration } from '@kuckit/sdk'
|
|
3
|
-
|
|
4
|
-
interface RestRouterEntry {
|
|
5
|
-
name: string
|
|
6
|
-
router: Router
|
|
7
|
-
basePath: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const restRouters: RestRouterEntry[] = []
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Collect REST routers from module registrations.
|
|
14
|
-
* Called from the SDK loader's onApiRegistrations callback.
|
|
15
|
-
*/
|
|
16
|
-
export const collectModuleRestRouters = (registrations: ApiRegistration[]): void => {
|
|
17
|
-
for (const reg of registrations) {
|
|
18
|
-
if (reg.type !== 'rest-router') continue
|
|
19
|
-
|
|
20
|
-
const basePath = reg.prefix ?? `/${reg.name}`
|
|
21
|
-
restRouters.push({
|
|
22
|
-
name: reg.name,
|
|
23
|
-
router: reg.router as Router,
|
|
24
|
-
basePath,
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get all collected REST routers for wiring to Express app.
|
|
31
|
-
*/
|
|
32
|
-
export const getRestRouters = (): readonly RestRouterEntry[] => restRouters
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { ApiRegistration } from '@kuckit/sdk'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Central mutable RPC router object used by RPCHandler.
|
|
5
|
-
*
|
|
6
|
-
* Module routers are wired into this object during the SDK loader's
|
|
7
|
-
* "wire" phase, before RPCHandler is instantiated.
|
|
8
|
-
*/
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
export const rootRpcRouter: Record<string, any> = {}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Wire module RPC routers into the central router object.
|
|
14
|
-
* Called from the SDK loader's onApiRegistrations callback.
|
|
15
|
-
*/
|
|
16
|
-
export const wireModuleRpcRouters = (registrations: ApiRegistration[]): void => {
|
|
17
|
-
for (const reg of registrations) {
|
|
18
|
-
if (reg.type !== 'rpc-router') continue
|
|
19
|
-
|
|
20
|
-
if (rootRpcRouter[reg.name]) {
|
|
21
|
-
throw new Error(`Duplicate RPC router name: "${reg.name}"`)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
rootRpcRouter[reg.name] = reg.router
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { RPCHandler } from '@orpc/server/node'
|
|
2
|
-
import { onError } from '@orpc/server'
|
|
3
|
-
import { createContext } from '@kuckit/api/context'
|
|
4
|
-
import type { Express } from 'express'
|
|
5
|
-
import { rootRpcRouter } from './rpc-router-registry'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Setup oRPC handler
|
|
9
|
-
*
|
|
10
|
-
* IMPORTANT: This must be called AFTER setupContainerMiddleware() has completed,
|
|
11
|
-
* which ensures all module routers have been wired into rootRpcRouter.
|
|
12
|
-
*/
|
|
13
|
-
export const setupRPC = (app: Express) => {
|
|
14
|
-
const rpcHandler = new RPCHandler(rootRpcRouter, {
|
|
15
|
-
interceptors: [
|
|
16
|
-
onError((error) => {
|
|
17
|
-
console.error('[RPC Error]', error)
|
|
18
|
-
}),
|
|
19
|
-
],
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
app.use(async (req, res, next) => {
|
|
23
|
-
const result = await rpcHandler.handle(req, res, {
|
|
24
|
-
prefix: '/rpc',
|
|
25
|
-
context: await createContext({ req }),
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
if (result.matched) return
|
|
29
|
-
next()
|
|
30
|
-
})
|
|
31
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext, useEffect, useState, useMemo, type ReactNode } from 'react'
|
|
2
|
-
import { RouterProvider, createRouter } from '@tanstack/react-router'
|
|
3
|
-
import {
|
|
4
|
-
loadKuckitClientModules,
|
|
5
|
-
KuckitNavProvider,
|
|
6
|
-
KuckitSlotProvider,
|
|
7
|
-
KuckitRpcProvider,
|
|
8
|
-
type LoadClientModulesResult,
|
|
9
|
-
type RouteRegistry,
|
|
10
|
-
type NavRegistry,
|
|
11
|
-
type SlotRegistry,
|
|
12
|
-
} from '@kuckit/sdk-react'
|
|
13
|
-
import { routeTree } from '../routeTree.gen'
|
|
14
|
-
import { useServices } from './ServicesProvider'
|
|
15
|
-
import { getClientModuleSpecs } from '../modules.client'
|
|
16
|
-
|
|
17
|
-
interface KuckitContextValue {
|
|
18
|
-
routeRegistry: RouteRegistry
|
|
19
|
-
navRegistry: NavRegistry
|
|
20
|
-
slotRegistry: SlotRegistry
|
|
21
|
-
isLoaded: boolean
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const KuckitContext = createContext<KuckitContextValue | null>(null)
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Hook to access Kuckit registries
|
|
28
|
-
*/
|
|
29
|
-
export function useKuckit(): KuckitContextValue {
|
|
30
|
-
const ctx = useContext(KuckitContext)
|
|
31
|
-
if (!ctx) {
|
|
32
|
-
throw new Error('useKuckit must be used within a KuckitProvider')
|
|
33
|
-
}
|
|
34
|
-
return ctx
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface KuckitProviderProps {
|
|
38
|
-
children?: ReactNode
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* KuckitProvider handles module loading and router creation
|
|
43
|
-
*/
|
|
44
|
-
export function KuckitProvider({ children }: KuckitProviderProps) {
|
|
45
|
-
const { orpc, queryClient, rpcClient } = useServices()
|
|
46
|
-
const [loadResult, setLoadResult] = useState<LoadClientModulesResult | null>(null)
|
|
47
|
-
const [error, setError] = useState<Error | null>(null)
|
|
48
|
-
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
let cancelled = false
|
|
51
|
-
|
|
52
|
-
const loadModules = async () => {
|
|
53
|
-
try {
|
|
54
|
-
const result = await loadKuckitClientModules({
|
|
55
|
-
orpc,
|
|
56
|
-
queryClient,
|
|
57
|
-
env: import.meta.env.MODE,
|
|
58
|
-
modules: getClientModuleSpecs(),
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
if (!cancelled) {
|
|
62
|
-
setLoadResult(result)
|
|
63
|
-
}
|
|
64
|
-
} catch (err) {
|
|
65
|
-
if (!cancelled) {
|
|
66
|
-
setError(err instanceof Error ? err : new Error(String(err)))
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
loadModules()
|
|
72
|
-
|
|
73
|
-
return () => {
|
|
74
|
-
cancelled = true
|
|
75
|
-
}
|
|
76
|
-
}, [orpc, queryClient])
|
|
77
|
-
|
|
78
|
-
const router = useMemo(() => {
|
|
79
|
-
if (!loadResult) return null
|
|
80
|
-
return createRouter({
|
|
81
|
-
routeTree,
|
|
82
|
-
defaultPreload: 'intent',
|
|
83
|
-
context: { orpc, queryClient },
|
|
84
|
-
})
|
|
85
|
-
}, [loadResult, orpc, queryClient])
|
|
86
|
-
|
|
87
|
-
if (error) {
|
|
88
|
-
return (
|
|
89
|
-
<div style={{ padding: '2rem', color: 'red' }}>
|
|
90
|
-
<h2>Failed to load modules</h2>
|
|
91
|
-
<p>{error.message}</p>
|
|
92
|
-
</div>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (!loadResult || !router) {
|
|
97
|
-
return (
|
|
98
|
-
<div style={{ padding: '2rem' }}>
|
|
99
|
-
<p>Loading...</p>
|
|
100
|
-
</div>
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const contextValue: KuckitContextValue = {
|
|
105
|
-
routeRegistry: loadResult.routeRegistry,
|
|
106
|
-
navRegistry: loadResult.navRegistry,
|
|
107
|
-
slotRegistry: loadResult.slotRegistry,
|
|
108
|
-
isLoaded: true,
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<KuckitContext.Provider value={contextValue}>
|
|
113
|
-
<KuckitRpcProvider client={rpcClient}>
|
|
114
|
-
<KuckitNavProvider registry={loadResult.navRegistry}>
|
|
115
|
-
<KuckitSlotProvider registry={loadResult.slotRegistry}>
|
|
116
|
-
<RouterProvider router={router} />
|
|
117
|
-
{children}
|
|
118
|
-
</KuckitSlotProvider>
|
|
119
|
-
</KuckitNavProvider>
|
|
120
|
-
</KuckitRpcProvider>
|
|
121
|
-
</KuckitContext.Provider>
|
|
122
|
-
)
|
|
123
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext, useMemo, type ReactNode } from 'react'
|
|
2
|
-
import { QueryClientProvider } from '@tanstack/react-query'
|
|
3
|
-
import {
|
|
4
|
-
createQueryClient,
|
|
5
|
-
createRPCLink,
|
|
6
|
-
createRPCClient,
|
|
7
|
-
createORPCUtils,
|
|
8
|
-
createAuthClientService,
|
|
9
|
-
type Services,
|
|
10
|
-
} from '../services'
|
|
11
|
-
|
|
12
|
-
const ServicesContext = createContext<Services | null>(null)
|
|
13
|
-
|
|
14
|
-
interface ServicesProviderProps {
|
|
15
|
-
children: ReactNode
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function ServicesProvider({ children }: ServicesProviderProps) {
|
|
19
|
-
const services = useMemo<Services>(() => {
|
|
20
|
-
const queryClient = createQueryClient()
|
|
21
|
-
const link = createRPCLink()
|
|
22
|
-
const rpcClient = createRPCClient(link)
|
|
23
|
-
const orpc = createORPCUtils(rpcClient)
|
|
24
|
-
const authClient = createAuthClientService()
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
queryClient,
|
|
28
|
-
rpcClient,
|
|
29
|
-
orpc,
|
|
30
|
-
authClient,
|
|
31
|
-
}
|
|
32
|
-
}, [])
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<ServicesContext.Provider value={services}>
|
|
36
|
-
<QueryClientProvider client={services.queryClient}>{children}</QueryClientProvider>
|
|
37
|
-
</ServicesContext.Provider>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function useServices(): Services {
|
|
42
|
-
const context = useContext(ServicesContext)
|
|
43
|
-
if (!context) {
|
|
44
|
-
throw new Error('useServices must be used within a ServicesProvider')
|
|
45
|
-
}
|
|
46
|
-
return context
|
|
47
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { auth } from '@kuckit/auth'
|
|
2
|
-
import { createAuthClient } from 'better-auth/react'
|
|
3
|
-
import { inferAdditionalFields } from 'better-auth/client/plugins'
|
|
4
|
-
|
|
5
|
-
export function createAuthClientService() {
|
|
6
|
-
return createAuthClient({
|
|
7
|
-
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000',
|
|
8
|
-
plugins: [inferAdditionalFields<typeof auth>()],
|
|
9
|
-
})
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type AuthClient = ReturnType<typeof createAuthClientService>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { createORPCClient } from '@orpc/client'
|
|
2
|
-
import { RPCLink } from '@orpc/client/fetch'
|
|
3
|
-
import { createTanstackQueryUtils } from '@orpc/tanstack-query'
|
|
4
|
-
import { QueryClient } from '@tanstack/react-query'
|
|
5
|
-
import type { RPCClient, ORPCUtils } from './types'
|
|
6
|
-
|
|
7
|
-
export function createQueryClient(): QueryClient {
|
|
8
|
-
return new QueryClient()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function createRPCLink() {
|
|
12
|
-
return new RPCLink({
|
|
13
|
-
url: `${import.meta.env.VITE_API_URL || 'http://localhost:3000'}/rpc`,
|
|
14
|
-
fetch(url, options) {
|
|
15
|
-
return fetch(url, {
|
|
16
|
-
...options,
|
|
17
|
-
credentials: 'include',
|
|
18
|
-
})
|
|
19
|
-
},
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function createRPCClient(link: ReturnType<typeof createRPCLink>): RPCClient {
|
|
24
|
-
return createORPCClient(link)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function createORPCUtils(client: RPCClient): ORPCUtils {
|
|
28
|
-
return createTanstackQueryUtils(client)
|
|
29
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { QueryClient } from '@tanstack/react-query'
|
|
2
|
-
import type { createTanstackQueryUtils } from '@orpc/tanstack-query'
|
|
3
|
-
import type { AuthClient } from './auth-client'
|
|
4
|
-
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
-
export type RPCClient = Record<string, any>
|
|
7
|
-
export type ORPCUtils = ReturnType<typeof createTanstackQueryUtils<RPCClient>>
|
|
8
|
-
|
|
9
|
-
export interface Services {
|
|
10
|
-
queryClient: QueryClient
|
|
11
|
-
rpcClient: RPCClient
|
|
12
|
-
orpc: ORPCUtils
|
|
13
|
-
authClient: AuthClient
|
|
14
|
-
}
|