create-next-imagicma 0.1.13 → 0.1.15
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/package.json +1 -1
- package/template-hono/.env.example +16 -3
- package/template-hono/AGENTS.md +91 -16
- package/template-hono/README.md +89 -3
- package/template-hono/client/src/components/HelloClient.tsx +1 -1
- package/template-hono/client/src/globals.css +1 -417
- package/template-hono/client/src/lib/ai-ui-stream.ts +64 -0
- package/template-hono/client/src/providers.tsx +1 -1
- package/template-hono/client/src/theme/default-theme.css +482 -0
- package/template-hono/drizzle.config.ts +3 -36
- package/template-hono/package.json +5 -1
- package/template-hono/pnpm-lock.yaml +186 -54
- package/template-hono/server/app.ts +2 -0
- package/template-hono/server/controllers/ai-chat-controller.ts +49 -0
- package/template-hono/server/controllers/greeting-controller.ts +25 -0
- package/template-hono/server/db/client.ts +25 -0
- package/template-hono/server/env.ts +89 -0
- package/template-hono/server/index.ts +1 -1
- package/template-hono/server/lib/ai-provider.ts +74 -0
- package/template-hono/server/lib/ai.ts +205 -0
- package/template-hono/server/middlewares/auth.ts +69 -0
- package/template-hono/server/middlewares/index.ts +12 -0
- package/template-hono/server/repositories/message-repository.ts +13 -0
- package/template-hono/server/routes/ai-chat.ts +9 -0
- package/template-hono/server/routes/greeting.ts +2 -18
- package/template-hono/shared/routes.ts +55 -0
- package/template-hono/shared/schema/greeting.ts +17 -0
- package/template-hono/shared/schema.ts +8 -16
- package/template-hono/tailwind.config.mjs +111 -62
- package/template-hono/vite.config.ts +1 -1
- package/template-hono/server/database-path.ts +0 -35
- package/template-hono/server/db.ts +0 -20
- package/template-hono/server/storage.ts +0 -30
|
@@ -1,5 +1,114 @@
|
|
|
1
1
|
import animate from "tailwindcss-animate";
|
|
2
2
|
|
|
3
|
+
const withAlpha = (name) => `hsl(var(--${name}) / <alpha-value>)`;
|
|
4
|
+
|
|
5
|
+
const themeBorderRadius = {
|
|
6
|
+
lg: "var(--radius)",
|
|
7
|
+
md: "calc(var(--radius) - 0.125rem)",
|
|
8
|
+
sm: "calc(var(--radius) - 0.25rem)",
|
|
9
|
+
full: "var(--radius-full-token)",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const themeColors = {
|
|
13
|
+
background: withAlpha("background"),
|
|
14
|
+
foreground: withAlpha("foreground"),
|
|
15
|
+
border: withAlpha("border"),
|
|
16
|
+
input: withAlpha("input"),
|
|
17
|
+
ring: withAlpha("ring"),
|
|
18
|
+
|
|
19
|
+
card: withAlpha("card"),
|
|
20
|
+
"card-foreground": withAlpha("card-foreground"),
|
|
21
|
+
"card-border": withAlpha("card-border"),
|
|
22
|
+
|
|
23
|
+
popover: withAlpha("popover"),
|
|
24
|
+
"popover-foreground": withAlpha("popover-foreground"),
|
|
25
|
+
"popover-border": withAlpha("popover-border"),
|
|
26
|
+
|
|
27
|
+
primary: withAlpha("primary"),
|
|
28
|
+
"primary-foreground": withAlpha("primary-foreground"),
|
|
29
|
+
"primary-border": "var(--primary-border)",
|
|
30
|
+
|
|
31
|
+
secondary: withAlpha("secondary"),
|
|
32
|
+
"secondary-foreground": withAlpha("secondary-foreground"),
|
|
33
|
+
"secondary-border": "var(--secondary-border)",
|
|
34
|
+
|
|
35
|
+
muted: withAlpha("muted"),
|
|
36
|
+
"muted-foreground": withAlpha("muted-foreground"),
|
|
37
|
+
"muted-border": "var(--muted-border)",
|
|
38
|
+
|
|
39
|
+
accent: withAlpha("accent"),
|
|
40
|
+
"accent-foreground": withAlpha("accent-foreground"),
|
|
41
|
+
"accent-border": "var(--accent-border)",
|
|
42
|
+
|
|
43
|
+
destructive: withAlpha("destructive"),
|
|
44
|
+
"destructive-foreground": withAlpha("destructive-foreground"),
|
|
45
|
+
"destructive-border": "var(--destructive-border)",
|
|
46
|
+
|
|
47
|
+
sidebar: withAlpha("sidebar"),
|
|
48
|
+
"sidebar-foreground": withAlpha("sidebar-foreground"),
|
|
49
|
+
"sidebar-border": withAlpha("sidebar-border"),
|
|
50
|
+
"sidebar-ring": withAlpha("sidebar-ring"),
|
|
51
|
+
"sidebar-accent": withAlpha("sidebar-accent"),
|
|
52
|
+
"sidebar-accent-foreground": withAlpha("sidebar-accent-foreground"),
|
|
53
|
+
|
|
54
|
+
"chart-1": withAlpha("chart-1"),
|
|
55
|
+
"chart-2": withAlpha("chart-2"),
|
|
56
|
+
"chart-3": withAlpha("chart-3"),
|
|
57
|
+
"chart-4": withAlpha("chart-4"),
|
|
58
|
+
"chart-5": withAlpha("chart-5"),
|
|
59
|
+
|
|
60
|
+
"background-base": withAlpha("background-base"),
|
|
61
|
+
"on-background": withAlpha("on-background"),
|
|
62
|
+
surface: withAlpha("surface"),
|
|
63
|
+
"surface-bright": withAlpha("surface-bright"),
|
|
64
|
+
"surface-dim": withAlpha("surface-dim"),
|
|
65
|
+
"surface-container-lowest": withAlpha("surface-container-lowest"),
|
|
66
|
+
"surface-container-low": withAlpha("surface-container-low"),
|
|
67
|
+
"surface-container": withAlpha("surface-container"),
|
|
68
|
+
"surface-container-high": withAlpha("surface-container-high"),
|
|
69
|
+
"surface-container-highest": withAlpha("surface-container-highest"),
|
|
70
|
+
"surface-variant": withAlpha("surface-variant"),
|
|
71
|
+
"surface-tint": withAlpha("surface-tint"),
|
|
72
|
+
"on-surface": withAlpha("on-surface"),
|
|
73
|
+
"on-surface-variant": withAlpha("on-surface-variant"),
|
|
74
|
+
|
|
75
|
+
"primary-container": withAlpha("primary-container"),
|
|
76
|
+
"on-primary": withAlpha("on-primary"),
|
|
77
|
+
"on-primary-container": withAlpha("on-primary-container"),
|
|
78
|
+
"primary-fixed": withAlpha("primary-fixed"),
|
|
79
|
+
"primary-fixed-dim": withAlpha("primary-fixed-dim"),
|
|
80
|
+
"on-primary-fixed": withAlpha("on-primary-fixed"),
|
|
81
|
+
"on-primary-fixed-variant": withAlpha("on-primary-fixed-variant"),
|
|
82
|
+
"inverse-primary": withAlpha("inverse-primary"),
|
|
83
|
+
|
|
84
|
+
"secondary-container": withAlpha("secondary-container"),
|
|
85
|
+
"on-secondary": withAlpha("on-secondary"),
|
|
86
|
+
"on-secondary-container": withAlpha("on-secondary-container"),
|
|
87
|
+
"secondary-fixed": withAlpha("secondary-fixed"),
|
|
88
|
+
"secondary-fixed-dim": withAlpha("secondary-fixed-dim"),
|
|
89
|
+
"on-secondary-fixed": withAlpha("on-secondary-fixed"),
|
|
90
|
+
"on-secondary-fixed-variant": withAlpha("on-secondary-fixed-variant"),
|
|
91
|
+
|
|
92
|
+
tertiary: withAlpha("tertiary"),
|
|
93
|
+
"tertiary-container": withAlpha("tertiary-container"),
|
|
94
|
+
"on-tertiary": withAlpha("on-tertiary"),
|
|
95
|
+
"on-tertiary-container": withAlpha("on-tertiary-container"),
|
|
96
|
+
"tertiary-fixed": withAlpha("tertiary-fixed"),
|
|
97
|
+
"tertiary-fixed-dim": withAlpha("tertiary-fixed-dim"),
|
|
98
|
+
"on-tertiary-fixed": withAlpha("on-tertiary-fixed"),
|
|
99
|
+
"on-tertiary-fixed-variant": withAlpha("on-tertiary-fixed-variant"),
|
|
100
|
+
|
|
101
|
+
error: withAlpha("error"),
|
|
102
|
+
"on-error": withAlpha("on-error"),
|
|
103
|
+
"error-container": withAlpha("error-container"),
|
|
104
|
+
"on-error-container": withAlpha("on-error-container"),
|
|
105
|
+
|
|
106
|
+
outline: withAlpha("outline"),
|
|
107
|
+
"outline-variant": withAlpha("outline-variant"),
|
|
108
|
+
"inverse-surface": withAlpha("inverse-surface"),
|
|
109
|
+
"inverse-on-surface": withAlpha("inverse-on-surface"),
|
|
110
|
+
};
|
|
111
|
+
|
|
3
112
|
/** @type {import("tailwindcss").Config} */
|
|
4
113
|
const config = {
|
|
5
114
|
darkMode: ["class"],
|
|
@@ -10,68 +119,8 @@ const config = {
|
|
|
10
119
|
],
|
|
11
120
|
theme: {
|
|
12
121
|
extend: {
|
|
13
|
-
borderRadius:
|
|
14
|
-
|
|
15
|
-
md: "calc(var(--radius) - 2px)",
|
|
16
|
-
sm: "calc(var(--radius) - 4px)",
|
|
17
|
-
},
|
|
18
|
-
colors: {
|
|
19
|
-
background: "hsl(var(--background) / <alpha-value>)",
|
|
20
|
-
foreground: "hsl(var(--foreground) / <alpha-value>)",
|
|
21
|
-
border: "hsl(var(--border) / <alpha-value>)",
|
|
22
|
-
input: "hsl(var(--input) / <alpha-value>)",
|
|
23
|
-
ring: "hsl(var(--ring) / <alpha-value>)",
|
|
24
|
-
card: {
|
|
25
|
-
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
|
26
|
-
foreground: "hsl(var(--card-foreground) / <alpha-value>)",
|
|
27
|
-
border: "hsl(var(--card-border) / <alpha-value>)",
|
|
28
|
-
},
|
|
29
|
-
popover: {
|
|
30
|
-
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
|
|
31
|
-
foreground: "hsl(var(--popover-foreground) / <alpha-value>)",
|
|
32
|
-
border: "hsl(var(--popover-border) / <alpha-value>)",
|
|
33
|
-
},
|
|
34
|
-
primary: {
|
|
35
|
-
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
|
|
36
|
-
foreground: "hsl(var(--primary-foreground) / <alpha-value>)",
|
|
37
|
-
border: "var(--primary-border)",
|
|
38
|
-
},
|
|
39
|
-
secondary: {
|
|
40
|
-
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
|
|
41
|
-
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)",
|
|
42
|
-
border: "var(--secondary-border)",
|
|
43
|
-
},
|
|
44
|
-
muted: {
|
|
45
|
-
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
|
|
46
|
-
foreground: "hsl(var(--muted-foreground) / <alpha-value>)",
|
|
47
|
-
border: "var(--muted-border)",
|
|
48
|
-
},
|
|
49
|
-
accent: {
|
|
50
|
-
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
|
|
51
|
-
foreground: "hsl(var(--accent-foreground) / <alpha-value>)",
|
|
52
|
-
border: "var(--accent-border)",
|
|
53
|
-
},
|
|
54
|
-
destructive: {
|
|
55
|
-
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
|
|
56
|
-
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)",
|
|
57
|
-
border: "var(--destructive-border)",
|
|
58
|
-
},
|
|
59
|
-
chart: {
|
|
60
|
-
"1": "hsl(var(--chart-1) / <alpha-value>)",
|
|
61
|
-
"2": "hsl(var(--chart-2) / <alpha-value>)",
|
|
62
|
-
"3": "hsl(var(--chart-3) / <alpha-value>)",
|
|
63
|
-
"4": "hsl(var(--chart-4) / <alpha-value>)",
|
|
64
|
-
"5": "hsl(var(--chart-5) / <alpha-value>)",
|
|
65
|
-
},
|
|
66
|
-
sidebar: {
|
|
67
|
-
DEFAULT: "hsl(var(--sidebar) / <alpha-value>)",
|
|
68
|
-
foreground: "hsl(var(--sidebar-foreground) / <alpha-value>)",
|
|
69
|
-
border: "hsl(var(--sidebar-border) / <alpha-value>)",
|
|
70
|
-
ring: "hsl(var(--sidebar-ring) / <alpha-value>)",
|
|
71
|
-
accent: "hsl(var(--accent) / <alpha-value>)",
|
|
72
|
-
"accent-foreground": "hsl(var(--accent-foreground) / <alpha-value>)",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
122
|
+
borderRadius: themeBorderRadius,
|
|
123
|
+
colors: themeColors,
|
|
75
124
|
keyframes: {
|
|
76
125
|
"accordion-down": {
|
|
77
126
|
from: { height: "0" },
|
|
@@ -50,7 +50,7 @@ async function readRuntimeEnvPort() {
|
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
async function resolveRuntimePort(raw = process.env.PORT) {
|
|
53
|
+
async function resolveRuntimePort(raw: string | null | undefined = process.env.PORT) {
|
|
54
54
|
let candidate = raw;
|
|
55
55
|
if (candidate === undefined || candidate === null || candidate === "") {
|
|
56
56
|
candidate = await readRuntimeEnvPort();
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { pathToFileURL } from "node:url";
|
|
4
|
-
|
|
5
|
-
const DEFAULT_DATABASE_FILE = "./.data/app.db";
|
|
6
|
-
|
|
7
|
-
export function resolveDatabaseFilePath() {
|
|
8
|
-
const configuredPath = process.env.DATABASE_FILE?.trim();
|
|
9
|
-
const targetPath =
|
|
10
|
-
configuredPath && configuredPath.length > 0 ? configuredPath : DEFAULT_DATABASE_FILE;
|
|
11
|
-
|
|
12
|
-
return path.resolve(process.cwd(), targetPath);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function ensureDatabaseFilePath() {
|
|
16
|
-
const databaseFilePath = resolveDatabaseFilePath();
|
|
17
|
-
|
|
18
|
-
fs.mkdirSync(path.dirname(databaseFilePath), { recursive: true });
|
|
19
|
-
|
|
20
|
-
return databaseFilePath;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function resolveDatabaseUrl(databaseFilePath = resolveDatabaseFilePath()) {
|
|
24
|
-
return pathToFileURL(databaseFilePath).href;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function ensureDatabaseUrl() {
|
|
28
|
-
const databaseFilePath = ensureDatabaseFilePath();
|
|
29
|
-
|
|
30
|
-
return resolveDatabaseUrl(databaseFilePath);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function describeDatabaseFilePath(databaseFilePath = resolveDatabaseFilePath()) {
|
|
34
|
-
return path.relative(process.cwd(), databaseFilePath) || path.basename(databaseFilePath);
|
|
35
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { createClient } from "@libsql/client";
|
|
2
|
-
import { drizzle } from "drizzle-orm/libsql";
|
|
3
|
-
import * as schema from "../shared/schema";
|
|
4
|
-
import { ensureDatabaseUrl } from "./database-path";
|
|
5
|
-
|
|
6
|
-
const databaseUrl = ensureDatabaseUrl();
|
|
7
|
-
type DatabaseClient = ReturnType<typeof createClient>;
|
|
8
|
-
|
|
9
|
-
declare global {
|
|
10
|
-
var __dbClient: DatabaseClient | undefined;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const sqlite = globalThis.__dbClient ?? createClient({ url: databaseUrl });
|
|
14
|
-
|
|
15
|
-
if (process.env.NODE_ENV !== "production") {
|
|
16
|
-
globalThis.__dbClient = sqlite;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const db = drizzle(sqlite, { schema });
|
|
20
|
-
export { databaseUrl };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { desc } from "drizzle-orm";
|
|
2
|
-
import { messages } from "../shared/schema";
|
|
3
|
-
import { describeDatabaseFilePath } from "./database-path";
|
|
4
|
-
import { db } from "./db";
|
|
5
|
-
|
|
6
|
-
export interface IStorage {
|
|
7
|
-
getMessage(): Promise<string>;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class DatabaseStorage implements IStorage {
|
|
11
|
-
async getMessage(): Promise<string> {
|
|
12
|
-
try {
|
|
13
|
-
const rows = await db
|
|
14
|
-
.select({ content: messages.content })
|
|
15
|
-
.from(messages)
|
|
16
|
-
.orderBy(desc(messages.id))
|
|
17
|
-
.limit(1);
|
|
18
|
-
|
|
19
|
-
return rows[0]?.content ?? "Hello from the Backend API!";
|
|
20
|
-
} catch (error) {
|
|
21
|
-
console.error("DatabaseStorage.getMessage() failed:", error);
|
|
22
|
-
|
|
23
|
-
throw new Error(
|
|
24
|
-
`数据库读取失败:请先执行 \`pnpm db:push\` 初始化 SQLite 数据库(${describeDatabaseFilePath()})。`,
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const storage = new DatabaseStorage();
|