@svadmin/lite 0.3.6 → 0.3.10

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 (172) hide show
  1. package/README.md +19 -13
  2. package/dist/components/LiteAlert.svelte +19 -0
  3. package/dist/components/LiteAlert.svelte.d.ts +11 -0
  4. package/dist/components/LiteArrayField.svelte +60 -0
  5. package/dist/components/LiteArrayField.svelte.d.ts +17 -0
  6. package/dist/components/LiteArrayItem.svelte +146 -0
  7. package/dist/components/LiteArrayItem.svelte.d.ts +13 -0
  8. package/dist/components/LiteAuditLog.svelte +104 -0
  9. package/dist/components/LiteAuditLog.svelte.d.ts +23 -0
  10. package/dist/components/LiteBreadcrumbs.svelte +39 -0
  11. package/dist/components/LiteBreadcrumbs.svelte.d.ts +16 -0
  12. package/dist/components/LiteChatDialog.svelte +101 -0
  13. package/dist/components/LiteChatDialog.svelte.d.ts +20 -0
  14. package/dist/components/LiteConfirmDialog.svelte +60 -0
  15. package/dist/components/LiteConfirmDialog.svelte.d.ts +22 -0
  16. package/dist/components/LiteEmptyState.svelte +39 -0
  17. package/dist/components/LiteEmptyState.svelte.d.ts +16 -0
  18. package/dist/components/LiteForm.svelte +165 -0
  19. package/dist/components/LiteForm.svelte.d.ts +26 -0
  20. package/dist/components/LiteLayout.svelte +147 -0
  21. package/dist/components/LiteLayout.svelte.d.ts +19 -0
  22. package/dist/components/LiteLogin.svelte +41 -0
  23. package/dist/components/LiteLogin.svelte.d.ts +8 -0
  24. package/dist/components/LitePagination.svelte +73 -0
  25. package/dist/components/LitePagination.svelte.d.ts +11 -0
  26. package/dist/components/LitePermissionMatrix.svelte +147 -0
  27. package/dist/components/LitePermissionMatrix.svelte.d.ts +32 -0
  28. package/dist/components/LiteSearch.svelte +41 -0
  29. package/dist/components/LiteSearch.svelte.d.ts +9 -0
  30. package/dist/components/LiteShow.svelte +61 -0
  31. package/dist/components/LiteShow.svelte.d.ts +14 -0
  32. package/dist/components/LiteShowField.svelte +62 -0
  33. package/dist/components/LiteShowField.svelte.d.ts +12 -0
  34. package/dist/components/LiteStatsCard.svelte +70 -0
  35. package/dist/components/LiteStatsCard.svelte.d.ts +24 -0
  36. package/dist/components/LiteTable.svelte +132 -0
  37. package/dist/components/LiteTable.svelte.d.ts +19 -0
  38. package/dist/components/LiteTabs.svelte +57 -0
  39. package/dist/components/LiteTabs.svelte.d.ts +16 -0
  40. package/dist/components/advanced/LiteAutoSaveIndicator.svelte +26 -0
  41. package/dist/components/advanced/LiteAutoSaveIndicator.svelte.d.ts +12 -0
  42. package/dist/components/advanced/LiteDraggableHeader.svelte +33 -0
  43. package/dist/components/advanced/LiteDraggableHeader.svelte.d.ts +15 -0
  44. package/dist/components/advanced/LiteDrawerForm.svelte +42 -0
  45. package/dist/components/advanced/LiteDrawerForm.svelte.d.ts +16 -0
  46. package/dist/components/advanced/LiteInlineEdit.svelte +32 -0
  47. package/dist/components/advanced/LiteInlineEdit.svelte.d.ts +15 -0
  48. package/dist/components/advanced/LiteModalForm.svelte +44 -0
  49. package/dist/components/advanced/LiteModalForm.svelte.d.ts +17 -0
  50. package/dist/components/advanced/LiteToast.svelte +34 -0
  51. package/dist/components/advanced/LiteToast.svelte.d.ts +14 -0
  52. package/dist/components/advanced/LiteUndoableNotification.svelte +25 -0
  53. package/dist/components/advanced/LiteUndoableNotification.svelte.d.ts +13 -0
  54. package/dist/components/advanced/LiteVirtualTable.svelte +44 -0
  55. package/dist/components/advanced/LiteVirtualTable.svelte.d.ts +20 -0
  56. package/dist/components/advanced/index.js +8 -0
  57. package/dist/components/buttons/LiteCloneButton.svelte +33 -0
  58. package/dist/components/buttons/LiteCloneButton.svelte.d.ts +11 -0
  59. package/dist/components/buttons/LiteCreateButton.svelte +31 -0
  60. package/dist/components/buttons/LiteCreateButton.svelte.d.ts +10 -0
  61. package/dist/components/buttons/LiteDeleteButton.svelte +57 -0
  62. package/dist/components/buttons/LiteDeleteButton.svelte.d.ts +12 -0
  63. package/dist/components/buttons/LiteEditButton.svelte +33 -0
  64. package/dist/components/buttons/LiteEditButton.svelte.d.ts +11 -0
  65. package/dist/components/buttons/LiteExportButton.svelte +31 -0
  66. package/dist/components/buttons/LiteExportButton.svelte.d.ts +10 -0
  67. package/dist/components/buttons/LiteImportButton.svelte +50 -0
  68. package/dist/components/buttons/LiteImportButton.svelte.d.ts +10 -0
  69. package/dist/components/buttons/LiteListButton.svelte +31 -0
  70. package/dist/components/buttons/LiteListButton.svelte.d.ts +10 -0
  71. package/dist/components/buttons/LiteRefreshButton.svelte +34 -0
  72. package/dist/components/buttons/LiteRefreshButton.svelte.d.ts +8 -0
  73. package/dist/components/buttons/LiteSaveButton.svelte +27 -0
  74. package/dist/components/buttons/LiteSaveButton.svelte.d.ts +8 -0
  75. package/dist/components/buttons/LiteShowButton.svelte +33 -0
  76. package/dist/components/buttons/LiteShowButton.svelte.d.ts +11 -0
  77. package/dist/components/buttons/index.js +10 -0
  78. package/dist/components/fields/LiteBooleanField.svelte +42 -0
  79. package/dist/components/fields/LiteBooleanField.svelte.d.ts +10 -0
  80. package/dist/components/fields/LiteDateField.svelte +51 -0
  81. package/dist/components/fields/LiteDateField.svelte.d.ts +10 -0
  82. package/dist/components/fields/LiteEmailField.svelte +41 -0
  83. package/dist/components/fields/LiteEmailField.svelte.d.ts +10 -0
  84. package/dist/components/fields/LiteFileField.svelte +59 -0
  85. package/dist/components/fields/LiteFileField.svelte.d.ts +10 -0
  86. package/dist/components/fields/LiteImageField.svelte +57 -0
  87. package/dist/components/fields/LiteImageField.svelte.d.ts +10 -0
  88. package/dist/components/fields/LiteJsonField.svelte +43 -0
  89. package/dist/components/fields/LiteJsonField.svelte.d.ts +10 -0
  90. package/dist/components/fields/LiteMarkdownField.svelte +33 -0
  91. package/dist/components/fields/LiteMarkdownField.svelte.d.ts +10 -0
  92. package/dist/components/fields/LiteMultiSelectField.svelte +57 -0
  93. package/dist/components/fields/LiteMultiSelectField.svelte.d.ts +10 -0
  94. package/dist/components/fields/LiteNumberField.svelte +35 -0
  95. package/dist/components/fields/LiteNumberField.svelte.d.ts +10 -0
  96. package/dist/components/fields/LiteRelationField.svelte +67 -0
  97. package/dist/components/fields/LiteRelationField.svelte.d.ts +10 -0
  98. package/dist/components/fields/LiteRichTextField.svelte +44 -0
  99. package/dist/components/fields/LiteRichTextField.svelte.d.ts +10 -0
  100. package/dist/components/fields/LiteSelectField.svelte +47 -0
  101. package/dist/components/fields/LiteSelectField.svelte.d.ts +10 -0
  102. package/dist/components/fields/LiteTagField.svelte +44 -0
  103. package/dist/components/fields/LiteTagField.svelte.d.ts +10 -0
  104. package/dist/components/fields/LiteTextField.svelte +35 -0
  105. package/dist/components/fields/LiteTextField.svelte.d.ts +10 -0
  106. package/dist/components/fields/LiteUrlField.svelte +52 -0
  107. package/dist/components/fields/LiteUrlField.svelte.d.ts +10 -0
  108. package/dist/components/fields/index.js +15 -0
  109. package/dist/components/layout/LiteAuthenticated.svelte +23 -0
  110. package/dist/components/layout/LiteAuthenticated.svelte.d.ts +10 -0
  111. package/dist/components/layout/LiteCanAccess.svelte +27 -0
  112. package/dist/components/layout/LiteCanAccess.svelte.d.ts +10 -0
  113. package/dist/components/layout/LiteCatchAllNavigate.svelte +20 -0
  114. package/dist/components/layout/LiteCatchAllNavigate.svelte.d.ts +7 -0
  115. package/dist/components/layout/LiteErrorBoundary.svelte +20 -0
  116. package/dist/components/layout/LiteErrorBoundary.svelte.d.ts +13 -0
  117. package/dist/components/layout/LiteErrorComponent.svelte +37 -0
  118. package/dist/components/layout/LiteErrorComponent.svelte.d.ts +9 -0
  119. package/dist/components/layout/LiteHeader.svelte +19 -0
  120. package/dist/components/layout/LiteHeader.svelte.d.ts +8 -0
  121. package/dist/components/layout/LiteNavigateToResource.svelte +25 -0
  122. package/dist/components/layout/LiteNavigateToResource.svelte.d.ts +7 -0
  123. package/dist/components/layout/LiteSidebar.svelte +93 -0
  124. package/dist/components/layout/LiteSidebar.svelte.d.ts +12 -0
  125. package/dist/components/layout/index.js +8 -0
  126. package/dist/components/pages/LiteCreatePage.svelte +39 -0
  127. package/dist/components/pages/LiteCreatePage.svelte.d.ts +10 -0
  128. package/dist/components/pages/LiteEditPage.svelte +54 -0
  129. package/dist/components/pages/LiteEditPage.svelte.d.ts +12 -0
  130. package/dist/components/pages/LiteForgotPasswordPage.svelte +60 -0
  131. package/dist/components/pages/LiteForgotPasswordPage.svelte.d.ts +11 -0
  132. package/dist/components/pages/LiteListPage.svelte +81 -0
  133. package/dist/components/pages/LiteListPage.svelte.d.ts +20 -0
  134. package/dist/components/pages/LiteProfilePage.svelte +61 -0
  135. package/dist/components/pages/LiteProfilePage.svelte.d.ts +14 -0
  136. package/dist/components/pages/LiteRegisterPage.svelte +63 -0
  137. package/dist/components/pages/LiteRegisterPage.svelte.d.ts +10 -0
  138. package/dist/components/pages/LiteShowPage.svelte +61 -0
  139. package/dist/components/pages/LiteShowPage.svelte.d.ts +11 -0
  140. package/dist/components/pages/LiteUpdatePasswordPage.svelte +51 -0
  141. package/dist/components/pages/LiteUpdatePasswordPage.svelte.d.ts +9 -0
  142. package/dist/components/pages/index.js +8 -0
  143. package/dist/components/widgets/LiteAnomalyBadge.svelte +40 -0
  144. package/dist/components/widgets/LiteAnomalyBadge.svelte.d.ts +15 -0
  145. package/dist/components/widgets/LiteBarChart.svelte +45 -0
  146. package/dist/components/widgets/LiteBarChart.svelte.d.ts +17 -0
  147. package/dist/components/widgets/LiteInsightCard.svelte +31 -0
  148. package/dist/components/widgets/LiteInsightCard.svelte.d.ts +13 -0
  149. package/dist/components/widgets/LiteLineChart.svelte +48 -0
  150. package/dist/components/widgets/LiteLineChart.svelte.d.ts +17 -0
  151. package/dist/components/widgets/LitePieChart.svelte +44 -0
  152. package/dist/components/widgets/LitePieChart.svelte.d.ts +17 -0
  153. package/dist/components/widgets/index.js +5 -0
  154. package/dist/enhance.js +112 -0
  155. package/dist/index.d.ts +27 -0
  156. package/{src/index.ts → dist/index.js} +3 -26
  157. package/dist/lite.css +817 -0
  158. package/dist/schema-generator.d.ts +29 -0
  159. package/dist/schema-generator.js +226 -0
  160. package/dist/security.d.ts +14 -0
  161. package/dist/security.js +59 -0
  162. package/dist/server-adapter.d.ts +111 -0
  163. package/dist/server-adapter.js +422 -0
  164. package/package.json +55 -18
  165. package/src/schema-generator.ts +0 -147
  166. package/src/server-adapter.ts +0 -307
  167. /package/{src/components/advanced/index.ts → dist/components/advanced/index.d.ts} +0 -0
  168. /package/{src/components/buttons/index.ts → dist/components/buttons/index.d.ts} +0 -0
  169. /package/{src/components/fields/index.ts → dist/components/fields/index.d.ts} +0 -0
  170. /package/{src/components/layout/index.ts → dist/components/layout/index.d.ts} +0 -0
  171. /package/{src/components/pages/index.ts → dist/components/pages/index.d.ts} +0 -0
  172. /package/{src/components/widgets/index.ts → dist/components/widgets/index.d.ts} +0 -0
