create-next-imagicma 0.1.15 → 0.2.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.
Files changed (50) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/template-hono/.env.example +6 -14
  4. package/template-hono/.imagicma/AGENTS.md +7 -0
  5. package/template-hono/AGENTS.md +98 -128
  6. package/template-hono/README.md +86 -118
  7. package/template-hono/client/index.html +1 -1
  8. package/template-hono/client/public/imagicma-picker-bridge.js +2 -6
  9. package/template-hono/client/public/imagicma-preview-feedback.js +0 -1
  10. package/template-hono/client/src/components/HelloClient.tsx +1 -1
  11. package/template-hono/client/src/globals.css +417 -1
  12. package/template-hono/client/src/lib/imagicma-preview-bridge.ts +1 -1
  13. package/template-hono/client/src/lib/imagicma-preview-picker.ts +28 -130
  14. package/template-hono/client/src/providers.tsx +1 -1
  15. package/template-hono/gitignore +2 -1
  16. package/template-hono/package.json +9 -9
  17. package/template-hono/pnpm-lock.yaml +646 -1173
  18. package/template-hono/server/app.ts +3 -2
  19. package/template-hono/server/controllers/greeting.controller.ts +22 -0
  20. package/template-hono/server/db/index.ts +129 -0
  21. package/template-hono/server/index.ts +3 -3
  22. package/template-hono/server/middlewares/error-handler.ts +8 -0
  23. package/template-hono/server/models/entities/message.entity.ts +13 -0
  24. package/template-hono/server/models/repositories/message.repository.ts +43 -0
  25. package/template-hono/server/models/services/greeting.service.ts +14 -0
  26. package/template-hono/server/models/types/message.ts +7 -0
  27. package/template-hono/server/routes/greeting.ts +1 -1
  28. package/template-hono/shared/constants/greeting.ts +1 -0
  29. package/template-hono/shared/contracts/routes.ts +14 -0
  30. package/template-hono/shared/routes.ts +1 -68
  31. package/template-hono/shared/schema.ts +5 -8
  32. package/template-hono/shared/types/greeting.ts +3 -0
  33. package/template-hono/tailwind.config.mjs +62 -111
  34. package/template-hono/tsconfig.json +3 -2
  35. package/template-hono/tsconfig.server.json +2 -0
  36. package/template-hono/vite.config.ts +4 -4
  37. package/template-hono/client/src/lib/ai-ui-stream.ts +0 -64
  38. package/template-hono/client/src/theme/default-theme.css +0 -482
  39. package/template-hono/drizzle.config.ts +0 -13
  40. package/template-hono/server/controllers/ai-chat-controller.ts +0 -49
  41. package/template-hono/server/controllers/greeting-controller.ts +0 -25
  42. package/template-hono/server/db/client.ts +0 -25
  43. package/template-hono/server/env.ts +0 -89
  44. package/template-hono/server/lib/ai-provider.ts +0 -74
  45. package/template-hono/server/lib/ai.ts +0 -205
  46. package/template-hono/server/middlewares/auth.ts +0 -69
  47. package/template-hono/server/middlewares/index.ts +0 -12
  48. package/template-hono/server/repositories/message-repository.ts +0 -13
  49. package/template-hono/server/routes/ai-chat.ts +0 -9
  50. package/template-hono/shared/schema/greeting.ts +0 -17
