@tanstack/cta-framework-react-cra 0.10.0-alpha.21 → 0.10.0-alpha.26

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,3 @@
1
+ ## Setting up Neon
2
+
3
+ - Set the `DATABASE_URL` in your `.env`.
@@ -0,0 +1,2 @@
1
+ # Neon database URL
2
+ DATABASE_URL=
@@ -0,0 +1,14 @@
1
+ -- Schema for a simple to-do list
2
+ CREATE TABLE IF NOT EXISTS todos (
3
+ id SERIAL PRIMARY KEY,
4
+ title VARCHAR(255) NOT NULL,
5
+ description TEXT,
6
+ is_completed BOOLEAN DEFAULT FALSE,
7
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
8
+ );
9
+
10
+ -- Initial data for the to-do list
11
+ INSERT INTO todos (title, description, is_completed) VALUES
12
+ ('Buy groceries', 'Milk, Bread, Eggs, and Butter', FALSE),
13
+ ('Read a book', 'Finish reading "The Great Gatsby"', FALSE),
14
+ ('Workout', 'Go for a 30-minute run', FALSE);
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" width="256" height="256" preserveAspectRatio="xMidYMid"><defs><linearGradient id="a" x1="100%" x2="12.069%" y1="100%" y2="0%"><stop offset="0%" stop-color="#62F755"/><stop offset="100%" stop-color="#8FF986" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="100%" x2="40.603%" y1="100%" y2="76.897%"><stop offset="0%" stop-opacity=".9"/><stop offset="100%" stop-color="#1A1A1A" stop-opacity="0"/></linearGradient></defs><path fill="#00E0D9" d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"/><path fill="url(#a)" d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"/><path fill="url(#b)" fill-opacity=".4" d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"/><path fill="#63F655" d="M211.861 0C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723a4.409 4.409 0 0 0 4.409-4.409V115.058c0-25.223 31.914-36.167 47.395-16.256l48.391 62.243V8.825c0-4.871-3.953-8.825-8.832-8.825Z"/></svg>
@@ -0,0 +1,13 @@
1
+ import { neon } from '@neondatabase/serverless'
2
+
3
+ let client: ReturnType<typeof neon>
4
+
5
+ export async function getClient() {
6
+ if (!process.env.DATABASE_URL) {
7
+ return undefined
8
+ }
9
+ if (!client) {
10
+ client = await neon(process.env.DATABASE_URL!)
11
+ }
12
+ return client
13
+ }
@@ -0,0 +1,168 @@
1
+ import { createServerFn } from '@tanstack/react-start'
2
+ import { createFileRoute, useRouter } from '@tanstack/react-router'
3
+
4
+ import { getClient } from '@/db'
5
+
6
+ const getTodos = createServerFn({
7
+ method: 'GET',
8
+ }).handler(async () => {
9
+ const client = await getClient()
10
+ if (!client) {
11
+ return undefined
12
+ }
13
+ return (await client.query(`SELECT * FROM todos`)) as Array<{
14
+ id: number
15
+ title: string
16
+ }>
17
+ })
18
+
19
+ const insertTodo = createServerFn({
20
+ method: 'POST',
21
+ })
22
+ .validator((d: { title: string }) => d)
23
+ .handler(async ({ data }) => {
24
+ const client = await getClient()
25
+ if (!client) {
26
+ return undefined
27
+ }
28
+ await client.query(`INSERT INTO todos (title) VALUES ($1)`, [data.title])
29
+ })
30
+
31
+ export const Route = createFileRoute('/demo/neon')({
32
+ component: App,
33
+ loader: async () => {
34
+ const todos = await getTodos()
35
+ return { todos }
36
+ },
37
+ })
38
+
39
+ function App() {
40
+ const { todos } = Route.useLoaderData()
41
+ const router = useRouter()
42
+
43
+ const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
44
+ e.preventDefault()
45
+ const formData = new FormData(e.target as HTMLFormElement)
46
+ const data = Object.fromEntries(formData)
47
+ await insertTodo({ data: { title: data.title as string } })
48
+ router.invalidate()
49
+ }
50
+
51
+ if (!todos) {
52
+ return <DBConnectionError />
53
+ }
54
+
55
+ return (
56
+ <div
57
+ className="flex items-center justify-center min-h-screen bg-gradient-to-br from-purple-100 to-blue-100 p-4 text-white"
58
+ style={{
59
+ backgroundImage:
60
+ 'radial-gradient(circle at 5% 40%, #63F655 0%, #00E0D9 40%, #1a0f0a 100%)',
61
+ }}
62
+ >
63
+ <div className="w-full max-w-2xl p-8 rounded-xl backdrop-blur-md bg-black/50 shadow-xl border-8 border-black/10">
64
+ <div className="flex items-center justify-center gap-4 mb-8 bg-black/30 p-4 rounded-lg">
65
+ <div className="relative">
66
+ <div className="absolute -inset-1 bg-gradient-to-r from-emerald-400 to-cyan-400 rounded-lg blur opacity-75 group-hover:opacity-100 transition duration-1000"></div>
67
+ <div className="relative">
68
+ <img
69
+ src="/demo-neon.svg"
70
+ alt="Neon Logo"
71
+ className="w-12 h-12 transform hover:scale-110 transition-transform duration-200"
72
+ />
73
+ </div>
74
+ </div>
75
+ <h1 className="text-3xl font-bold bg-gradient-to-r from-emerald-200 to-cyan-200 text-transparent bg-clip-text">
76
+ Neon Database Demo
77
+ </h1>
78
+ </div>
79
+ {todos && (
80
+ <>
81
+ <h1 className="text-2xl font-bold mb-4">Todos</h1>
82
+ <ul className="space-y-3 mb-6">
83
+ {todos.map((todo: { id: number; title: string }) => (
84
+ <li
85
+ key={todo.id}
86
+ className="bg-white/10 backdrop-blur-sm rounded-lg p-4 shadow-sm border border-white/20 transition-all hover:bg-white/20 hover:scale-[1.02] cursor-pointer group"
87
+ >
88
+ <div className="flex items-center justify-between">
89
+ <span className="text-lg font-medium group-hover:text-white/90">
90
+ {todo.title}
91
+ </span>
92
+ <span className="text-xs text-white/50">#{todo.id}</span>
93
+ </div>
94
+ </li>
95
+ ))}
96
+ </ul>
97
+ <form onSubmit={handleSubmit} className="mt-4 flex gap-2">
98
+ <input
99
+ type="text"
100
+ name="title"
101
+ className="w-full px-4 py-2 rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-[#00E0D9] bg-black/20"
102
+ />
103
+ <button
104
+ type="submit"
105
+ className="px-6 py-2 bg-[#00E0D9] text-black font-medium rounded-md hover:bg-[#00E0D9]/80 focus:outline-none focus:ring-2 focus:ring-[#00E0D9] focus:ring-offset-2 transition-colors disabled:opacity-50 whitespace-nowrap"
106
+ >
107
+ Add Todo
108
+ </button>
109
+ </form>
110
+ </>
111
+ )}
112
+ </div>
113
+ </div>
114
+ )
115
+ }
116
+
117
+ function DBConnectionError() {
118
+ return (
119
+ <div className="text-center space-y-6">
120
+ <div className="flex items-center justify-center mb-4">
121
+ <svg
122
+ className="w-12 h-12 text-amber-500"
123
+ fill="none"
124
+ stroke="currentColor"
125
+ viewBox="0 0 24 24"
126
+ xmlns="http://www.w3.org/2000/svg"
127
+ >
128
+ <path
129
+ strokeLinecap="round"
130
+ strokeLinejoin="round"
131
+ strokeWidth="2"
132
+ d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
133
+ />
134
+ </svg>
135
+ </div>
136
+ <h2 className="text-2xl font-bold mb-4">Database Connection Issue</h2>
137
+ <div className="text-lg mb-6">The Neon database is not connected.</div>
138
+ <div className="bg-black/30 p-6 rounded-lg max-w-xl mx-auto">
139
+ <h3 className="text-lg font-semibold mb-4">Required Steps to Fix:</h3>
140
+ <ul className="space-y-4 text-left list-none">
141
+ <li className="flex items-start">
142
+ <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-amber-500 text-black font-bold mr-3 min-w-8 min-h-8">
143
+ 1
144
+ </span>
145
+ <div>
146
+ Use the{' '}
147
+ <code className="bg-black/30 px-2 py-1 rounded">db/init.sql</code>{' '}
148
+ file to create the database
149
+ </div>
150
+ </li>
151
+ <li className="flex items-start">
152
+ <span className="inline-flex items-center justify-center w-8 h-8 rounded-full bg-amber-500 text-black font-bold mr-3 min-w-8 min-h-8">
153
+ 2
154
+ </span>
155
+ <div>
156
+ Set the{' '}
157
+ <code className="bg-black/30 px-2 py-1 rounded">
158
+ DATABASE_URL
159
+ </code>{' '}
160
+ environment variable to the connection string of your Neon
161
+ database
162
+ </div>
163
+ </li>
164
+ </ul>
165
+ </div>
166
+ </div>
167
+ )
168
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "Neon",
3
+ "description": "Add the Neon database to your application.",
4
+ "link": "https://neon.tech",
5
+ "phase": "add-on",
6
+ "type": "add-on",
7
+ "modes": ["file-router"],
8
+ "routes": [
9
+ {
10
+ "url": "/demo/neon",
11
+ "name": "Neon",
12
+ "path": "src/routes/demo.neon.tsx",
13
+ "jsName": "NeonDemo"
14
+ }
15
+ ],
16
+ "dependsOn": ["start"]
17
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "dependencies": {
3
+ "@neondatabase/serverless": "^1.0.0"
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" width="256" height="256" preserveAspectRatio="xMidYMid"><defs><linearGradient id="a" x1="100%" x2="12.069%" y1="100%" y2="0%"><stop offset="0%" stop-color="#62F755"/><stop offset="100%" stop-color="#8FF986" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="100%" x2="40.603%" y1="100%" y2="76.897%"><stop offset="0%" stop-opacity=".9"/><stop offset="100%" stop-color="#1A1A1A" stop-opacity="0"/></linearGradient></defs><path fill="#00E0D9" d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"/><path fill="url(#a)" d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"/><path fill="url(#b)" fill-opacity=".4" d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"/><path fill="#63F655" d="M211.861 0C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723a4.409 4.409 0 0 0 4.409-4.409V115.058c0-25.223 31.914-36.167 47.395-16.256l48.391 62.243V8.825c0-4.871-3.953-8.825-8.832-8.825Z"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-framework-react-cra",
3
- "version": "0.10.0-alpha.21",
3
+ "version": "0.10.0-alpha.26",
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.10.0-alpha.21"
26
+ "@tanstack/cta-engine": "0.10.0-alpha.26"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^22.13.4",