@@ -1,307 +0,0 @@
1
- /**
2
- * @svadmin/lite — Server Adapter
3
- *
4
- * Bridges @svadmin/core DataProvider into SvelteKit server loaders and form actions.
5
- * All data fetching happens on the server — zero client-side JS required.
6
- */
7
- import type {
8
- DataProvider, AuthProvider,
9
- ResourceDefinition, FieldDefinition,
10
- Sort, Filter,
11
- } from '@svadmin/core';
12
- import { redirect, isRedirect, type RequestEvent } from '@sveltejs/kit';
13
-
14
- // ─── List Loader ──────────────────────────────────────────────
15
-
16
- export interface ListLoaderResult {
17
- records: Record<string, unknown>[];
18
- total: number;
19
- page: number;
20
- pageSize: number;
21
- totalPages: number;
22
- sort?: string;
23
- order?: 'asc' | 'desc';
24
- search?: string;
25
- resource: ResourceDefinition;
26
- }
27
-
28
- /**
29
- * Creates a SvelteKit `load` function that fetches a resource list
30
- * via the DataProvider. All state is driven by URL search params.
31
- */
32
- export function createListLoader(
33
- dp: DataProvider,
34
- resource: ResourceDefinition,
35
- ) {
36
- return async ({ url }: { url: URL }): Promise<ListLoaderResult> => {
37
- const page = Math.max(1, Number(url.searchParams.get('page')) || 1);
38
- const pageSize = resource.pageSize ?? 20;
39
- const sort = url.searchParams.get('sort') ?? undefined;
40
- const order = (url.searchParams.get('order') as 'asc' | 'desc') ?? 'asc';
41
- const search = url.searchParams.get('q') ?? undefined;
42
-
43
- const sorters: Sort[] = sort ? [{ field: sort, order }] :
44
- resource.defaultSort ? [resource.defaultSort] : [];
45
-
46
- const filters: Filter[] = [];
47
- if (search) {
48
- const searchable = resource.fields.find((f: FieldDefinition) => f.searchable);
49
- if (searchable) {
50
- filters.push({ field: searchable.key, operator: 'contains', value: search });
51
- }
52
- }
53
-
54
- const result = await dp.getList({
55
- resource: resource.name,
56
- pagination: { current: page, pageSize },
57
- sorters,
58
- filters,
59
- });
60
-
61
- return {
62
- records: result.data as Record<string, unknown>[],
63
- total: result.total,
64
- page,
65
- pageSize,
66
- totalPages: Math.ceil(result.total / pageSize),
67
- sort,
68
- order,
69
- search,
70
- resource,
71
- };
72
- };
73
- }
74
-
75
- // ─── Detail Loader ────────────────────────────────────────────
76
-
77
- export function createDetailLoader(
78
- dp: DataProvider,
79
- resource: ResourceDefinition,
80
- ) {
81
- return async ({ params }: { params: { id: string } }) => {
82
- const result = await dp.getOne({
83
- resource: resource.name,
84
- id: params.id,
85
- });
86
- return { record: result.data as Record<string, unknown>, resource };
87
- };
88
- }
89
-
90
- // ─── CRUD Form Actions ────────────────────────────────────────
91
-
92
- /**
93
- * Creates SvelteKit form actions for create / update / delete.
94
- * Works with standard `<form method="POST">` submissions — no JS needed.
95
- */
96
- export function createCrudActions(
97
- dp: DataProvider,
98
- resource: ResourceDefinition,
99
- ) {
100
- const pk = resource.primaryKey ?? 'id';
101
-
102
- return {
103
- create: async ({ request }: RequestEvent) => {
104
- const formData = await request.formData();
105
- const variables = formDataToObject(formData, resource.fields);
106
- try {
107
- const result = await dp.create({ resource: resource.name, variables });
108
- return { success: true, id: (result.data as Record<string, unknown>)[pk] };
109
- } catch (e) {
110
- if (isRedirect(e)) throw e;
111
- return { success: false, error: (e as Error).message, values: variables };
112
- }
113
- },
114
-
115
- update: async ({ request }: RequestEvent) => {
116
- const formData = await request.formData();
117
- const id = formData.get('_id') as string;
118
- formData.delete('_id');
119
- const variables = formDataToObject(formData, resource.fields);
120
- try {
121
- await dp.update({ resource: resource.name, id, variables });
122
- return { success: true };
123
- } catch (e) {
124
- if (isRedirect(e)) throw e;
125
- return { success: false, error: (e as Error).message, values: variables };
126
- }
127
- },
128
-
129
- delete: async ({ request }: RequestEvent) => {
130
- const formData = await request.formData();
131
- const id = formData.get('id') as string;
132
- const redirectTo = formData.get('redirect') as string | undefined;
133
- try {
134
- await dp.deleteOne({ resource: resource.name, id });
135
- if (redirectTo) throw redirect(303, redirectTo);
136
- return { success: true };
137
- } catch (e) {
138
- if (isRedirect(e)) throw e;
139
- return { success: false, error: (e as Error).message };
140
- }
141
- },
142
- };
143
- }
144
-
145
- // ─── Auth Helpers ─────────────────────────────────────────────
146
-
147
- /**
148
- * Creates a SvelteKit server hook that checks auth via AuthProvider
149
- * and redirects unauthenticated users to a login page.
150
- */
151
- export function createAuthGuard(
152
- authProvider: AuthProvider,
153
- loginPath = '/lite/login',
154
- ) {
155
- return async ({ event, resolve }: { event: RequestEvent; resolve: (event: RequestEvent) => Promise<Response> }) => {
156
- // Skip auth check for the login page itself
157
- if (event.url.pathname === loginPath) {
158
- return resolve(event);
159
- }
160
-
161
- // Local Lite Session Verify
162
- const session = event.cookies.get('svadmin-session');
163
- if (!session) {
164
- return new Response(null, {
165
- status: 302,
166
- headers: { Location: loginPath },
167
- });
168
- }
169
-
170
- try {
171
- const check = await authProvider.check();
172
- if (!check.authenticated) {
173
- event.cookies.delete('svadmin-session', { path: '/' });
174
- return new Response(null, {
175
- status: 302,
176
- headers: { Location: loginPath },
177
- });
178
- }
179
- } catch {
180
- event.cookies.delete('svadmin-session', { path: '/' });
181
- return new Response(null, {
182
- status: 302,
183
- headers: { Location: loginPath },
184
- });
185
- }
186
- return resolve(event);
187
- };
188
- }
189
-
190
- /**
191
- * Creates login/logout form actions using AuthProvider.
192
- */
193
- export function createAuthActions(authProvider: AuthProvider) {
194
- return {
195
- login: async ({ request, cookies }: RequestEvent) => {
196
- const formData = await request.formData();
197
- const params = Object.fromEntries(formData);
198
- try {
199
- const result = await authProvider.login(params);
200
- if (result.success) {
201
- // Store a session indicator in a cookie
202
- cookies.set('svadmin-session', 'active', {
203
- path: '/',
204
- httpOnly: true,
205
- sameSite: 'lax',
206
- maxAge: 60 * 60 * 24 * 7, // 7 days
207
- });
208
- throw redirect(303, result.redirectTo ?? '/lite');
209
- }
210
- return { success: false, error: result.error?.message ?? 'Login failed' };
211
- } catch (e) {
212
- if (isRedirect(e)) throw e;
213
- return { success: false, error: (e as Error).message };
214
- }
215
- },
216
-
217
- logout: async ({ cookies }: RequestEvent) => {
218
- try { await authProvider.logout(); } catch { /* ignore */ }
219
- cookies.delete('svadmin-session', { path: '/' });
220
- return { success: true };
221
- },
222
- };
223
- }
224
-
225
- // ─── UA Detection ─────────────────────────────────────────────
226
-
227
- /**
228
- * Detects legacy browsers (IE11) from the User-Agent header.
229
- */
230
- export function isLegacyBrowser(userAgent: string): boolean {
231
- return /MSIE|Trident|rv:11/.test(userAgent);
232
- }
233
-
234
- /**
235
- * Creates a SvelteKit handle hook that auto-redirects legacy browsers to /lite/.
236
- */
237
- export function createLegacyRedirectHook(litePrefix = '/lite') {
238
- return async ({ event, resolve }: { event: RequestEvent; resolve: (event: RequestEvent) => Promise<Response> }) => {
239
- const ua = event.request.headers.get('user-agent') ?? '';
240
- if (isLegacyBrowser(ua) && !event.url.pathname.startsWith(litePrefix)) {
241
- return new Response(null, {
242
- status: 302,
243
- headers: { Location: `${litePrefix}${event.url.pathname}` },
244
- });
245
- }
246
- return resolve(event);
247
- };
248
- }
249
-
250
- // ─── Utilities ────────────────────────────────────────────────
251
-
252
- function formDataToObject(
253
- formData: FormData,
254
- fields: FieldDefinition[],
255
- ): Record<string, unknown> {
256
- const obj: Record<string, unknown> = {};
257
- for (const field of fields) {
258
- if (field.showInForm === false) continue;
259
-
260
- // Handle array types (like multiselect)
261
- if (field.type === 'multiselect') {
262
- const values = formData.getAll(field.key);
263
- if (values.length > 0) {
264
- obj[field.key] = values.map(v => String(v));
265
- }
266
- continue;
267
- }
268
-
269
- const raw = formData.get(field.key);
270
- if (raw === null) {
271
- if (field.type === 'boolean') obj[field.key] = false;
272
- continue;
273
- }
274
-
275
- // Don't coerce File objects, but ignore empty native file inputs
276
- if (raw instanceof File) {
277
- if (raw.size > 0 && raw.name !== '') {
278
- obj[field.key] = raw;
279
- }
280
- continue;
281
- }
282
-
283
- const strRaw = String(raw);
284
-
285
- switch (field.type) {
286
- case 'number':
287
- obj[field.key] = strRaw === '' ? null : Number(strRaw);
288
- break;
289
- case 'boolean':
290
- obj[field.key] = strRaw === 'on' || strRaw === 'true' || strRaw === '1';
291
- break;
292
- case 'tags':
293
- obj[field.key] = strRaw ? strRaw.split(',').map(s => s.trim()).filter(Boolean) : [];
294
- break;
295
- case 'json':
296
- try {
297
- obj[field.key] = strRaw ? JSON.parse(strRaw) : null;
298
- } catch {
299
- obj[field.key] = strRaw; // Let Zod handle validation errors
300
- }
301
- break;
302
- default:
303
- obj[field.key] = strRaw;
304
- }
305
- }
306
- return obj;
307
- }