@@ -1,64 +0,0 @@
1
- export type AiUiStreamPart =
2
- | { type: "start" | "start-step" | "finish-step" | "finish"; [key: string]: unknown }
3
- | { type: "text-start"; id?: string; [key: string]: unknown }
4
- | { type: "text-delta"; id?: string; delta: string; [key: string]: unknown }
5
- | { type: "text-end"; id?: string; [key: string]: unknown }
6
- | { type: "error"; errorText?: string; [key: string]: unknown };
7
-
8
- export async function readAiUiMessageStream(
9
- stream: ReadableStream<Uint8Array>,
10
- options?: {
11
- onPart?: (part: AiUiStreamPart) => void;
12
- onTextDelta?: (delta: string, fullText: string) => void;
13
- },
14
- ) {
15
- const reader = stream.getReader();
16
- const decoder = new TextDecoder();
17
- let buffer = "";
18
- let text = "";
19
-
20
- const consumeEvent = (eventText: string) => {
21
- const dataLines = eventText
22
- .split("\n")
23
- .map((line) => line.trim())
24
- .filter((line) => line.startsWith("data:"))
25
- .map((line) => line.slice(5).trim());
26
-
27
- if (dataLines.length === 0) return;
28
-
29
- const payload = dataLines.join("\n");
30
- if (!payload || payload === "[DONE]") return;
31
-
32
- const part = JSON.parse(payload) as AiUiStreamPart;
33
- options?.onPart?.(part);
34
-
35
- if (part.type === "error") {
36
- throw new Error(part.errorText || "AI stream failed");
37
- }
38
-
39
- if (part.type === "text-delta") {
40
- text += part.delta;
41
- options?.onTextDelta?.(part.delta, text);
42
- }
43
- };
44
-
45
- while (true) {
46
- const { value, done } = await reader.read();
47
- if (value) {
48
- buffer += decoder.decode(value, { stream: true });
49
- const events = buffer.split("\n\n");
50
- buffer = events.pop() ?? "";
51
- for (const eventText of events) {
52
- consumeEvent(eventText);
53
- }
54
- }
55
-
56
- if (done) break;
57
- }
58
-
59
- if (buffer.trim()) {
60
- consumeEvent(buffer);
61
- }
62
-
63
- return text;
64
- }
@@ -1,482 +0,0 @@
1
- :root {
2
- /* Fonts */
3
- --font-sans: "Poppins", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
4
- "Noto Sans SC", "Helvetica Neue", sans-serif;
5
- --font-display: "Poppins", "PingFang SC", "Hiragino Sans GB",
6
- "Microsoft YaHei", sans-serif;
7
- --font-serif: "Poppins", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
8
- "Noto Sans SC", "Helvetica Neue", sans-serif;
9
- --font-mono: Menlo, ui-monospace, SFMono-Regular, Monaco, Consolas,
10
- "Liberation Mono", "Courier New", monospace;
11
-
12
- /* Shape defaults */
13
- --radius: 1rem;
14
- --radius-lg-token: 2rem;
15
- --radius-xl-token: 3rem;
16
- --radius-full-token: 9999px;
17
-
18
- /* Design tokens */
19
- --background-base: 200 69.2% 97.5%;
20
- --on-background: 193.3 17% 10.4%;
21
- --surface: 200 69.2% 97.5%;
22
- --surface-bright: 200 69.2% 97.5%;
23
- --surface-dim: 193.3 11.7% 84.9%;
24
- --surface-container-lowest: 0 0% 100%;
25
- --surface-container-low: 193.3 36% 95.1%;
26
- --surface-container: 193.3 24.3% 92.7%;
27
- --surface-container-high: 198 20.8% 90.6%;
28
- --surface-container-highest: 193.3 15.3% 88.4%;
29
- --surface-variant: 193.3 15.3% 88.4%;
30
- --surface-tint: 167.7 100% 21%;
31
- --on-surface: 193.3 17% 10.4%;
32
- --on-surface-variant: 154.3 10.4% 26.3%;
33
-
34
- --primary: 167.7 100% 21%;
35
- --on-primary: 0 0% 100%;
36
- --primary-container: 168.3 100% 36.1%;
37
- --on-primary-container: 166.4 100% 12.9%;
38
- --primary-fixed: 163 93.4% 70.4%;
39
- --primary-fixed-dim: 164.4 68.2% 58%;
40
- --on-primary-fixed: 165 100% 6.3%;
41
- --on-primary-fixed-variant: 167.4 100% 15.9%;
42
- --inverse-primary: 164.4 68.2% 58%;
43
-
44
- --secondary: 358.4 51.4% 43.5%;
45
- --on-secondary: 0 0% 100%;
46
- --secondary-container: 0.4 100% 72.9%;
47
- --on-secondary-container: 353.6 82.4% 24.5%;
48
- --secondary-fixed: 3.1 100% 92.4%;
49
- --secondary-fixed-dim: 2.3 100% 84.5%;
50
- --on-secondary-fixed: 354.5 100% 12.7%;
51
- --on-secondary-fixed-variant: 356.1 64.8% 32.4%;
52
-
53
- --tertiary: 244.5 36.8% 50.4%;
54
- --on-tertiary: 0 0% 100%;
55
- --tertiary-container: 244.2 90.8% 78.6%;
56
- --on-tertiary-container: 246.4 53.4% 34.5%;
57
- --tertiary-fixed: 247.5 100% 93.7%;
58
- --tertiary-fixed-dim: 244.8 100% 87.6%;
59
- --on-tertiary-fixed: 251.7 100% 20.2%;
60
- --on-tertiary-fixed-variant: 245.2 44.9% 40.6%;
61
-
62
- --error: 0 75.5% 41.6%;
63
- --on-error: 0 0% 100%;
64
- --error-container: 5.9 100% 92%;
65
- --on-error-container: 355.9 100% 28.8%;
66
-
67
- --outline: 154.3 6.1% 45.1%;
68
- --outline-variant: 152 12.4% 76.3%;
69
- --inverse-surface: 193.3 9.5% 18.6%;
70
- --inverse-on-surface: 193.3 29% 93.9%;
71
-
72
- /* Semantic aliases consumed by the current app */
73
- --background: var(--background-base);
74
- --foreground: var(--on-background);
75
-
76
- --card: var(--surface-container-lowest);
77
- --card-foreground: var(--on-surface);
78
-
79
- --popover: var(--surface-container-low);
80
- --popover-foreground: var(--on-surface);
81
-
82
- --primary-foreground: var(--on-primary);
83
- --secondary-foreground: var(--on-secondary);
84
-
85
- --muted: var(--surface-container);
86
- --muted-foreground: var(--on-surface-variant);
87
-
88
- --accent: var(--secondary-container);
89
- --accent-foreground: var(--on-secondary-container);
90
-
91
- --destructive: var(--error);
92
- --destructive-foreground: var(--on-error);
93
-
94
- --border: var(--outline-variant);
95
- --input: var(--surface-variant);
96
- --ring: var(--primary);
97
-
98
- /* Visual system tokens for showcase pages */
99
- --surface-1: var(--surface-container-lowest);
100
- --surface-2: var(--surface-container-low);
101
- --brand-accent: var(--tertiary-container);
102
- --brand-success: var(--primary-container);
103
- --elevation-soft: 0 14px 34px rgba(15, 23, 42, 0.12);
104
- --elevation-strong: 0 22px 56px rgba(15, 23, 42, 0.18);
105
- --space-xs: 0.625rem;
106
- --space-sm: 0.875rem;
107
- --space-md: 1.125rem;
108
- --space-lg: 1.625rem;
109
-
110
- /* Extra tokens used by the migrated shadcn components */
111
- --card-border: var(--outline-variant);
112
- --popover-border: var(--outline-variant);
113
- --sidebar: var(--surface-container-low);
114
- --sidebar-foreground: var(--on-surface);
115
- --sidebar-border: var(--outline-variant);
116
- --sidebar-ring: var(--primary);
117
- --sidebar-accent: var(--secondary-container);
118
- --sidebar-accent-foreground: var(--on-secondary-container);
119
-
120
- --chart-1: var(--primary);
121
- --chart-2: var(--secondary);
122
- --chart-3: var(--tertiary);
123
- --chart-4: var(--primary-container);
124
- --chart-5: var(--error);
125
-
126
- /* Border colors expected by template classnames */
127
- --primary-border: hsl(var(--primary) / 0.18);
128
- --secondary-border: hsl(var(--outline-variant));
129
- --muted-border: hsl(var(--outline-variant));
130
- --accent-border: hsl(var(--secondary-container) / 0.4);
131
- --destructive-border: hsl(var(--error) / 0.25);
132
-
133
- --button-outline: hsl(var(--outline-variant));
134
- --badge-outline: hsl(var(--outline-variant));
135
- }
136
-
137
- .dark {
138
- /* Design tokens */
139
- --background-base: 193.3 9.5% 18.6%;
140
- --on-background: 193.3 29% 93.9%;
141
- --surface: 193.3 9.5% 18.6%;
142
- --surface-bright: 193.3 8.5% 24%;
143
- --surface-dim: 193.3 10% 12%;
144
- --surface-container-lowest: 193.3 11% 8%;
145
- --surface-container-low: 193.3 10% 12%;
146
- --surface-container: 193.3 10% 16%;
147
- --surface-container-high: 193.3 10% 20%;
148
- --surface-container-highest: 193.3 10.4% 26.3%;
149
- --surface-variant: 154.3 10.4% 26.3%;
150
- --surface-tint: 164.4 68.2% 58%;
151
- --on-surface: 193.3 29% 93.9%;
152
- --on-surface-variant: 152 12.4% 76.3%;
153
-
154
- --primary: 164.4 68.2% 58%;
155
- --on-primary: 165 100% 6.3%;
156
- --primary-container: 167.4 100% 15.9%;
157
- --on-primary-container: 163 93.4% 70.4%;
158
- --primary-fixed: 163 93.4% 70.4%;
159
- --primary-fixed-dim: 164.4 68.2% 58%;
160
- --on-primary-fixed: 165 100% 6.3%;
161
- --on-primary-fixed-variant: 167.4 100% 15.9%;
162
- --inverse-primary: 167.7 100% 21%;
163
-
164
- --secondary: 2.3 100% 84.5%;
165
- --on-secondary: 354.5 100% 12.7%;
166
- --secondary-container: 356.1 64.8% 32.4%;
167
- --on-secondary-container: 3.1 100% 92.4%;
168
- --secondary-fixed: 3.1 100% 92.4%;
169
- --secondary-fixed-dim: 2.3 100% 84.5%;
170
- --on-secondary-fixed: 354.5 100% 12.7%;
171
- --on-secondary-fixed-variant: 356.1 64.8% 32.4%;
172
-
173
- --tertiary: 244.8 100% 87.6%;
174
- --on-tertiary: 251.7 100% 20.2%;
175
- --tertiary-container: 245.2 44.9% 40.6%;
176
- --on-tertiary-container: 247.5 100% 93.7%;
177
- --tertiary-fixed: 247.5 100% 93.7%;
178
- --tertiary-fixed-dim: 244.8 100% 87.6%;
179
- --on-tertiary-fixed: 251.7 100% 20.2%;
180
- --on-tertiary-fixed-variant: 245.2 44.9% 40.6%;
181
-
182
- --error: 0 62.8% 30.6%;
183
- --on-error: 0 0% 98%;
184
- --error-container: 355.9 100% 28.8%;
185
- --on-error-container: 5.9 100% 92%;
186
-
187
- --outline: 152 12.4% 60%;
188
- --outline-variant: 154.3 10.4% 26.3%;
189
- --inverse-surface: 200 69.2% 97.5%;
190
- --inverse-on-surface: 193.3 17% 10.4%;
191
-
192
- /* Semantic aliases consumed by the current app */
193
- --background: var(--background-base);
194
- --foreground: var(--on-background);
195
-
196
- --card: var(--surface-container-low);
197
- --card-foreground: var(--on-surface);
198
-
199
- --popover: var(--surface-container);
200
- --popover-foreground: var(--on-surface);
201
-
202
- --primary-foreground: var(--on-primary);
203
- --secondary-foreground: var(--on-secondary);
204
-
205
- --muted: var(--surface-container-high);
206
- --muted-foreground: var(--on-surface-variant);
207
-
208
- --accent: var(--secondary-container);
209
- --accent-foreground: var(--on-secondary-container);
210
-
211
- --destructive: var(--error);
212
- --destructive-foreground: var(--on-error);
213
-
214
- --border: var(--outline-variant);
215
- --input: var(--surface-container-high);
216
- --ring: var(--primary);
217
-
218
- /* Visual system tokens for showcase pages */
219
- --surface-1: var(--surface-container-low);
220
- --surface-2: var(--surface-container);
221
- --brand-accent: var(--tertiary-fixed-dim);
222
- --brand-success: var(--primary-fixed-dim);
223
-
224
- /* Extra tokens used by the migrated shadcn components */
225
- --card-border: var(--outline-variant);
226
- --popover-border: var(--outline-variant);
227
- --sidebar: var(--surface-container-low);
228
- --sidebar-foreground: var(--on-surface);
229
- --sidebar-border: var(--outline-variant);
230
- --sidebar-ring: var(--primary);
231
- --sidebar-accent: var(--secondary-container);
232
- --sidebar-accent-foreground: var(--on-secondary-container);
233
-
234
- --chart-1: var(--primary-fixed-dim);
235
- --chart-2: var(--secondary-fixed-dim);
236
- --chart-3: var(--tertiary-fixed-dim);
237
- --chart-4: var(--primary-fixed);
238
- --chart-5: var(--error-container);
239
-
240
- /* Border colors expected by template classnames */
241
- --primary-border: hsl(var(--primary) / 0.15);
242
- --secondary-border: hsl(var(--outline-variant));
243
- --muted-border: hsl(var(--outline-variant));
244
- --accent-border: hsl(var(--secondary-fixed-dim) / 0.35);
245
- --destructive-border: hsl(var(--error-container) / 0.35);
246
-
247
- --button-outline: hsl(var(--outline-variant));
248
- --badge-outline: hsl(var(--outline-variant));
249
- }
250
-
251
- /* Theme style presets (used by html[data-theme-style="<preset>"]) */
252
- :root[data-theme-style="quadratic"] {
253
- --background: 246 33% 96%;
254
- --foreground: 233 24% 17%;
255
-
256
- --card: 0 0% 100%;
257
- --card-foreground: 233 24% 17%;
258
- --popover: 0 0% 100%;
259
- --popover-foreground: 233 24% 17%;
260
-
261
- --primary: 258 84% 63%;
262
- --primary-foreground: 0 0% 100%;
263
- --secondary: 250 44% 92%;
264
- --secondary-foreground: 233 24% 20%;
265
- --muted: 246 36% 93%;
266
- --muted-foreground: 230 12% 42%;
267
- --accent: 257 62% 88%;
268
- --accent-foreground: 234 24% 24%;
269
-
270
- --border: 246 24% 86%;
271
- --input: 246 24% 84%;
272
- --ring: 258 84% 63%;
273
-
274
- --chart-1: 258 78% 56%;
275
- --chart-2: 201 84% 56%;
276
- --chart-3: 172 65% 45%;
277
- --chart-4: 338 74% 58%;
278
- --chart-5: 39 84% 58%;
279
- }
280
-
281
- .dark[data-theme-style="quadratic"] {
282
- --background: 233 22% 11%;
283
- --foreground: 246 33% 96%;
284
-
285
- --card: 232 20% 14%;
286
- --card-foreground: 246 33% 96%;
287
- --popover: 232 20% 14%;
288
- --popover-foreground: 246 33% 96%;
289
-
290
- --primary: 258 90% 70%;
291
- --primary-foreground: 233 22% 11%;
292
- --secondary: 235 16% 20%;
293
- --secondary-foreground: 246 30% 94%;
294
- --muted: 234 14% 18%;
295
- --muted-foreground: 240 15% 76%;
296
- --accent: 235 16% 20%;
297
- --accent-foreground: 246 30% 94%;
298
-
299
- --border: 234 14% 26%;
300
- --input: 234 14% 26%;
301
- --ring: 258 90% 70%;
302
-
303
- --chart-1: 258 90% 70%;
304
- --chart-2: 201 78% 68%;
305
- --chart-3: 172 58% 62%;
306
- --chart-4: 338 76% 72%;
307
- --chart-5: 39 78% 70%;
308
- }
309
-
310
- :root[data-theme-style="honey"] {
311
- --background: 49 38.1% 91.8%;
312
- --foreground: 40 52.9% 27.5%;
313
-
314
- --card: 49 42% 95%;
315
- --card-foreground: 40 52.9% 27.5%;
316
- --popover: 49 42% 95%;
317
- --popover-foreground: 40 52.9% 27.5%;
318
-
319
- --primary: 40 72.8% 68.2%;
320
- --primary-foreground: 40 52.9% 18%;
321
- --secondary: 63 20.8% 79.2%;
322
- --secondary-foreground: 40 52.9% 27.5%;
323
- --muted: 49 30% 88%;
324
- --muted-foreground: 40 24% 38%;
325
- --accent: 63 20.8% 79.2%;
326
- --accent-foreground: 40 52.9% 27.5%;
327
-
328
- --border: 52 22% 74%;
329
- --input: 52 22% 74%;
330
- --ring: 40 72.8% 68.2%;
331
-
332
- --chart-1: 40 72.8% 55%;
333
- --chart-2: 63 30% 45%;
334
- --chart-3: 173 25% 42%;
335
- --chart-4: 18 56% 50%;
336
- --chart-5: 240 16% 52%;
337
- }
338
-
339
- .dark[data-theme-style="honey"] {
340
- --background: 36 38% 10%;
341
- --foreground: 49 30% 88%;
342
-
343
- --card: 34 30% 14%;
344
- --card-foreground: 49 30% 88%;
345
- --popover: 34 30% 14%;
346
- --popover-foreground: 49 30% 88%;
347
-
348
- --primary: 40 72.8% 68.2%;
349
- --primary-foreground: 36 38% 10%;
350
- --secondary: 38 20% 20%;
351
- --secondary-foreground: 49 30% 88%;
352
- --muted: 38 18% 18%;
353
- --muted-foreground: 49 18% 70%;
354
- --accent: 38 18% 18%;
355
- --accent-foreground: 49 30% 88%;
356
-
357
- --border: 38 18% 26%;
358
- --input: 38 18% 26%;
359
- --ring: 40 72.8% 68.2%;
360
-
361
- --chart-1: 40 72.8% 68.2%;
362
- --chart-2: 63 35% 58%;
363
- --chart-3: 173 30% 56%;
364
- --chart-4: 20 56% 64%;
365
- --chart-5: 240 22% 70%;
366
- }
367
-
368
- :root[data-theme-style="zen-garden"] {
369
- --background: 84 9.8% 90%;
370
- --foreground: 225 18.2% 8.6%;
371
-
372
- --card: 84 12% 94%;
373
- --card-foreground: 225 18.2% 8.6%;
374
- --popover: 84 12% 94%;
375
- --popover-foreground: 225 18.2% 8.6%;
376
-
377
- --primary: 173 24.7% 62%;
378
- --primary-foreground: 225 18.2% 8.6%;
379
- --secondary: 289 32.9% 72%;
380
- --secondary-foreground: 225 18.2% 8.6%;
381
- --muted: 84 10% 86%;
382
- --muted-foreground: 225 10% 36%;
383
- --accent: 289 32.9% 72%;
384
- --accent-foreground: 225 18.2% 8.6%;
385
-
386
- --border: 84 8% 78%;
387
- --input: 84 8% 78%;
388
- --ring: 173 24.7% 62%;
389
-
390
- --chart-1: 173 24.7% 48%;
391
- --chart-2: 289 32.9% 58%;
392
- --chart-3: 40 68% 56%;
393
- --chart-4: 220 26% 50%;
394
- --chart-5: 0 55% 58%;
395
- }
396
-
397
- .dark[data-theme-style="zen-garden"] {
398
- --background: 225 18.2% 8.6%;
399
- --foreground: 84 9.8% 90%;
400
-
401
- --card: 225 16% 12%;
402
- --card-foreground: 84 9.8% 90%;
403
- --popover: 225 16% 12%;
404
- --popover-foreground: 84 9.8% 90%;
405
-
406
- --primary: 173 30% 66%;
407
- --primary-foreground: 225 18.2% 8.6%;
408
- --secondary: 225 12% 18%;
409
- --secondary-foreground: 84 9.8% 90%;
410
- --muted: 225 10% 15%;
411
- --muted-foreground: 84 8% 72%;
412
- --accent: 225 10% 15%;
413
- --accent-foreground: 84 9.8% 90%;
414
-
415
- --border: 225 10% 24%;
416
- --input: 225 10% 24%;
417
- --ring: 173 30% 66%;
418
-
419
- --chart-1: 173 30% 66%;
420
- --chart-2: 289 36% 70%;
421
- --chart-3: 40 68% 64%;
422
- --chart-4: 220 30% 70%;
423
- --chart-5: 355 65% 68%;
424
- }
425
-
426
- :root[data-theme-style="highlighter"] {
427
- --background: 228 23.8% 95.9%;
428
- --foreground: 223 18.9% 7.3%;
429
-
430
- --card: 228 24% 98%;
431
- --card-foreground: 223 18.9% 7.3%;
432
- --popover: 228 24% 98%;
433
- --popover-foreground: 223 18.9% 7.3%;
434
-
435
- --primary: 97 70.5% 64.1%;
436
- --primary-foreground: 223 18.9% 7.3%;
437
- --secondary: 249 35.6% 88.4%;
438
- --secondary-foreground: 223 18.9% 7.3%;
439
- --muted: 228 20% 92%;
440
- --muted-foreground: 223 10% 35%;
441
- --accent: 249 35.6% 88.4%;
442
- --accent-foreground: 223 18.9% 7.3%;
443
-
444
- --border: 238 20% 84%;
445
- --input: 238 20% 84%;
446
- --ring: 97 70.5% 64.1%;
447
-
448
- --chart-1: 97 70.5% 48%;
449
- --chart-2: 249 45% 56%;
450
- --chart-3: 202 72% 54%;
451
- --chart-4: 339 78% 58%;
452
- --chart-5: 40 78% 58%;
453
- }
454
-
455
- .dark[data-theme-style="highlighter"] {
456
- --background: 223 18.9% 7.3%;
457
- --foreground: 228 23.8% 95.9%;
458
-
459
- --card: 223 16% 11%;
460
- --card-foreground: 228 23.8% 95.9%;
461
- --popover: 223 16% 11%;
462
- --popover-foreground: 228 23.8% 95.9%;
463
-
464
- --primary: 97 74% 66%;
465
- --primary-foreground: 223 18.9% 7.3%;
466
- --secondary: 223 12% 18%;
467
- --secondary-foreground: 228 23.8% 95.9%;
468
- --muted: 223 10% 15%;
469
- --muted-foreground: 228 14% 72%;
470
- --accent: 223 10% 15%;
471
- --accent-foreground: 228 23.8% 95.9%;
472
-
473
- --border: 223 10% 24%;
474
- --input: 223 10% 24%;
475
- --ring: 97 74% 66%;
476
-
477
- --chart-1: 97 74% 66%;
478
- --chart-2: 249 50% 72%;
479
- --chart-3: 202 78% 70%;
480
- --chart-4: 339 80% 70%;
481
- --chart-5: 40 78% 68%;
482
- }
@@ -1,13 +0,0 @@
1
- import { defineConfig } from "drizzle-kit";
2
- import { requireDatabaseUrl } from "./server/env";
3
-
4
- const databaseUrl = requireDatabaseUrl();
5
-
6
- export default defineConfig({
7
- out: "./migrations",
8
- schema: "./shared/schema.ts",
9
- dialect: "postgresql",
10
- dbCredentials: {
11
- url: databaseUrl,
12
- },
13
- });
@@ -1,49 +0,0 @@
1
- import type { Context } from "hono";
2
- import { ZodError } from "zod";
3
- import { api } from "../../shared/routes";
4
- import { createAiErrorBody, AiGatewayError, streamAiChat } from "../lib/ai";
5
-
6
- export async function postAiChat(c: Context) {
7
- try {
8
- const payload = await c.req.json();
9
- const body = api.ai.chat.post.request.body.parse(payload);
10
-
11
- return streamAiChat(body.messages, c.req.raw.signal);
12
- } catch (error) {
13
- if (error instanceof SyntaxError) {
14
- return c.json(
15
- createAiErrorBody("AI_INVALID_JSON", "请求体必须是合法 JSON。"),
16
- 400,
17
- );
18
- }
19
-
20
- if (error instanceof ZodError) {
21
- return c.json(
22
- createAiErrorBody(
23
- "AI_INVALID_REQUEST",
24
- "AI 请求体不符合约定,请检查 messages 与 parts 结构。",
25
- ),
26
- 400,
27
- );
28
- }
29
-
30
- if (error instanceof AiGatewayError) {
31
- const status = error.status === 400 ? 400 : 500;
32
-
33
- return c.json(
34
- createAiErrorBody(error.code, error.message),
35
- status,
36
- );
37
- }
38
-
39
- console.error("POST /api/ai/chat failed:", error);
40
-
41
- return c.json(
42
- createAiErrorBody(
43
- "AI_GATEWAY_ERROR",
44
- "AI 网关请求失败,请稍后重试。",
45
- ),
46
- 500,
47
- );
48
- }
49
- }
@@ -1,25 +0,0 @@
1
- import type { Context } from "hono";
2
- import { api } from "../../shared/routes";
3
- import { findLatestMessage } from "../repositories/message-repository";
4
-
5
- const DEFAULT_GREETING_MESSAGE = "Hello from the Backend API!";
6
-
7
- export async function getGreeting(c: Context) {
8
- try {
9
- const message = (await findLatestMessage()) ?? DEFAULT_GREETING_MESSAGE;
10
- const body = { message };
11
-
12
- api.greeting.get.responses[200].parse(body);
13
-
14
- return c.json(body);
15
- } catch (error) {
16
- console.error("GET /api/greeting failed:", error);
17
-
18
- const message =
19
- error instanceof Error
20
- ? "数据库读取失败:请确认 .env.local 中的 DATABASE_URL 可用,并执行 `pnpm db:push` 初始化 PostgreSQL 数据库。"
21
- : "Internal Server Error";
22
-
23
- return c.json({ message }, 500);
24
- }
25
- }
@@ -1,25 +0,0 @@
1
- import { drizzle } from "drizzle-orm/node-postgres";
2
- import pg from "pg";
3
- import * as schema from "../../shared/schema";
4
- import { requireDatabaseUrl } from "../env";
5
-
6
- const { Pool } = pg;
7
- const databaseUrl = requireDatabaseUrl();
8
- type DatabasePool = InstanceType<typeof Pool>;
9
-
10
- declare global {
11
- var __dbPool: DatabasePool | undefined;
12
- }
13
-
14
- const pool =
15
- globalThis.__dbPool ??
16
- new Pool({
17
- connectionString: databaseUrl,
18
- });
19
-
20
- if (process.env.NODE_ENV !== "production") {
21
- globalThis.__dbPool = pool;
22
- }
23
-
24
- export const db = drizzle(pool, { schema });
25
- export { databaseUrl, pool };