@tanstack/cta-framework-react-cra 0.33.3 → 0.34.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.
@@ -0,0 +1,7 @@
1
+ <% if (addOnOption.drizzle.database === 'postgresql') { %>
2
+ # Database URL for PostgreSQL
3
+ DATABASE_URL="postgresql://username:password@localhost:5432/mydb"<% } else if (addOnOption.drizzle.database === 'mysql') { %>
4
+ # Database URL for MySQL
5
+ DATABASE_URL="mysql://username:password@localhost:3306/mydb"<% } else if (addOnOption.drizzle.database === 'sqlite') { %>
6
+ # Database URL for SQLite
7
+ DATABASE_URL="file:./dev.db"<% } %>
@@ -0,0 +1,13 @@
1
+ import { config } from "dotenv";
2
+ import { defineConfig } from 'drizzle-kit';
3
+
4
+ config();
5
+
6
+ export default defineConfig({
7
+ out: "./drizzle",
8
+ schema: "./src/db/schema.ts",
9
+ dialect: '<%= addOnOption.drizzle.database %>',
10
+ dbCredentials: {
11
+ url: process.env.DATABASE_URL,
12
+ },
13
+ });
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="160" height="160" fill="none" viewBox="0 0 160 160"><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 43.48 67.304)"/><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 76.94 46.534)"/><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 128.424 46.535)"/><rect width="9.631" height="40.852" fill="#C5F74F" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 94.957 67.304)"/></svg>
@@ -0,0 +1,27 @@
1
+ import { config } from 'dotenv'
2
+ <% if (addOnOption.drizzle.database === 'postgresql') { %>
3
+ import { drizzle } from 'drizzle-orm/node-postgres';
4
+ import { Pool } from 'pg';
5
+ <% } else if (addOnOption.drizzle.database === 'mysql') {%>
6
+ import { drizzle } from 'drizzle-orm/mysql2';
7
+ import mysql from 'mysql2/promise';
8
+ <% } else if (addOnOption.drizzle.database === 'sqlite') {%>
9
+ import { drizzle } from 'drizzle-orm/better-sqlite3';
10
+ import Database from 'better-sqlite3';
11
+ <% } %>
12
+ import * as schema from './schema.ts'
13
+
14
+ config()
15
+
16
+ <% if (addOnOption.drizzle.database === 'sqlite') { %>
17
+ const sqlite = new Database(process.env.DATABASE_URL!);
18
+ export const db = drizzle(sqlite, { schema });
19
+ <% } else if (addOnOption.drizzle.database === 'postgresql') { %>
20
+ const pool = new Pool({
21
+ connectionString: process.env.DATABASE_URL!,
22
+ });
23
+ export const db = drizzle(pool, { schema });
24
+ <% } else if (addOnOption.drizzle.database === 'mysql') { %>
25
+ const connection = await mysql.createConnection(process.env.DATABASE_URL!);
26
+ export const db = drizzle(connection, { schema });
27
+ <% } %>
@@ -0,0 +1,32 @@
1
+ <% if (addOnOption.drizzle.database === 'postgresql') { %>
2
+ import { pgTable, serial, text, timestamp } from
3
+ 'drizzle-orm/pg-core';
4
+
5
+ export const todos = pgTable('todos', {
6
+ id: serial('id').primaryKey(),
7
+ title: text('title').notNull(),
8
+ createdAt: timestamp('created_at').defaultNow(),
9
+ });
10
+ <% } else if (addOnOption.drizzle.database === 'mysql') {
11
+ %>
12
+ import { mysqlTable, int, text, timestamp } from
13
+ 'drizzle-orm/mysql-core';
14
+
15
+ export const todos = mysqlTable('todos', {
16
+ id: int('id').primaryKey().autoincrement(),
17
+ title: text('title').notNull(),
18
+ createdAt: timestamp('created_at', { mode: 'date' }).defaultNow(),
19
+ });
20
+ <% } else if (addOnOption.drizzle.database === 'sqlite') {
21
+ %>
22
+ import { sqliteTable, integer, text } from
23
+ 'drizzle-orm/sqlite-core';
24
+ import { sql } from 'drizzle-orm';
25
+
26
+ export const todos = sqliteTable('todos', {
27
+ id: integer('id', { mode: 'number' }).primaryKey({
28
+ autoIncrement: true }),
29
+ title: text('title').notNull(),
30
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`(unixepoch())`),
31
+ });
32
+ <% } %>
@@ -0,0 +1,187 @@
1
+ import { createFileRoute, useRouter } from '@tanstack/react-router'
2
+ import { createServerFn } from '@tanstack/react-start'
3
+ import { db } from '@/db'
4
+ import { desc } from 'drizzle-orm'
5
+ import { todos } from '@/db/schema'
6
+
7
+ const getTodos = createServerFn({
8
+ method: 'GET',
9
+ }).handler(async () => {
10
+ return await db.query.todos.findMany({
11
+ orderBy: [desc(todos.createdAt)],
12
+ })
13
+ })
14
+
15
+ const createTodo = createServerFn({
16
+ method: 'POST',
17
+ })
18
+ .inputValidator((data: { title: string }) => data)
19
+ .handler(async ({ data }) => {
20
+ await db.insert(todos).values({ title: data.title })
21
+ return { success: true }
22
+ })
23
+
24
+ export const Route = createFileRoute('/demo/drizzle')({
25
+ component: DemoDrizzle,
26
+ loader: async () => await getTodos(),
27
+ })
28
+
29
+ function DemoDrizzle() {
30
+ const router = useRouter()
31
+ const todos = Route.useLoaderData()
32
+
33
+ const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
34
+ e.preventDefault()
35
+ const formData = new FormData(e.target as HTMLFormElement)
36
+ const title = formData.get('title') as string
37
+
38
+ if (!title) return
39
+
40
+ try {
41
+ await createTodo({ data: { title } })
42
+ router.invalidate()
43
+ ;(e.target as HTMLFormElement).reset()
44
+ } catch (error) {
45
+ console.error('Failed to create todo:', error)
46
+ }
47
+ }
48
+
49
+ return (
50
+ <div
51
+ className="flex items-center justify-center min-h-screen p-4 text-white"
52
+ style={{
53
+ background:
54
+ 'linear-gradient(135deg, #0c1a2b 0%, #1a2332 50%, #16202e 100%)',
55
+ }}
56
+ >
57
+ <div
58
+ className="w-full max-w-2xl p-8 rounded-xl shadow-2xl border border-white/10"
59
+ style={{
60
+ background:
61
+ 'linear-gradient(135deg, rgba(22, 32, 46, 0.95) 0%, rgba(12, 26, 43, 0.95) 100%)',
62
+ backdropFilter: 'blur(10px)',
63
+ }}
64
+ >
65
+ <div
66
+ className="flex items-center justify-center gap-4 mb-8 p-4 rounded-lg"
67
+ style={{
68
+ background:
69
+ 'linear-gradient(90deg, rgba(93, 103, 227, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%)',
70
+ border: '1px solid rgba(93, 103, 227, 0.2)',
71
+ }}
72
+ >
73
+ <div className="relative group">
74
+ <div className="absolute -inset-2 bg-gradient-to-r from-indigo-500 via-purple-500 to-indigo-500 rounded-lg blur-lg opacity-60 group-hover:opacity-100 transition duration-500"></div>
75
+ <div className="relative bg-gradient-to-br from-indigo-600 to-purple-600 p-3 rounded-lg">
76
+ <img
77
+ src="/drizzle.svg"
78
+ alt="Drizzle Logo"
79
+ className="w-8 h-8 transform group-hover:scale-110 transition-transform duration-300"
80
+ />
81
+ </div>
82
+ </div>
83
+ <h1 className="text-3xl font-bold bg-gradient-to-r from-indigo-300 via-purple-300 to-indigo-300 text-transparent bg-clip-text">
84
+ Drizzle Database Demo
85
+ </h1>
86
+ </div>
87
+
88
+ <h2 className="text-2xl font-bold mb-4 text-indigo-200">Todos</h2>
89
+
90
+ <ul className="space-y-3 mb-6">
91
+ {todos.map((todo) => (
92
+ <li
93
+ key={todo.id}
94
+ className="rounded-lg p-4 shadow-md border transition-all hover:scale-[1.02] cursor-pointer group"
95
+ style={{
96
+ background:
97
+ 'linear-gradient(135deg, rgba(93, 103, 227, 0.15) 0%, rgba(139, 92, 246, 0.15) 100%)',
98
+ borderColor: 'rgba(93, 103, 227, 0.3)',
99
+ }}
100
+ >
101
+ <div className="flex items-center justify-between">
102
+ <span className="text-lg font-medium text-white group-hover:text-indigo-200 transition-colors">
103
+ {todo.title}
104
+ </span>
105
+ <span className="text-xs text-indigo-300/70">#{todo.id}</span>
106
+ </div>
107
+ </li>
108
+ ))}
109
+ {todos.length === 0 && (
110
+ <li className="text-center py-8 text-indigo-300/70">
111
+ No todos yet. Create one below!
112
+ </li>
113
+ )}
114
+ </ul>
115
+
116
+ <form onSubmit={handleSubmit} className="flex gap-2">
117
+ <input
118
+ type="text"
119
+ name="title"
120
+ placeholder="Add a new todo..."
121
+ className="flex-1 px-4 py-3 rounded-lg border focus:outline-none focus:ring-2 transition-all text-white placeholder-indigo-300/50"
122
+ style={{
123
+ background: 'rgba(93, 103, 227, 0.1)',
124
+ borderColor: 'rgba(93, 103, 227, 0.3)',
125
+ focusRing: 'rgba(93, 103, 227, 0.5)',
126
+ }}
127
+ />
128
+ <button
129
+ type="submit"
130
+ className="px-6 py-3 font-semibold rounded-lg shadow-lg transition-all duration-200 hover:shadow-xl hover:scale-105 active:scale-95 whitespace-nowrap"
131
+ style={{
132
+ background: 'linear-gradient(135deg, #5d67e3 0%, #8b5cf6 100%)',
133
+ color: 'white',
134
+ }}
135
+ >
136
+ Add Todo
137
+ </button>
138
+ </form>
139
+
140
+ <div
141
+ className="mt-8 p-6 rounded-lg border"
142
+ style={{
143
+ background: 'rgba(93, 103, 227, 0.05)',
144
+ borderColor: 'rgba(93, 103, 227, 0.2)',
145
+ }}
146
+ >
147
+ <h3 className="text-lg font-semibold mb-2 text-indigo-200">
148
+ Powered by Drizzle ORM
149
+ </h3>
150
+ <p className="text-sm text-indigo-300/80 mb-4">
151
+ Next-generation ORM for Node.js & TypeScript with PostgreSQL
152
+ </p>
153
+ <div className="space-y-2 text-sm">
154
+ <p className="text-indigo-200 font-medium">Setup Instructions:</p>
155
+ <ol className="list-decimal list-inside space-y-2 text-indigo-300/80">
156
+ <li>
157
+ Configure your{' '}
158
+ <code className="px-2 py-1 rounded bg-black/30 text-purple-300">
159
+ DATABASE_URL
160
+ </code>{' '}
161
+ in .env.local
162
+ </li>
163
+ <li>
164
+ Run:{' '}
165
+ <code className="px-2 py-1 rounded bg-black/30 text-purple-300">
166
+ npx drizzle-kit generate
167
+ </code>
168
+ </li>
169
+ <li>
170
+ Run:{' '}
171
+ <code className="px-2 py-1 rounded bg-black/30 text-purple-300">
172
+ npx drizzle-kit migrate
173
+ </code>
174
+ </li>
175
+ <li>
176
+ Optional:{' '}
177
+ <code className="px-2 py-1 rounded bg-black/30 text-purple-300">
178
+ npx drizzle-kit studio
179
+ </code>
180
+ </li>
181
+ </ol>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ )
187
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "Drizzle",
3
+ "description": "Add Drizzle ORM to your application.",
4
+ "phase": "add-on",
5
+ "type": "add-on",
6
+ "priority": 48,
7
+ "link": "https://orm.drizzle.team/",
8
+ "modes": ["file-router"],
9
+ "dependsOn": ["start"],
10
+ "options": {
11
+ "database": {
12
+ "type": "select",
13
+ "label": "Database Provider",
14
+ "description": "Choose your database provider",
15
+ "default": "postgresql",
16
+ "options": [
17
+ { "value": "postgresql", "label": "PostgreSQL" },
18
+ { "value": "sqlite", "label": "SQLite" },
19
+ { "value": "mysql", "label": "MySQL" }
20
+ ]
21
+ }
22
+ },
23
+ "routes": [
24
+ {
25
+ "icon": "Database",
26
+ "url": "/demo/drizzle",
27
+ "name": "Drizzle",
28
+ "path": "src/routes/demo/drizzle.tsx",
29
+ "jsName": "DemoDrizzle"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "dependencies": {
3
+ "drizzle-orm": "^0.39.0",
4
+ "drizzle-kit": "^0.30.0"<% if (addOnOption.drizzle.database === 'postgresql') { %>,
5
+ "pg": "^8.11.0"<% } %><% if (addOnOption.drizzle.database === 'mysql') { %>,
6
+ "mysql2": "^3.6.0"<% } %><% if (addOnOption.drizzle.database === 'sqlite') { %>,
7
+ "better-sqlite3": "^9.4.0"<% } %>
8
+ },
9
+ "devDependencies": {
10
+ "dotenv": "^16.0.0",
11
+ "tsx": "^4.0.0",
12
+ <% if (addOnOption.drizzle.database === 'postgresql') { %>
13
+ "@types/pg": "^8.10.0"<% } %><% if (addOnOption.drizzle.database === 'mysql') { %>
14
+ "@types/mysql2": "^3.6.0"<% } %><% if (addOnOption.drizzle.database === 'sqlite') { %>
15
+ "@types/better-sqlite3": "^7.6.0"<% } %>
16
+ },
17
+ "scripts": {
18
+ "db:generate": "drizzle-kit generate",
19
+ "db:migrate": "drizzle-kit migrate",
20
+ "db:push": "drizzle-kit push",
21
+ "db:pull": "drizzle-kit pull",
22
+ "db:studio": "drizzle-kit studio"
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="160" height="160" fill="none" viewBox="0 0 160 160"><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 43.48 67.304)"/><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 76.94 46.534)"/><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 128.424 46.535)"/><rect width="9.631" height="40.852" fill="#121212" rx="4.816" transform="matrix(.87303 .48767 -.49721 .86763 94.957 67.304)"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-framework-react-cra",
3
- "version": "0.33.3",
3
+ "version": "0.34.0",
4
4
  "description": "CTA Framework for React (Create React App)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "author": "Jack Herrington <jherr@pobox.com>",
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "@tanstack/cta-engine": "0.33.3"
26
+ "@tanstack/cta-engine": "0.34.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^24.6.0",