sveltekit-admin 0.1.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.
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # sveltekit-admin
2
+
3
+ 🎛️ A Django-like admin panel for SvelteKit applications with Prisma and better-auth.
4
+
5
+ ![Version](https://img.shields.io/npm/v/sveltekit-admin)
6
+ ![License](https://img.shields.io/npm/l/sveltekit-admin)
7
+
8
+ ## Features
9
+
10
+ - 🔍 **Auto-introspection** of Prisma schema
11
+ - 📝 **CRUD operations** auto-generated for all models
12
+ - 🔐 **better-auth integration** for admin authentication
13
+ - 🎨 **Standalone UI** - no Tailwind or other CSS framework required
14
+ - ⚡ **Zero-config** - just add the plugin and you're ready
15
+ - 🔧 **Customizable** - hide fields, set readonly, custom labels
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install sveltekit-admin
21
+ # or
22
+ bun add sveltekit-admin
23
+ # or
24
+ pnpm add sveltekit-admin
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Add the Vite plugin
30
+
31
+ ```typescript
32
+ // vite.config.ts
33
+ import { sveltekit } from '@sveltejs/kit/vite';
34
+ import { svelteKitAdmin } from 'sveltekit-admin/plugin';
35
+ import { defineConfig } from 'vite';
36
+
37
+ export default defineConfig({
38
+ plugins: [
39
+ sveltekit(),
40
+ svelteKitAdmin({
41
+ prismaSchemaPath: './prisma/schema.prisma',
42
+ basePath: '/admin',
43
+ auth: {
44
+ provider: 'better-auth',
45
+ adminRole: 'admin'
46
+ }
47
+ })
48
+ ]
49
+ });
50
+ ```
51
+
52
+ ### 2. Add the auth hook (optional, for protected admin)
53
+
54
+ ```typescript
55
+ // src/hooks.server.ts
56
+ import { createAdminHandle } from 'sveltekit-admin';
57
+ import { sequence } from '@sveltejs/kit/hooks';
58
+
59
+ const adminHandle = createAdminHandle({
60
+ basePath: '/admin',
61
+ auth: {
62
+ provider: 'better-auth',
63
+ adminRole: 'admin'
64
+ }
65
+ });
66
+
67
+ export const handle = sequence(
68
+ // your auth handle first
69
+ adminHandle
70
+ );
71
+ ```
72
+
73
+ ### 3. Access your admin panel
74
+
75
+ Navigate to `/admin` and you'll see:
76
+ - Dashboard with model statistics
77
+ - List views with pagination, search, and sorting
78
+ - Create/Edit forms auto-generated from your Prisma schema
79
+ - Delete with confirmation
80
+
81
+ ## Configuration
82
+
83
+ ```typescript
84
+ svelteKitAdmin({
85
+ // Path to your Prisma schema (default: './prisma/schema.prisma')
86
+ prismaSchemaPath: './prisma/schema.prisma',
87
+
88
+ // Base path for admin routes (default: '/admin')
89
+ basePath: '/admin',
90
+
91
+ // Authentication configuration
92
+ auth: {
93
+ provider: 'better-auth',
94
+ adminRole: 'admin', // Role required to access admin
95
+ // Or custom check function:
96
+ adminCheck: async (user) => user.isAdmin === true
97
+ },
98
+
99
+ // Per-model configuration
100
+ models: {
101
+ User: {
102
+ // Fields to hide from all views
103
+ hidden: ['password', 'hashedPassword'],
104
+ // Fields that cannot be edited
105
+ readonly: ['id', 'createdAt', 'updatedAt'],
106
+ // Fields to show in list view (default: auto-detect)
107
+ listFields: ['email', 'name', 'role', 'createdAt'],
108
+ // Custom label for the model
109
+ label: 'Users',
110
+ // Icon name (Lucide icon)
111
+ icon: 'users'
112
+ },
113
+ Session: {
114
+ // Completely exclude this model from admin
115
+ hidden: true
116
+ }
117
+ },
118
+
119
+ // Models to exclude from admin
120
+ exclude: ['Session', 'VerificationToken'],
121
+
122
+ // Custom branding
123
+ branding: {
124
+ title: 'My Admin',
125
+ logo: '/logo.svg',
126
+ primaryColor: '#6366f1'
127
+ }
128
+ })
129
+ ```
130
+
131
+ ## Components
132
+
133
+ You can also use the admin components directly in your own pages:
134
+
135
+ ```svelte
136
+ <script>
137
+ import { AdminLayout, DataTable, AdminForm } from 'sveltekit-admin/components';
138
+ </script>
139
+
140
+ <AdminLayout title="Custom Admin" models={[...]}>
141
+ <DataTable
142
+ data={users}
143
+ columns={[
144
+ { key: 'email', label: 'Email', sortable: true },
145
+ { key: 'name', label: 'Name', sortable: true }
146
+ ]}
147
+ basePath="/admin"
148
+ modelName="User"
149
+ />
150
+ </AdminLayout>
151
+ ```
152
+
153
+ ## Prisma Schema Introspection
154
+
155
+ The admin automatically parses your Prisma schema and:
156
+
157
+ - Extracts all models and their fields
158
+ - Detects field types and generates appropriate form inputs
159
+ - Handles relations (1-1, 1-N, N-N)
160
+ - Respects field attributes (@id, @unique, @default, @updatedAt)
161
+ - Hides sensitive fields by name pattern (password, hash, secret)
162
+
163
+ ## Requirements
164
+
165
+ - SvelteKit 2.x
166
+ - Svelte 5.x
167
+ - Prisma 5.x or 6.x
168
+ - better-auth 1.x (for authentication)
169
+
170
+ ## License
171
+
172
+ MIT
@@ -0,0 +1,227 @@
1
+ /**
2
+ * SvelteKit Admin - Core Admin Factory
3
+ * Creates all the necessary handlers for the admin panel
4
+ */
5
+ import { type PrismaSchema, type PrismaModel } from './server/introspection/parser.js';
6
+ export interface AdminConfig {
7
+ /** Prisma client instance */
8
+ prisma: any;
9
+ /** Path to Prisma schema file */
10
+ schemaPath?: string;
11
+ /** Parsed schema (alternative to schemaPath) */
12
+ schema?: PrismaSchema;
13
+ /** Base path for admin (default: /admin) */
14
+ basePath?: string;
15
+ /** Models to exclude */
16
+ exclude?: string[];
17
+ /** Per-model configuration */
18
+ models?: Record<string, {
19
+ hidden?: string[];
20
+ readonly?: string[];
21
+ listFields?: string[];
22
+ label?: string;
23
+ }>;
24
+ /** Branding options */
25
+ branding?: {
26
+ title?: string;
27
+ logo?: string;
28
+ primaryColor?: string;
29
+ };
30
+ /** Auth check function */
31
+ checkAdmin?: (user: unknown) => boolean | Promise<boolean>;
32
+ /** Admin role name (if using default check) */
33
+ adminRole?: string;
34
+ }
35
+ export interface AdminContext {
36
+ config: AdminConfig;
37
+ schema: PrismaSchema;
38
+ models: PrismaModel[];
39
+ getModel: (name: string) => PrismaModel | undefined;
40
+ }
41
+ /**
42
+ * Create admin context with all necessary data
43
+ */
44
+ export declare function createAdmin(config: AdminConfig): AdminContext;
45
+ /**
46
+ * Layout data loader - provides models list and config to layout
47
+ */
48
+ export declare function createLayoutLoad(ctx: AdminContext): ({ locals }: {
49
+ locals: any;
50
+ }) => Promise<{
51
+ models: {
52
+ name: string;
53
+ label: string;
54
+ }[];
55
+ user: {
56
+ name: any;
57
+ email: any;
58
+ } | undefined;
59
+ config: {
60
+ basePath: string;
61
+ branding: {
62
+ title: string;
63
+ logo: string | undefined;
64
+ primaryColor: string;
65
+ };
66
+ };
67
+ }>;
68
+ /**
69
+ * Dashboard data loader - provides model counts
70
+ */
71
+ export declare function createDashboardLoad(ctx: AdminContext): () => Promise<{
72
+ models: {
73
+ name: string;
74
+ label: string;
75
+ count: number;
76
+ }[];
77
+ stats: {
78
+ totalRecords: number;
79
+ modelsCount: number;
80
+ };
81
+ }>;
82
+ /**
83
+ * Model list data loader
84
+ */
85
+ export declare function createModelListLoad(ctx: AdminContext): ({ params, url }: {
86
+ params: {
87
+ model: string;
88
+ };
89
+ url: URL;
90
+ }) => Promise<{
91
+ model: {
92
+ name: string;
93
+ label: string;
94
+ fields: {
95
+ name: string;
96
+ type: string;
97
+ label: string;
98
+ }[];
99
+ primaryKey: string;
100
+ };
101
+ items: unknown[];
102
+ total: number;
103
+ page: number;
104
+ perPage: number;
105
+ orderBy: string;
106
+ orderDir: "asc" | "desc";
107
+ search: string;
108
+ config: {
109
+ basePath: string;
110
+ hidden: string[];
111
+ listFields: string[] | undefined;
112
+ };
113
+ }>;
114
+ /**
115
+ * Model create page loader
116
+ */
117
+ export declare function createModelNewLoad(ctx: AdminContext): ({ params }: {
118
+ params: {
119
+ model: string;
120
+ };
121
+ }) => Promise<{
122
+ model: {
123
+ name: string;
124
+ label: string;
125
+ fields: {
126
+ name: string;
127
+ type: string;
128
+ required: boolean;
129
+ label: string;
130
+ }[];
131
+ };
132
+ config: {
133
+ basePath: string;
134
+ hidden: string[];
135
+ readonly: string[];
136
+ };
137
+ relationOptions: Record<string, {
138
+ id: string | number;
139
+ label: string;
140
+ }[]>;
141
+ }>;
142
+ /**
143
+ * Model create action
144
+ */
145
+ export declare function createModelNewAction(ctx: AdminContext): ({ params, request }: {
146
+ params: {
147
+ model: string;
148
+ };
149
+ request: Request;
150
+ }) => Promise<{
151
+ success: boolean;
152
+ error?: undefined;
153
+ fieldErrors?: undefined;
154
+ } | {
155
+ success: boolean;
156
+ error: any;
157
+ fieldErrors: {};
158
+ }>;
159
+ /**
160
+ * Model edit page loader
161
+ */
162
+ export declare function createModelEditLoad(ctx: AdminContext): ({ params }: {
163
+ params: {
164
+ model: string;
165
+ id: string;
166
+ };
167
+ }) => Promise<{
168
+ model: {
169
+ name: string;
170
+ label: string;
171
+ primaryKey: string;
172
+ fields: {
173
+ name: string;
174
+ type: string;
175
+ required: boolean;
176
+ label: string;
177
+ }[];
178
+ };
179
+ item: {};
180
+ config: {
181
+ basePath: string;
182
+ hidden: string[];
183
+ readonly: string[];
184
+ };
185
+ relationOptions: Record<string, {
186
+ id: string | number;
187
+ label: string;
188
+ }[]>;
189
+ }>;
190
+ /**
191
+ * Model update action
192
+ */
193
+ export declare function createModelEditAction(ctx: AdminContext): ({ params, request }: {
194
+ params: {
195
+ model: string;
196
+ id: string;
197
+ };
198
+ request: Request;
199
+ }) => Promise<{
200
+ success: boolean;
201
+ error?: undefined;
202
+ } | {
203
+ success: boolean;
204
+ error: any;
205
+ }>;
206
+ /**
207
+ * Model delete action
208
+ */
209
+ export declare function createModelDeleteAction(ctx: AdminContext): ({ params, request }: {
210
+ params: {
211
+ model: string;
212
+ };
213
+ request: Request;
214
+ }) => Promise<{
215
+ success: boolean;
216
+ error?: undefined;
217
+ } | {
218
+ success: boolean;
219
+ error: any;
220
+ }>;
221
+ /**
222
+ * Auth guard hook
223
+ */
224
+ export declare function createAdminGuard(ctx: AdminContext): ({ event, resolve }: {
225
+ event: any;
226
+ resolve: Function;
227
+ }) => Promise<any>;