create-ej-app 20.0.0 → 21.0.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/cli.js CHANGED
@@ -1,14 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
- return new (P || (P = Promise))(function (resolve, reject) {
6
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
- step((generator = generator.apply(thisArg, _arguments || [])).next());
10
- });
11
- };
12
3
  var __importDefault = (this && this.__importDefault) || function (mod) {
13
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
14
5
  };
@@ -54,8 +45,8 @@ const getDevCommand = (packageManager) => {
54
45
  return 'npm run dev';
55
46
  }
56
47
  };
57
- commander_1.program.action(() => __awaiter(void 0, void 0, void 0, function* () {
58
- const response = yield (0, enquirer_1.prompt)([
48
+ commander_1.program.action(async () => {
49
+ const response = await (0, enquirer_1.prompt)([
59
50
  {
60
51
  type: 'input',
61
52
  name: 'projectName',
@@ -139,5 +130,5 @@ ${devCommand}
139
130
 
140
131
  Happy coding! 🚀
141
132
  `);
142
- }));
133
+ });
143
134
  commander_1.program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ej-app",
3
- "version": "20.0.0",
3
+ "version": "21.0.0",
4
4
  "description": "Bootstrap a next.js app with my preferred setup",
5
5
  "main": "cli.js",
6
6
  "scripts": {
@@ -34,7 +34,7 @@
34
34
  "enquirer": "^2.4.1"
35
35
  },
36
36
  "devDependencies": {
37
- "@types/node": "^25.5.0",
38
- "typescript": "^5.9.3"
37
+ "@types/node": "^25.6.2",
38
+ "typescript": "^6.0.3"
39
39
  }
40
40
  }
@@ -14,18 +14,18 @@
14
14
  "db:seed": "bun ./src/scripts/seed.ts"
15
15
  },
16
16
  "dependencies": {
17
- "@elysiajs/openapi": "1.4.14",
17
+ "@elysiajs/openapi": "1.4.15",
18
18
  "@t3-oss/env-core": "0.13.11",
19
- "drizzle-orm": "0.45.1",
19
+ "drizzle-orm": "0.45.2",
20
20
  "elysia": "1.4.28",
21
- "zod": "4.3.6"
21
+ "zod": "4.4.3"
22
22
  },
23
23
  "devDependencies": {
24
- "@types/bun": "1.3.11",
25
- "@typescript/native-preview": "7.0.0-dev.20260326.1",
24
+ "@types/bun": "1.3.13",
25
+ "@typescript/native-preview": "7.0.0-dev.20260508.1",
26
26
  "drizzle-kit": "0.31.10",
27
- "postgres": "3.4.8",
28
- "prettier": "3.8.1",
27
+ "postgres": "3.4.9",
28
+ "prettier": "3.8.3",
29
29
  "prettier-plugin-organize-imports": "4.3.0"
30
30
  }
31
31
  }
@@ -23,55 +23,54 @@
23
23
  "dependencies": {
24
24
  "@ejekanshjain/simple-email-validator": "1.0.4",
25
25
  "@hookform/resolvers": "5.2.2",
26
- "@next/third-parties": "16.2.1",
26
+ "@next/third-parties": "16.2.6",
27
27
  "@opentelemetry/api": "1.9.1",
28
- "@opentelemetry/sdk-trace-base": "2.6.1",
28
+ "@opentelemetry/sdk-trace-base": "2.7.1",
29
29
  "@paralleldrive/cuid2": "3.3.0",
30
- "@react-email/components": "1.0.10",
31
- "@react-email/render": "2.0.4",
30
+ "@react-email/render": "2.0.8",
32
31
  "@t3-oss/env-nextjs": "0.13.11",
33
- "@tanstack/react-query": "5.95.2",
34
- "@vercel/otel": "2.1.1",
35
- "better-auth": "1.5.6",
32
+ "@tanstack/react-query": "5.100.9",
33
+ "@vercel/otel": "2.1.2",
34
+ "better-auth": "1.6.9",
36
35
  "class-variance-authority": "0.7.1",
37
36
  "clsx": "2.1.1",
38
- "drizzle-orm": "0.45.1",
39
- "lucide-react": "1.7.0",
40
- "next": "16.2.1",
41
- "next-safe-action": "8.1.8",
42
- "next-themes": "0.4.6",
37
+ "drizzle-orm": "0.45.2",
38
+ "lucide-react": "1.14.0",
39
+ "next": "16.2.6",
40
+ "next-safe-action": "8.5.2",
41
+ "next-themes": "^0.4.6",
43
42
  "nextjs-toploader": "3.9.17",
44
- "nodemailer": "8.0.4",
45
- "postgres": "3.4.8",
43
+ "nodemailer": "8.0.7",
44
+ "postgres": "3.4.9",
46
45
  "radix-ui": "1.4.3",
47
- "react": "19.2.4",
48
- "react-dom": "19.2.4",
49
- "react-hook-form": "7.72.0",
50
- "sonner": "2.0.7",
46
+ "react": "19.2.6",
47
+ "react-dom": "19.2.6",
48
+ "react-hook-form": "7.75.0",
49
+ "sonner": "^2.0.7",
51
50
  "tailwind-merge": "3.5.0",
52
51
  "tw-animate-css": "1.4.0",
53
- "workflow": "4.2.0-beta.72",
54
- "zod": "4.3.6"
52
+ "workflow": "4.2.4",
53
+ "zod": "4.4.3"
55
54
  },
56
55
  "devDependencies": {
57
- "@next/bundle-analyzer": "16.2.1",
56
+ "@next/bundle-analyzer": "16.2.6",
58
57
  "@react-email/preview-server": "5.2.10",
59
- "@tailwindcss/postcss": "4.2.2",
60
- "@types/bun": "1.3.11",
61
- "@types/nodemailer": "7.0.11",
58
+ "@tailwindcss/postcss": "4.2.4",
59
+ "@types/bun": "1.3.13",
60
+ "@types/nodemailer": "8.0.0",
62
61
  "@types/react": "19.2.14",
63
62
  "@types/react-dom": "19.2.3",
64
- "@typescript/native-preview": "7.0.0-dev.20260326.1",
63
+ "@typescript/native-preview": "7.0.0-dev.20260508.1",
65
64
  "babel-plugin-react-compiler": "1.0.0",
66
65
  "drizzle-kit": "0.31.10",
67
66
  "eslint": "9.39.4",
68
- "eslint-config-next": "16.2.1",
69
- "prettier": "3.8.1",
67
+ "eslint-config-next": "16.2.6",
68
+ "prettier": "3.8.3",
70
69
  "prettier-plugin-organize-imports": "4.3.0",
71
- "prettier-plugin-tailwindcss": "0.7.2",
72
- "react-email": "5.2.10",
73
- "tailwindcss": "4.2.2",
74
- "typescript": "6.0.2"
70
+ "prettier-plugin-tailwindcss": "0.8.0",
71
+ "react-email": "6.1.1",
72
+ "tailwindcss": "4.2.4",
73
+ "typescript": "6.0.3"
75
74
  },
76
75
  "trustedDependencies": [
77
76
  "@nestjs/core",
@@ -5,7 +5,7 @@ import * as React from 'react'
5
5
  import { cn } from '~/lib/cn'
6
6
 
7
7
  const buttonVariants = cva(
8
- "group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ "group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
9
9
  {
10
10
  variants: {
11
11
  variant: {
@@ -25,7 +25,7 @@ const buttonVariants = cva(
25
25
  'h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
26
26
  xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
27
27
  sm: 'h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5',
28
- lg: 'h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',
28
+ lg: 'h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
29
29
  icon: 'size-9',
30
30
  'icon-xs':
31
31
  "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
@@ -120,7 +120,7 @@ function FieldTitle({ className, ...props }: React.ComponentProps<'div'>) {
120
120
  <div
121
121
  data-slot="field-label"
122
122
  className={cn(
123
- 'flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50',
123
+ 'flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50',
124
124
  className
125
125
  )}
126
126
  {...props}
@@ -1,7 +1,50 @@
1
1
  import { drizzle } from 'drizzle-orm/postgres-js'
2
+ import postgres from 'postgres'
2
3
  import { env } from '~/env'
3
4
  import * as schema from './schema'
4
5
 
5
- export const db = drizzle(env.DATABASE_URL, {
6
+ // In development, Next.js hot-reloading can re-evaluate modules frequently.
7
+ // Keep a single postgres-js client on `globalThis` to avoid opening multiple
8
+ // database connections during local development.
9
+ const globalForDb = globalThis as unknown as {
10
+ client?: ReturnType<typeof postgres>
11
+ }
12
+
13
+ // Prefer the cached client (dev) and fall back to creating a new one.
14
+ // `max: 1` limits the pool size, and `prepare: false` disables prepared
15
+ // statements for compatibility with environments where prepared statements
16
+ // can be problematic.
17
+ const client =
18
+ globalForDb.client ??
19
+ postgres(env.DATABASE_URL, {
20
+ max: 1,
21
+ prepare: false
22
+ })
23
+
24
+ // Only cache the client outside production to avoid unexpected cross-request
25
+ // state retention in long-lived production processes.
26
+ if (env.APP_ENV !== 'production') globalForDb.client = client
27
+
28
+ /**
29
+ * Drizzle ORM database client for PostgreSQL.
30
+ *
31
+ * Backed by a postgres-js client configured via `env.DATABASE_URL`, and wired
32
+ * up with schema + relations so you get typed query helpers.
33
+ *
34
+ * Use this instance throughout the app for all database operations.
35
+ *
36
+ * @example
37
+ * const users = await db.query.usersTable.findMany()
38
+ * const newUser = await db.insert(usersTable).values({ email: 'user@example.com' })
39
+ *
40
+ * @example
41
+ * await db.transaction(async (tx) => {
42
+ * await tx.insert(usersTable).values({ email: 'user@example.com' })
43
+ * })
44
+ */
45
+ export const db = drizzle(client, {
6
46
  schema: { ...schema }
7
47
  })
48
+
49
+ /** The transaction client type passed into `db.transaction(async (tx) => ...)`. */
50
+ export type DbTx = Parameters<Parameters<(typeof db)['transaction']>[0]>[0]
@@ -9,7 +9,7 @@ import {
9
9
  Section,
10
10
  Tailwind,
11
11
  Text
12
- } from '@react-email/components'
12
+ } from 'react-email'
13
13
 
14
14
  interface EmailLayoutProps {
15
15
  previewText: string
@@ -1,4 +1,4 @@
1
- import { Button, Heading, Text } from '@react-email/components'
1
+ import { Button, Heading, Text } from 'react-email'
2
2
  import EmailLayout from './components/email-layout'
3
3
 
4
4
  export interface MagicLinkEmailProps {
@@ -1,4 +1,4 @@
1
- import { Button, Heading, Text } from '@react-email/components'
1
+ import { Button, Heading, Text } from 'react-email'
2
2
  import EmailLayout from './components/email-layout'
3
3
 
4
4
  interface TestEmailProps {
@@ -1,4 +1,4 @@
1
- import { Heading, Text } from '@react-email/components'
1
+ import { Heading, Text } from 'react-email'
2
2
  import EmailLayout from './components/email-layout'
3
3
 
4
4
  export interface WelcomeEmailProps {
package/tsconfig.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "outDir": "./",
4
- "lib": ["ESNext", "DOM"],
5
- "target": "es2016",
6
- "module": "commonjs",
4
+ "target": "ES2022",
5
+ "lib": ["ES2022"],
6
+ "module": "Node16",
7
+ "moduleResolution": "Node16",
8
+ "types": ["node"],
7
9
  "esModuleInterop": true,
8
10
  "forceConsistentCasingInFileNames": true,
9
11
  "strict": true,