@amirulabu/create-recurring-rabbit-app 0.2.16 → 0.2.19
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 +39 -21
- package/package.json +1 -1
- package/templates/default/eslint.config.js +62 -0
- package/templates/default/src/app/__root.tsx +2 -1
- package/templates/default/src/app/api/auth/$.ts +2 -2
- package/templates/default/src/app/api/auth/get-session.ts +1 -1
- package/templates/default/src/app/api/health.ts +2 -2
- package/templates/default/src/app/auth/forgot-password.tsx +15 -4
- package/templates/default/src/app/auth/login.tsx +1 -1
- package/templates/default/src/app/auth/register.tsx +1 -1
- package/templates/default/src/app/auth/reset-password.tsx +1 -1
- package/templates/default/src/app/auth/verify-email.tsx +2 -1
- package/templates/default/src/app/dashboard/settings.tsx +4 -6
- package/templates/default/src/app/index.tsx +1 -1
- package/templates/default/src/app/routeTree.gen.ts +43 -0
- package/templates/default/src/lib/auth.ts +3 -3
- package/templates/default/src/server/api/routers/dashboard.ts +3 -3
- package/templates/default/src/server/api/routers/user.ts +4 -4
- package/templates/default/src/server/db/seed.ts +2 -2
- package/templates/default/.eslintrc.json +0 -35
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { program } from 'commander';
|
|
3
|
-
import
|
|
3
|
+
import path6 from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import { existsSync, promises, mkdirSync
|
|
5
|
+
import { existsSync, readFileSync, promises, mkdirSync } from 'fs';
|
|
6
6
|
import ora from 'ora';
|
|
7
7
|
import fs from 'fs/promises';
|
|
8
8
|
import { execSync, spawn } from 'child_process';
|
|
@@ -16,10 +16,10 @@ async function copyTemplateFiles(templateDir, targetDir) {
|
|
|
16
16
|
const entries = await fs.readdir(src);
|
|
17
17
|
await fs.mkdir(dest, { recursive: true });
|
|
18
18
|
for (const entry of entries) {
|
|
19
|
-
await copyRecursive(
|
|
19
|
+
await copyRecursive(path6.join(src, entry), path6.join(dest, entry));
|
|
20
20
|
}
|
|
21
21
|
} else {
|
|
22
|
-
await fs.mkdir(
|
|
22
|
+
await fs.mkdir(path6.dirname(dest), { recursive: true });
|
|
23
23
|
await fs.copyFile(src, dest);
|
|
24
24
|
}
|
|
25
25
|
};
|
|
@@ -29,7 +29,7 @@ async function copyDirectory(src, dest) {
|
|
|
29
29
|
await copyTemplateFiles(src, dest);
|
|
30
30
|
}
|
|
31
31
|
async function generatePackageJson(targetDir, config) {
|
|
32
|
-
const packageJsonPath =
|
|
32
|
+
const packageJsonPath = path6.join(targetDir, "package.json");
|
|
33
33
|
const packageJson = {
|
|
34
34
|
name: config.name,
|
|
35
35
|
version: config.version ?? "0.1.0",
|
|
@@ -47,8 +47,8 @@ async function generatePackageJson(targetDir, config) {
|
|
|
47
47
|
"db:studio": "drizzle-kit studio",
|
|
48
48
|
"db:seed": "tsx src/server/db/seed.ts",
|
|
49
49
|
typecheck: "tsc --noEmit",
|
|
50
|
-
lint: "eslint .
|
|
51
|
-
"lint:fix": "eslint . --
|
|
50
|
+
lint: "eslint .",
|
|
51
|
+
"lint:fix": "eslint . --fix",
|
|
52
52
|
format: 'prettier --write "src/**/*.{ts,tsx,json,css}"',
|
|
53
53
|
clean: "rm -rf .vinxi dist data/*.db data/*.db-shm data/*.db-wal",
|
|
54
54
|
"build:analyze": "ANALYZE=true vinxi build",
|
|
@@ -82,19 +82,21 @@ async function generatePackageJson(targetDir, config) {
|
|
|
82
82
|
...config.dependencies
|
|
83
83
|
},
|
|
84
84
|
devDependencies: {
|
|
85
|
+
"@eslint/js": "^9.39.2",
|
|
85
86
|
"@lhci/cli": "^0.12.0",
|
|
86
87
|
"@types/better-sqlite3": "^7.6.9",
|
|
87
88
|
"@types/node": "^20.11.0",
|
|
88
89
|
"@types/react": "^18.2.0",
|
|
89
90
|
"@types/react-dom": "^18.2.0",
|
|
90
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
91
|
-
"@typescript-eslint/parser": "^
|
|
91
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
92
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
92
93
|
"@vitejs/plugin-react": "^4.3.0",
|
|
93
94
|
"@vitest/coverage-v8": "^1.6.0",
|
|
94
|
-
eslint: "^
|
|
95
|
-
"eslint-plugin-react": "^7.
|
|
96
|
-
"eslint-plugin-react-hooks": "^
|
|
95
|
+
eslint: "^9.39.2",
|
|
96
|
+
"eslint-plugin-react": "^7.37.0",
|
|
97
|
+
"eslint-plugin-react-hooks": "^5.0.0",
|
|
97
98
|
"drizzle-kit": "^0.31.0",
|
|
99
|
+
globals: "^15.0.0",
|
|
98
100
|
postcss: "^8.4.0",
|
|
99
101
|
prettier: "^3.2.5",
|
|
100
102
|
"rollup-plugin-visualizer": "^5.12.0",
|
|
@@ -232,7 +234,7 @@ function generateSecret(length = 32) {
|
|
|
232
234
|
return crypto.randomBytes(length).toString("base64");
|
|
233
235
|
}
|
|
234
236
|
async function generateEnvFile(targetDir, options = {}) {
|
|
235
|
-
const envPath =
|
|
237
|
+
const envPath = path6.join(targetDir, ".env.local");
|
|
236
238
|
const secret = generateSecret(32);
|
|
237
239
|
const content = [
|
|
238
240
|
`# Database`,
|
|
@@ -255,7 +257,7 @@ async function generateEnvFile(targetDir, options = {}) {
|
|
|
255
257
|
await fs.writeFile(envPath, content);
|
|
256
258
|
}
|
|
257
259
|
function loadEnvFile(projectPath) {
|
|
258
|
-
const envPath =
|
|
260
|
+
const envPath = path6.join(projectPath, ".env.local");
|
|
259
261
|
const env = {};
|
|
260
262
|
try {
|
|
261
263
|
const content = readFileSync(envPath, "utf-8");
|
|
@@ -278,7 +280,7 @@ function loadEnvFile(projectPath) {
|
|
|
278
280
|
async function initializeDatabase(projectPath) {
|
|
279
281
|
const spinner = ora("Initializing database...").start();
|
|
280
282
|
try {
|
|
281
|
-
const dataDir =
|
|
283
|
+
const dataDir = path6.join(projectPath, "data");
|
|
282
284
|
if (!existsSync(dataDir)) {
|
|
283
285
|
mkdirSync(dataDir, { recursive: true });
|
|
284
286
|
spinner.text = "Data directory created";
|
|
@@ -324,7 +326,7 @@ ${errorOutput}`));
|
|
|
324
326
|
}
|
|
325
327
|
async function runSeedScript(projectPath, env) {
|
|
326
328
|
return new Promise((resolve, reject) => {
|
|
327
|
-
const seedScriptPath =
|
|
329
|
+
const seedScriptPath = path6.join(projectPath, "src/server/db/seed.ts");
|
|
328
330
|
const command = "npx";
|
|
329
331
|
const args = ["tsx", seedScriptPath];
|
|
330
332
|
const child = spawn(command, args, {
|
|
@@ -502,7 +504,7 @@ function validateProjectName(name) {
|
|
|
502
504
|
if (RESERVED_NAMES.has(name)) {
|
|
503
505
|
throw new CLIError(`Invalid project name: "${name}" is a reserved name`);
|
|
504
506
|
}
|
|
505
|
-
const parts = name.split(
|
|
507
|
+
const parts = name.split(path6.sep);
|
|
506
508
|
const baseName = parts[parts.length - 1];
|
|
507
509
|
if (baseName !== name) {
|
|
508
510
|
throw new CLIError("Invalid project name: cannot contain path separators");
|
|
@@ -519,16 +521,32 @@ async function cleanupProject(projectPath) {
|
|
|
519
521
|
}
|
|
520
522
|
|
|
521
523
|
// src/commands/create.ts
|
|
522
|
-
var
|
|
523
|
-
|
|
524
|
-
|
|
524
|
+
var getPackageRoot = () => {
|
|
525
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
526
|
+
let currentDir = path6.dirname(currentFile);
|
|
527
|
+
while (currentDir !== path6.parse(currentDir).root) {
|
|
528
|
+
const packageJsonPath = path6.join(currentDir, "package.json");
|
|
529
|
+
if (existsSync(packageJsonPath)) {
|
|
530
|
+
try {
|
|
531
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
532
|
+
if (pkg.name === "@amirulabu/create-recurring-rabbit-app") {
|
|
533
|
+
return currentDir;
|
|
534
|
+
}
|
|
535
|
+
} catch {
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
currentDir = path6.dirname(currentDir);
|
|
539
|
+
}
|
|
540
|
+
throw new Error("Could not find package root");
|
|
541
|
+
};
|
|
542
|
+
var TEMPLATE_DIR = path6.join(getPackageRoot(), "templates/default");
|
|
525
543
|
async function scaffoldProject(projectName, targetPath) {
|
|
526
544
|
const spinner = ora("Creating project structure...").start();
|
|
527
545
|
let projectPath = "";
|
|
528
546
|
let projectCreated = false;
|
|
529
547
|
try {
|
|
530
548
|
validateProjectName(projectName);
|
|
531
|
-
projectPath =
|
|
549
|
+
projectPath = path6.join(targetPath, projectName);
|
|
532
550
|
if (existsSync(projectPath)) {
|
|
533
551
|
spinner.fail(`Directory ${projectName} already exists. Please choose a different name.`);
|
|
534
552
|
throw new Error(`Directory ${projectName} already exists`);
|
package/package.json
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import js from '@eslint/js'
|
|
2
|
+
import tseslint from '@typescript-eslint/eslint-plugin'
|
|
3
|
+
import tsparser from '@typescript-eslint/parser'
|
|
4
|
+
import react from 'eslint-plugin-react'
|
|
5
|
+
import reactHooks from 'eslint-plugin-react-hooks'
|
|
6
|
+
import globals from 'globals'
|
|
7
|
+
|
|
8
|
+
export default [
|
|
9
|
+
{
|
|
10
|
+
ignores: [
|
|
11
|
+
'node_modules/',
|
|
12
|
+
'dist/',
|
|
13
|
+
'.vinxi/',
|
|
14
|
+
'build/',
|
|
15
|
+
'coverage/',
|
|
16
|
+
'data/',
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
js.configs.recommended,
|
|
20
|
+
{
|
|
21
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
22
|
+
languageOptions: {
|
|
23
|
+
parser: tsparser,
|
|
24
|
+
parserOptions: {
|
|
25
|
+
ecmaVersion: 'latest',
|
|
26
|
+
sourceType: 'module',
|
|
27
|
+
ecmaFeatures: {
|
|
28
|
+
jsx: true,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
globals: {
|
|
32
|
+
...globals.browser,
|
|
33
|
+
...globals.node,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
plugins: {
|
|
37
|
+
'@typescript-eslint': tseslint,
|
|
38
|
+
react,
|
|
39
|
+
'react-hooks': reactHooks,
|
|
40
|
+
},
|
|
41
|
+
settings: {
|
|
42
|
+
react: {
|
|
43
|
+
version: 'detect',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
rules: {
|
|
47
|
+
...tseslint.configs.recommended.rules,
|
|
48
|
+
...react.configs.recommended.rules,
|
|
49
|
+
...reactHooks.configs.recommended.rules,
|
|
50
|
+
'@typescript-eslint/no-unused-vars': [
|
|
51
|
+
'error',
|
|
52
|
+
{
|
|
53
|
+
argsIgnorePattern: '^_',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
57
|
+
'react/react-in-jsx-scope': 'error',
|
|
58
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
59
|
+
'react-hooks/exhaustive-deps': 'warn',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
]
|
|
@@ -4,7 +4,6 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
|
|
|
4
4
|
import { useState } from 'react'
|
|
5
5
|
import { httpBatchLink } from '@trpc/client'
|
|
6
6
|
import { TRPCProvider, trpc } from '@/lib/api'
|
|
7
|
-
import type { AppRouter } from '@/server/api/root'
|
|
8
7
|
import { env } from '@/lib/env'
|
|
9
8
|
import '@/app/globals.css'
|
|
10
9
|
|
|
@@ -12,6 +11,8 @@ export const Route = createRootRoute({
|
|
|
12
11
|
component: RootComponent,
|
|
13
12
|
})
|
|
14
13
|
|
|
14
|
+
export const rootRoute = Route
|
|
15
|
+
|
|
15
16
|
function RootComponent() {
|
|
16
17
|
const [queryClient] = useState(() => new QueryClient())
|
|
17
18
|
const [trpcClient] = useState(() =>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createFileRoute } from '@tanstack/react-router'
|
|
2
2
|
import { auth } from '@/server/auth/config'
|
|
3
3
|
|
|
4
|
-
export const Route = createFileRoute('/api/auth
|
|
4
|
+
export const Route = createFileRoute('/api/auth/$')({
|
|
5
5
|
server: {
|
|
6
6
|
handlers: {
|
|
7
7
|
GET: async ({ request }: { request: Request }) => {
|
|
@@ -12,4 +12,4 @@ export const Route = createFileRoute('/api/auth/_')({
|
|
|
12
12
|
},
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
|
-
})
|
|
15
|
+
} as any)
|
|
@@ -8,7 +8,7 @@ export const Route = createFileRoute('/api/health')({
|
|
|
8
8
|
try {
|
|
9
9
|
const startTime = Date.now()
|
|
10
10
|
|
|
11
|
-
await db.select(
|
|
11
|
+
await (db as any).select().limit(1)
|
|
12
12
|
const dbLatency = Date.now() - startTime
|
|
13
13
|
|
|
14
14
|
return Response.json({
|
|
@@ -41,4 +41,4 @@ export const Route = createFileRoute('/api/health')({
|
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
|
-
})
|
|
44
|
+
} as any)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createFileRoute, useRouter } from '@tanstack/react-router'
|
|
2
2
|
import { useState } from 'react'
|
|
3
|
-
import { authClient } from '@/lib/auth'
|
|
4
3
|
import { Button } from '@/components/ui/button'
|
|
5
4
|
import { Input } from '@/components/ui/input'
|
|
6
5
|
import {
|
|
@@ -11,7 +10,7 @@ import {
|
|
|
11
10
|
CardTitle,
|
|
12
11
|
} from '@/components/ui/card'
|
|
13
12
|
|
|
14
|
-
export const Route = createFileRoute()({
|
|
13
|
+
export const Route = createFileRoute('/auth/forgot-password')({
|
|
15
14
|
component: ForgotPassword,
|
|
16
15
|
})
|
|
17
16
|
|
|
@@ -29,10 +28,22 @@ function ForgotPassword() {
|
|
|
29
28
|
setError('')
|
|
30
29
|
|
|
31
30
|
try {
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// Better-auth v1.4.17: Send password reset request to server
|
|
32
|
+
const response = await fetch('/api/auth/forget-password', {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
headers: {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
email,
|
|
39
|
+
redirectTo: '/auth/reset-password',
|
|
40
|
+
}),
|
|
34
41
|
})
|
|
35
42
|
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error('Failed to send reset email')
|
|
45
|
+
}
|
|
46
|
+
|
|
36
47
|
setMessage(
|
|
37
48
|
'If an account with this email exists, you will receive a password reset link.'
|
|
38
49
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createFileRoute, Link } from '@tanstack/react-router'
|
|
2
2
|
import { RegisterForm } from '@/components/features/auth/register-form'
|
|
3
3
|
|
|
4
|
-
export const Route = createFileRoute()({
|
|
4
|
+
export const Route = createFileRoute('/auth/register')({
|
|
5
5
|
component: Register,
|
|
6
6
|
})
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
CardTitle,
|
|
10
10
|
} from '@/components/ui/card'
|
|
11
11
|
|
|
12
|
-
export const Route = createFileRoute()({
|
|
12
|
+
export const Route = createFileRoute('/auth/verify-email')({
|
|
13
13
|
component: VerifyEmail,
|
|
14
14
|
})
|
|
15
15
|
|
|
@@ -26,6 +26,7 @@ function VerifyEmail() {
|
|
|
26
26
|
}, 3000)
|
|
27
27
|
return () => clearTimeout(timeout)
|
|
28
28
|
}
|
|
29
|
+
return undefined
|
|
29
30
|
}, [success, router])
|
|
30
31
|
|
|
31
32
|
return (
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createFileRoute, useRouter, redirect } from '@tanstack/react-router'
|
|
2
2
|
import React, { useState } from 'react'
|
|
3
|
-
import {
|
|
4
|
-
import { useTRPC } from '@/lib/api'
|
|
3
|
+
import { trpc } from '@/lib/api'
|
|
5
4
|
import { signOut } from '@/lib/auth'
|
|
6
5
|
import { Button } from '@/components/ui/button'
|
|
7
6
|
import { Input } from '@/components/ui/input'
|
|
@@ -47,9 +46,8 @@ export const Route = createFileRoute('/dashboard/settings')({
|
|
|
47
46
|
|
|
48
47
|
function Settings() {
|
|
49
48
|
const router = useRouter()
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const updateProfile = useMutation(trpc.user.updateProfile.mutationOptions())
|
|
49
|
+
const { data: user } = trpc.user.getProfile.useQuery()
|
|
50
|
+
const updateProfileMutation = trpc.user.updateProfile.useMutation()
|
|
53
51
|
|
|
54
52
|
const [name, setName] = useState('')
|
|
55
53
|
const [loading, setLoading] = useState(false)
|
|
@@ -69,7 +67,7 @@ function Settings() {
|
|
|
69
67
|
setError('')
|
|
70
68
|
|
|
71
69
|
try {
|
|
72
|
-
const result = await
|
|
70
|
+
const result = await updateProfileMutation.mutateAsync({
|
|
73
71
|
name,
|
|
74
72
|
})
|
|
75
73
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* prettier-ignore-start */
|
|
2
|
+
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
|
|
7
|
+
// noinspection JSUnusedGlobalSymbols
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This file is auto-generated by TanStack Router.
|
|
11
|
+
* Do not edit this file manually.
|
|
12
|
+
*
|
|
13
|
+
* This is a stub file for type-checking purposes.
|
|
14
|
+
* The actual route tree is generated at build/dev time by TanStack Router.
|
|
15
|
+
*
|
|
16
|
+
* When the dev server runs, this file will be replaced with the full route tree.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { rootRoute } from './__root'
|
|
20
|
+
|
|
21
|
+
// Stub route tree - this allows TypeScript to compile without errors
|
|
22
|
+
// The real route tree with proper types will be generated when you run the dev server
|
|
23
|
+
export const routeTree = rootRoute.addChildren([])
|
|
24
|
+
|
|
25
|
+
// Type augmentation to allow any route ID during development
|
|
26
|
+
declare module '@tanstack/react-router' {
|
|
27
|
+
interface FileRoutesByPath {
|
|
28
|
+
'/': any
|
|
29
|
+
'/_client': any
|
|
30
|
+
'/_ssr': any
|
|
31
|
+
'/api/health': any
|
|
32
|
+
'/api/auth/$': any
|
|
33
|
+
'/api/auth/_': any
|
|
34
|
+
'/api/auth/get-session': any
|
|
35
|
+
'/auth/login': any
|
|
36
|
+
'/auth/register': any
|
|
37
|
+
'/auth/forgot-password': any
|
|
38
|
+
'/auth/reset-password': any
|
|
39
|
+
'/auth/verify-email': any
|
|
40
|
+
'/dashboard/': any
|
|
41
|
+
'/dashboard/settings': any
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -186,7 +186,7 @@ export const { signOut } = authClient
|
|
|
186
186
|
* }
|
|
187
187
|
* ```
|
|
188
188
|
*/
|
|
189
|
-
export const { useSession,
|
|
189
|
+
export const { useSession, resetPassword } = authClient
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* Custom hook for common authentication patterns
|
|
@@ -214,12 +214,12 @@ export const { useSession, forgetPassword, resetPassword } = authClient
|
|
|
214
214
|
* ```
|
|
215
215
|
*/
|
|
216
216
|
export function useAuth() {
|
|
217
|
-
const { data: session,
|
|
217
|
+
const { data: session, isPending } = useSession()
|
|
218
218
|
|
|
219
219
|
return {
|
|
220
220
|
user: session?.user ?? null,
|
|
221
221
|
isAuthenticated: !!session?.user,
|
|
222
|
-
isLoading:
|
|
222
|
+
isLoading: isPending,
|
|
223
223
|
signOut,
|
|
224
224
|
}
|
|
225
225
|
}
|
|
@@ -5,11 +5,11 @@ import { eq, and, gte, sql } from 'drizzle-orm'
|
|
|
5
5
|
|
|
6
6
|
export const dashboardRouter = router({
|
|
7
7
|
getStats: protectedProcedure.query(async ({ ctx }) => {
|
|
8
|
-
const [totalUsersResult] = (await db
|
|
8
|
+
const [totalUsersResult] = (await (db as any)
|
|
9
9
|
.select({ count: sql<number>`count(*)` })
|
|
10
10
|
.from(users)) as any
|
|
11
11
|
|
|
12
|
-
const [activeUsersResult] = (await db
|
|
12
|
+
const [activeUsersResult] = (await (db as any)
|
|
13
13
|
.select({ count: sql<number>`count(*)` })
|
|
14
14
|
.from(users)
|
|
15
15
|
.where(
|
|
@@ -26,7 +26,7 @@ export const dashboardRouter = router({
|
|
|
26
26
|
}),
|
|
27
27
|
|
|
28
28
|
getUserProfile: protectedProcedure.query(async ({ ctx }) => {
|
|
29
|
-
const [user] = (await db
|
|
29
|
+
const [user] = (await (db as any)
|
|
30
30
|
.select()
|
|
31
31
|
.from(users)
|
|
32
32
|
.where(eq(users.id, ctx.user.id))
|
|
@@ -6,11 +6,11 @@ import { eq } from 'drizzle-orm'
|
|
|
6
6
|
|
|
7
7
|
export const userRouter = router({
|
|
8
8
|
getProfile: protectedProcedure.query(async ({ ctx }) => {
|
|
9
|
-
const result = await (db
|
|
9
|
+
const result = await (db as any)
|
|
10
10
|
.select()
|
|
11
11
|
.from(users)
|
|
12
12
|
.where(eq(users.id, ctx.user.id))
|
|
13
|
-
.limit(1)
|
|
13
|
+
.limit(1)
|
|
14
14
|
return result[0] ?? null
|
|
15
15
|
}),
|
|
16
16
|
|
|
@@ -21,11 +21,11 @@ export const userRouter = router({
|
|
|
21
21
|
})
|
|
22
22
|
)
|
|
23
23
|
.mutation(async ({ ctx, input }) => {
|
|
24
|
-
const result = await (db
|
|
24
|
+
const result = await (db as any)
|
|
25
25
|
.update(users)
|
|
26
26
|
.set({ name: input.name, updatedAt: new Date() })
|
|
27
27
|
.where(eq(users.id, ctx.user.id))
|
|
28
|
-
.returning()
|
|
28
|
+
.returning()
|
|
29
29
|
return result[0]
|
|
30
30
|
}),
|
|
31
31
|
})
|
|
@@ -108,10 +108,10 @@ export async function seedDatabase() {
|
|
|
108
108
|
]
|
|
109
109
|
|
|
110
110
|
try {
|
|
111
|
-
const result = await (db
|
|
111
|
+
const result = await (db as any)
|
|
112
112
|
.insert(users)
|
|
113
113
|
.values(sampleUsers)
|
|
114
|
-
.returning()
|
|
114
|
+
.returning()
|
|
115
115
|
console.log(`✓ Inserted ${result.length} users`)
|
|
116
116
|
console.log('✓ Database seeded successfully')
|
|
117
117
|
} catch (error: any) {
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json.schemastore.org/eslintrc",
|
|
3
|
-
"extends": [
|
|
4
|
-
"eslint:recommended",
|
|
5
|
-
"plugin:@typescript-eslint/recommended",
|
|
6
|
-
"plugin:react/recommended",
|
|
7
|
-
"plugin:react-hooks/recommended"
|
|
8
|
-
],
|
|
9
|
-
"plugins": ["@typescript-eslint", "react", "react-hooks"],
|
|
10
|
-
"parser": "@typescript-eslint/parser",
|
|
11
|
-
"parserOptions": {
|
|
12
|
-
"ecmaVersion": "latest",
|
|
13
|
-
"sourceType": "module",
|
|
14
|
-
"ecmaFeatures": {
|
|
15
|
-
"jsx": true
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
"settings": {
|
|
19
|
-
"react": {
|
|
20
|
-
"version": "detect"
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
"rules": {
|
|
24
|
-
"@typescript-eslint/no-unused-vars": [
|
|
25
|
-
"error",
|
|
26
|
-
{
|
|
27
|
-
"argsIgnorePattern": "^_"
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
"@typescript-eslint/no-explicit-any": "error",
|
|
31
|
-
"react/react-in-jsx-scope": "error",
|
|
32
|
-
"react-hooks/rules-of-hooks": "error",
|
|
33
|
-
"react-hooks/exhaustive-deps": "warn"
|
|
34
|
-
}
|
|
35
|
-
}
|