@chimerai/cli 0.2.73
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/LICENSE +21 -0
- package/README.md +293 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +317 -0
- package/dist/commands/add.d.ts +11 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +2126 -0
- package/dist/commands/create.d.ts +12 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +1703 -0
- package/dist/commands/deploy.d.ts +11 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +219 -0
- package/dist/commands/dev.d.ts +17 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +206 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +728 -0
- package/dist/commands/generate.d.ts +19 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +429 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +269 -0
- package/dist/commands/list.d.ts +12 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +328 -0
- package/dist/commands/migrate.d.ts +14 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +197 -0
- package/dist/commands/plugin.d.ts +10 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +239 -0
- package/dist/commands/remove.d.ts +11 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +472 -0
- package/dist/commands/secret.d.ts +12 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +102 -0
- package/dist/commands/setup.d.ts +9 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +788 -0
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +211 -0
- package/dist/commands/use.d.ts +9 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +51 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/license.d.ts +55 -0
- package/dist/license.d.ts.map +1 -0
- package/dist/license.js +258 -0
- package/dist/scanner.d.ts +31 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +113 -0
- package/dist/schema-manager.d.ts +26 -0
- package/dist/schema-manager.d.ts.map +1 -0
- package/dist/schema-manager.js +132 -0
- package/dist/templates/admin.d.ts +49 -0
- package/dist/templates/admin.d.ts.map +1 -0
- package/dist/templates/admin.js +1358 -0
- package/dist/templates/ai-routes.d.ts +17 -0
- package/dist/templates/ai-routes.d.ts.map +1 -0
- package/dist/templates/ai-routes.js +1130 -0
- package/dist/templates/ai-service-tools.d.ts +22 -0
- package/dist/templates/ai-service-tools.d.ts.map +1 -0
- package/dist/templates/ai-service-tools.js +1424 -0
- package/dist/templates/ai-service.d.ts +66 -0
- package/dist/templates/ai-service.d.ts.map +1 -0
- package/dist/templates/ai-service.js +2202 -0
- package/dist/templates/api-routes.d.ts +108 -0
- package/dist/templates/api-routes.d.ts.map +1 -0
- package/dist/templates/api-routes.js +1219 -0
- package/dist/templates/auth.d.ts +48 -0
- package/dist/templates/auth.d.ts.map +1 -0
- package/dist/templates/auth.js +381 -0
- package/dist/templates/billing.d.ts +44 -0
- package/dist/templates/billing.d.ts.map +1 -0
- package/dist/templates/billing.js +551 -0
- package/dist/templates/chat.d.ts +63 -0
- package/dist/templates/chat.d.ts.map +1 -0
- package/dist/templates/chat.js +1979 -0
- package/dist/templates/components.d.ts +22 -0
- package/dist/templates/components.d.ts.map +1 -0
- package/dist/templates/components.js +672 -0
- package/dist/templates/config.d.ts +6 -0
- package/dist/templates/config.d.ts.map +1 -0
- package/dist/templates/config.js +86 -0
- package/dist/templates/docker.d.ts +25 -0
- package/dist/templates/docker.d.ts.map +1 -0
- package/dist/templates/docker.js +165 -0
- package/dist/templates/gdpr.d.ts +16 -0
- package/dist/templates/gdpr.d.ts.map +1 -0
- package/dist/templates/gdpr.js +259 -0
- package/dist/templates/index.d.ts +77 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +339 -0
- package/dist/templates/layout.d.ts +67 -0
- package/dist/templates/layout.d.ts.map +1 -0
- package/dist/templates/layout.js +670 -0
- package/dist/templates/mfa.d.ts +23 -0
- package/dist/templates/mfa.d.ts.map +1 -0
- package/dist/templates/mfa.js +353 -0
- package/dist/templates/middleware.d.ts +12 -0
- package/dist/templates/middleware.d.ts.map +1 -0
- package/dist/templates/middleware.js +116 -0
- package/dist/templates/prisma.d.ts +35 -0
- package/dist/templates/prisma.d.ts.map +1 -0
- package/dist/templates/prisma.js +724 -0
- package/dist/templates/provider-routes.d.ts +21 -0
- package/dist/templates/provider-routes.d.ts.map +1 -0
- package/dist/templates/provider-routes.js +1203 -0
- package/dist/templates/rag.d.ts +48 -0
- package/dist/templates/rag.d.ts.map +1 -0
- package/dist/templates/rag.js +532 -0
- package/dist/templates/widget.d.ts +64 -0
- package/dist/templates/widget.d.ts.map +1 -0
- package/dist/templates/widget.js +1360 -0
- package/dist/utils/provider-db.d.ts +63 -0
- package/dist/utils/provider-db.d.ts.map +1 -0
- package/dist/utils/provider-db.js +300 -0
- package/dist/utils.d.ts +78 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +330 -0
- package/package.json +60 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication component templates for NextAuth.js integration
|
|
3
|
+
* Generates auth routes, pages, providers, and type definitions
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generates the NextAuth API route with credentials provider
|
|
7
|
+
* Includes user authentication, JWT callbacks, and role/permissions handling
|
|
8
|
+
* @returns TypeScript content for app/api/auth/[...nextauth]/route.ts
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateNextAuthRoute(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Generates the login page component with email/password form
|
|
13
|
+
* Includes error handling, loading states, and redirect to dashboard on success
|
|
14
|
+
* @returns TypeScript/JSX content for app/(auth)/login/page.tsx
|
|
15
|
+
*/
|
|
16
|
+
export declare function generateLoginPage(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Generates the SessionProvider wrapper component for client-side session access
|
|
19
|
+
* Wraps the app with NextAuth SessionProvider to enable useSession() hook usage
|
|
20
|
+
* @returns TypeScript/JSX content for components/SessionProvider.tsx
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateSessionProvider(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Generates the LogoutButton component for sign-out functionality
|
|
25
|
+
* Redirects to login page after sign-out
|
|
26
|
+
* @returns TypeScript/JSX content for components/LogoutButton.tsx
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateLogoutButton(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Generates NextAuth TypeScript type definitions
|
|
31
|
+
* Extends Session, User, and JWT interfaces for role-based access control
|
|
32
|
+
* @returns TypeScript content for types/next-auth.d.ts
|
|
33
|
+
*/
|
|
34
|
+
export declare function generateNextAuthTypes(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Generates the NextAuth configuration library
|
|
37
|
+
* Centralizes auth options, provider configuration, and session strategy
|
|
38
|
+
* Used for importing authOptions in route handlers and API middleware
|
|
39
|
+
* @returns TypeScript content for lib/auth.ts
|
|
40
|
+
*/
|
|
41
|
+
export declare function generateAuthLib(): string;
|
|
42
|
+
/**
|
|
43
|
+
* Generates the dual-auth resolve helper.
|
|
44
|
+
* Checks NextAuth session first (browser), then API key (widget/external).
|
|
45
|
+
* @returns TypeScript content for lib/auth/resolve-auth.ts
|
|
46
|
+
*/
|
|
47
|
+
export declare function generateResolveAuth(): string;
|
|
48
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/templates/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAS9C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CA4G1C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAUhD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAiB7C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAuC9C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAgGxC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA8C5C"}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Authentication component templates for NextAuth.js integration
|
|
4
|
+
* Generates auth routes, pages, providers, and type definitions
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.generateNextAuthRoute = generateNextAuthRoute;
|
|
8
|
+
exports.generateLoginPage = generateLoginPage;
|
|
9
|
+
exports.generateSessionProvider = generateSessionProvider;
|
|
10
|
+
exports.generateLogoutButton = generateLogoutButton;
|
|
11
|
+
exports.generateNextAuthTypes = generateNextAuthTypes;
|
|
12
|
+
exports.generateAuthLib = generateAuthLib;
|
|
13
|
+
exports.generateResolveAuth = generateResolveAuth;
|
|
14
|
+
/**
|
|
15
|
+
* Generates the NextAuth API route with credentials provider
|
|
16
|
+
* Includes user authentication, JWT callbacks, and role/permissions handling
|
|
17
|
+
* @returns TypeScript content for app/api/auth/[...nextauth]/route.ts
|
|
18
|
+
*/
|
|
19
|
+
function generateNextAuthRoute() {
|
|
20
|
+
return `// @chimerai component=NextAuthRoute version=1.0
|
|
21
|
+
import NextAuth from 'next-auth';
|
|
22
|
+
import { authOptions } from '@/lib/auth';
|
|
23
|
+
|
|
24
|
+
const handler = NextAuth(authOptions);
|
|
25
|
+
|
|
26
|
+
export { handler as GET, handler as POST };
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generates the login page component with email/password form
|
|
31
|
+
* Includes error handling, loading states, and redirect to dashboard on success
|
|
32
|
+
* @returns TypeScript/JSX content for app/(auth)/login/page.tsx
|
|
33
|
+
*/
|
|
34
|
+
function generateLoginPage() {
|
|
35
|
+
return `// @chimerai component=LoginPage version=1.0
|
|
36
|
+
'use client';
|
|
37
|
+
|
|
38
|
+
import { useState } from 'react';
|
|
39
|
+
import { signIn } from 'next-auth/react';
|
|
40
|
+
import { useRouter } from 'next/navigation';
|
|
41
|
+
|
|
42
|
+
export default function LoginPage() {
|
|
43
|
+
const router = useRouter();
|
|
44
|
+
const [email, setEmail] = useState('');
|
|
45
|
+
const [password, setPassword] = useState('');
|
|
46
|
+
const [error, setError] = useState('');
|
|
47
|
+
const [loading, setLoading] = useState(false);
|
|
48
|
+
|
|
49
|
+
async function handleSubmit(e: React.FormEvent) {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
setError('');
|
|
52
|
+
setLoading(true);
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const result = await signIn('credentials', {
|
|
56
|
+
email,
|
|
57
|
+
password,
|
|
58
|
+
redirect: false,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (result?.error) {
|
|
62
|
+
setError('Invalid email or password');
|
|
63
|
+
} else {
|
|
64
|
+
router.push('/');
|
|
65
|
+
router.refresh();
|
|
66
|
+
}
|
|
67
|
+
} catch (err) {
|
|
68
|
+
setError('An error occurred. Please try again.');
|
|
69
|
+
} finally {
|
|
70
|
+
setLoading(false);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-950 py-12 px-4 sm:px-6 lg:px-8">
|
|
76
|
+
<div className="max-w-md w-full space-y-8">
|
|
77
|
+
<div>
|
|
78
|
+
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900 dark:text-white">
|
|
79
|
+
Sign in to your account
|
|
80
|
+
</h2>
|
|
81
|
+
</div>
|
|
82
|
+
<form className="mt-8 space-y-6" onSubmit={handleSubmit}>
|
|
83
|
+
{error && (
|
|
84
|
+
<div className="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
|
|
85
|
+
<div className="text-sm text-red-800 dark:text-red-400">{error}</div>
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
<div className="rounded-md shadow-sm -space-y-px">
|
|
89
|
+
<div>
|
|
90
|
+
<label htmlFor="email" className="sr-only">
|
|
91
|
+
Email address
|
|
92
|
+
</label>
|
|
93
|
+
<input
|
|
94
|
+
id="email"
|
|
95
|
+
name="email"
|
|
96
|
+
type="email"
|
|
97
|
+
autoComplete="email"
|
|
98
|
+
required
|
|
99
|
+
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
|
|
100
|
+
placeholder="Email address"
|
|
101
|
+
value={email}
|
|
102
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<div>
|
|
106
|
+
<label htmlFor="password" className="sr-only">
|
|
107
|
+
Password
|
|
108
|
+
</label>
|
|
109
|
+
<input
|
|
110
|
+
id="password"
|
|
111
|
+
name="password"
|
|
112
|
+
type="password"
|
|
113
|
+
autoComplete="current-password"
|
|
114
|
+
required
|
|
115
|
+
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
|
|
116
|
+
placeholder="Password"
|
|
117
|
+
value={password}
|
|
118
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<div>
|
|
124
|
+
<button
|
|
125
|
+
type="submit"
|
|
126
|
+
disabled={loading}
|
|
127
|
+
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-950 focus:ring-indigo-500 disabled:opacity-50"
|
|
128
|
+
>
|
|
129
|
+
{loading ? 'Signing in...' : 'Sign in'}
|
|
130
|
+
</button>
|
|
131
|
+
</div>
|
|
132
|
+
</form>
|
|
133
|
+
<div className="text-center text-sm text-gray-600 dark:text-gray-400">
|
|
134
|
+
<p>Default admin credentials:</p>
|
|
135
|
+
<p className="font-mono text-xs mt-1 dark:text-gray-500">admin@example.com / admin123</p>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Generates the SessionProvider wrapper component for client-side session access
|
|
145
|
+
* Wraps the app with NextAuth SessionProvider to enable useSession() hook usage
|
|
146
|
+
* @returns TypeScript/JSX content for components/SessionProvider.tsx
|
|
147
|
+
*/
|
|
148
|
+
function generateSessionProvider() {
|
|
149
|
+
return `// @chimerai component=SessionProvider version=1.0
|
|
150
|
+
'use client';
|
|
151
|
+
|
|
152
|
+
import { SessionProvider as NextAuthSessionProvider } from 'next-auth/react';
|
|
153
|
+
|
|
154
|
+
export function SessionProvider({ children }: { children: React.ReactNode }) {
|
|
155
|
+
return <NextAuthSessionProvider>{children}</NextAuthSessionProvider>;
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Generates the LogoutButton component for sign-out functionality
|
|
161
|
+
* Redirects to login page after sign-out
|
|
162
|
+
* @returns TypeScript/JSX content for components/LogoutButton.tsx
|
|
163
|
+
*/
|
|
164
|
+
function generateLogoutButton() {
|
|
165
|
+
return `// @chimerai component=LogoutButton version=1.0
|
|
166
|
+
'use client';
|
|
167
|
+
|
|
168
|
+
import { signOut } from 'next-auth/react';
|
|
169
|
+
|
|
170
|
+
export function LogoutButton() {
|
|
171
|
+
return (
|
|
172
|
+
<button
|
|
173
|
+
onClick={() => signOut({ callbackUrl: '/auth/signin' })}
|
|
174
|
+
className="px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-md hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
|
|
175
|
+
>
|
|
176
|
+
Sign Out
|
|
177
|
+
</button>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Generates NextAuth TypeScript type definitions
|
|
184
|
+
* Extends Session, User, and JWT interfaces for role-based access control
|
|
185
|
+
* @returns TypeScript content for types/next-auth.d.ts
|
|
186
|
+
*/
|
|
187
|
+
function generateNextAuthTypes() {
|
|
188
|
+
return `// @chimerai component=NextAuthTypes version=1.0
|
|
189
|
+
import { DefaultSession } from 'next-auth';
|
|
190
|
+
|
|
191
|
+
declare module 'next-auth' {
|
|
192
|
+
interface Session {
|
|
193
|
+
user: {
|
|
194
|
+
id: string;
|
|
195
|
+
roles?: Array<{
|
|
196
|
+
id: string;
|
|
197
|
+
name: string;
|
|
198
|
+
permissions: string[];
|
|
199
|
+
}>;
|
|
200
|
+
} & DefaultSession['user'];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
interface User {
|
|
204
|
+
id: string;
|
|
205
|
+
email: string;
|
|
206
|
+
name?: string | null;
|
|
207
|
+
roles?: Array<{
|
|
208
|
+
id: string;
|
|
209
|
+
name: string;
|
|
210
|
+
permissions: string[];
|
|
211
|
+
}>;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
declare module 'next-auth/jwt' {
|
|
216
|
+
interface JWT {
|
|
217
|
+
id: string;
|
|
218
|
+
roles?: Array<{
|
|
219
|
+
id: string;
|
|
220
|
+
name: string;
|
|
221
|
+
permissions: string[];
|
|
222
|
+
}>;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Generates the NextAuth configuration library
|
|
229
|
+
* Centralizes auth options, provider configuration, and session strategy
|
|
230
|
+
* Used for importing authOptions in route handlers and API middleware
|
|
231
|
+
* @returns TypeScript content for lib/auth.ts
|
|
232
|
+
*/
|
|
233
|
+
function generateAuthLib() {
|
|
234
|
+
return `// @chimerai component=AuthLib version=1.0
|
|
235
|
+
import { NextAuthOptions } from 'next-auth';
|
|
236
|
+
import { PrismaAdapter } from '@auth/prisma-adapter';
|
|
237
|
+
import { prisma } from './prisma';
|
|
238
|
+
import CredentialsProvider from 'next-auth/providers/credentials';
|
|
239
|
+
import bcrypt from 'bcryptjs';
|
|
240
|
+
import { logAuditAction } from './audit';
|
|
241
|
+
|
|
242
|
+
export const authOptions: NextAuthOptions = {
|
|
243
|
+
adapter: PrismaAdapter(prisma) as any,
|
|
244
|
+
providers: [
|
|
245
|
+
CredentialsProvider({
|
|
246
|
+
name: 'Credentials',
|
|
247
|
+
credentials: {
|
|
248
|
+
email: { label: 'Email', type: 'email' },
|
|
249
|
+
password: { label: 'Password', type: 'password' },
|
|
250
|
+
},
|
|
251
|
+
async authorize(credentials) {
|
|
252
|
+
if (!credentials?.email || !credentials?.password) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Query user — try with RBAC roles first, fall back to plain user if roles relation doesn't exist
|
|
257
|
+
let user: any = null;
|
|
258
|
+
try {
|
|
259
|
+
user = await (prisma.user as any).findUnique({
|
|
260
|
+
where: { email: credentials.email },
|
|
261
|
+
include: {
|
|
262
|
+
roles: { select: { role: { select: { id: true, name: true, permissions: true } } } },
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
} catch {
|
|
266
|
+
// roles relation not available (admin-ui not installed) — plain query
|
|
267
|
+
user = await prisma.user.findUnique({
|
|
268
|
+
where: { email: credentials.email },
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (!user || !user.password || !user.email) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const isValid = await bcrypt.compare(credentials.password, user.password);
|
|
277
|
+
|
|
278
|
+
if (!isValid) {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
id: user.id,
|
|
284
|
+
email: user.email,
|
|
285
|
+
name: user.name,
|
|
286
|
+
roles: Array.isArray(user.roles)
|
|
287
|
+
? user.roles.map((ur: any) => ur.role)
|
|
288
|
+
: [],
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
}),
|
|
292
|
+
],
|
|
293
|
+
callbacks: {
|
|
294
|
+
async jwt({ token, user }) {
|
|
295
|
+
if (user) {
|
|
296
|
+
token.id = user.id;
|
|
297
|
+
token.roles = (user as any).roles;
|
|
298
|
+
}
|
|
299
|
+
return token;
|
|
300
|
+
},
|
|
301
|
+
async session({ session, token }) {
|
|
302
|
+
if (session.user) {
|
|
303
|
+
session.user.id = token.id as string;
|
|
304
|
+
session.user.roles = token.roles as any;
|
|
305
|
+
}
|
|
306
|
+
return session;
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
events: {
|
|
310
|
+
async signIn({ user }) {
|
|
311
|
+
if (user?.id) {
|
|
312
|
+
await logAuditAction({
|
|
313
|
+
action: 'user.login',
|
|
314
|
+
userId: user.id,
|
|
315
|
+
metadata: { email: user.email },
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
session: {
|
|
321
|
+
strategy: 'jwt',
|
|
322
|
+
},
|
|
323
|
+
pages: {
|
|
324
|
+
signIn: '/auth/signin',
|
|
325
|
+
},
|
|
326
|
+
secret: process.env.NEXTAUTH_SECRET,
|
|
327
|
+
};
|
|
328
|
+
`;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Generates the dual-auth resolve helper.
|
|
332
|
+
* Checks NextAuth session first (browser), then API key (widget/external).
|
|
333
|
+
* @returns TypeScript content for lib/auth/resolve-auth.ts
|
|
334
|
+
*/
|
|
335
|
+
function generateResolveAuth() {
|
|
336
|
+
return `// @chimerai component=ResolveAuth version=1.0
|
|
337
|
+
import { getServerSession } from 'next-auth';
|
|
338
|
+
import { NextRequest } from 'next/server';
|
|
339
|
+
import { authOptions } from '@/lib/auth';
|
|
340
|
+
import { verifyApiKey } from '@/lib/api-key-auth';
|
|
341
|
+
|
|
342
|
+
export interface AuthContext {
|
|
343
|
+
userId: string;
|
|
344
|
+
email: string;
|
|
345
|
+
authMethod: 'session' | 'api-key';
|
|
346
|
+
scopes?: string[];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Dual-Auth: Checks NextAuth session first (browser), then API key (widget/external).
|
|
351
|
+
* Returns AuthContext or throws an error with status.
|
|
352
|
+
*/
|
|
353
|
+
export async function resolveAuth(request: NextRequest): Promise<AuthContext> {
|
|
354
|
+
// 1. Session-Auth (Browser-User)
|
|
355
|
+
const session = await getServerSession(authOptions);
|
|
356
|
+
if (session?.user?.id) {
|
|
357
|
+
return {
|
|
358
|
+
userId: session.user.id,
|
|
359
|
+
email: session.user.email || '',
|
|
360
|
+
authMethod: 'session',
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// 2. API-Key-Auth (Widget/External)
|
|
365
|
+
const result = await verifyApiKey(request);
|
|
366
|
+
if (result.valid && result.userId) {
|
|
367
|
+
return {
|
|
368
|
+
userId: result.userId,
|
|
369
|
+
email: result.email || '',
|
|
370
|
+
authMethod: 'api-key',
|
|
371
|
+
scopes: result.scopes || [],
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// 3. No Auth — Error
|
|
376
|
+
const error: any = new Error('Unauthorized');
|
|
377
|
+
error.status = 401;
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
380
|
+
`;
|
|
381
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Billing & Stripe template generators
|
|
3
|
+
* Generates billing page, Stripe lib, checkout/portal/webhook routes
|
|
4
|
+
* SPEC: FRONTEND_UI_SPEC.md Section A4
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Generates the Stripe utility library
|
|
8
|
+
* Raw fetch against Stripe API — no Stripe SDK dependency needed
|
|
9
|
+
* @returns TypeScript content for lib/stripe.ts
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateStripeLib(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Generates the billing / pricing page
|
|
14
|
+
* Shows pricing plans with upgrade flow + subscription overview
|
|
15
|
+
* SPEC: A4 — Pricing Plans, Upgrade Flow, Subscription Overview
|
|
16
|
+
* @returns TypeScript/JSX content for app/billing/page.tsx
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateBillingPage(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Generates the checkout API route
|
|
21
|
+
* POST: Creates Stripe Checkout Session for subscription upgrade
|
|
22
|
+
* @returns TypeScript content for app/api/billing/checkout/route.ts
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateCheckoutRoute(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generates the billing portal API route
|
|
27
|
+
* POST: Creates Stripe Customer Portal Session
|
|
28
|
+
* @returns TypeScript content for app/api/billing/portal/route.ts
|
|
29
|
+
*/
|
|
30
|
+
export declare function generatePortalRoute(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Generates the subscription status API route
|
|
33
|
+
* GET: Returns current subscription, credits, usage for the logged-in user
|
|
34
|
+
* @returns TypeScript content for app/api/billing/subscription/route.ts
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateSubscriptionRoute(): string;
|
|
37
|
+
/**
|
|
38
|
+
* Generates the Stripe webhook handler
|
|
39
|
+
* POST: Processes Stripe events (checkout complete, subscription updates, invoice events)
|
|
40
|
+
* SPEC: A4 — Webhook Events
|
|
41
|
+
* @returns TypeScript content for app/api/webhooks/stripe/route.ts
|
|
42
|
+
*/
|
|
43
|
+
export declare function generateStripeWebhookRoute(): string;
|
|
44
|
+
//# sourceMappingURL=billing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["../../src/templates/billing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CA0F1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAwM5C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAwC9C;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA8B5C;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAwClD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAoGnD"}
|