@kyro-cms/admin 0.3.2 → 0.3.4

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 (242) hide show
  1. package/dist/EditorClient-XEUOVAAC.js +466 -0
  2. package/dist/EditorClient-XEUOVAAC.js.map +1 -0
  3. package/dist/EditorClient-YLCGVDXY.cjs +468 -0
  4. package/dist/EditorClient-YLCGVDXY.cjs.map +1 -0
  5. package/dist/chunk-7KPIUCGT.js +384 -0
  6. package/dist/chunk-7KPIUCGT.js.map +1 -0
  7. package/dist/chunk-GOACG6R7.cjs +473 -0
  8. package/dist/chunk-GOACG6R7.cjs.map +1 -0
  9. package/dist/index.cjs +14861 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.css +1661 -0
  12. package/dist/index.css.map +1 -0
  13. package/dist/index.d.ts +563 -0
  14. package/dist/index.js +14784 -0
  15. package/dist/index.js.map +1 -0
  16. package/package.json +19 -19
  17. package/src/components/ActionBar.tsx +7 -43
  18. package/src/components/Admin.tsx +138 -277
  19. package/src/components/ApiKeysManager.tsx +428 -419
  20. package/src/components/AuditLogsPage.tsx +35 -39
  21. package/src/components/AuthBridge.tsx +51 -0
  22. package/src/components/AutoForm.tsx +495 -1230
  23. package/src/components/BrandingHub.tsx +18 -19
  24. package/src/components/BulkActionsBar.tsx +1 -1
  25. package/src/components/CreateView.tsx +22 -36
  26. package/src/components/Dashboard.tsx +60 -84
  27. package/src/components/DetailView.tsx +113 -91
  28. package/src/components/DeveloperCenter.tsx +200 -198
  29. package/src/components/FieldRenderer.tsx +206 -0
  30. package/src/components/GraphQLPlayground.tsx +340 -480
  31. package/src/components/ListView.tsx +828 -254
  32. package/src/components/LoginPage.tsx +3 -4
  33. package/src/components/MarketplaceManager.tsx +254 -0
  34. package/src/components/MediaGallery.tsx +856 -1192
  35. package/src/components/PluginsManager.tsx +277 -0
  36. package/src/components/RestPlayground.tsx +398 -560
  37. package/src/components/SessionsManager.tsx +211 -0
  38. package/src/components/Sidebar.astro +179 -151
  39. package/src/components/ThemeProvider.tsx +7 -161
  40. package/src/components/UserManagement.tsx +162 -146
  41. package/src/components/UserMenu.tsx +110 -0
  42. package/src/components/WebhookManager.tsx +305 -367
  43. package/src/components/blocks/AccordionBlock.tsx +4 -4
  44. package/src/components/blocks/ArrayBlock.tsx +3 -3
  45. package/src/components/blocks/BlockEditModal.tsx +8 -8
  46. package/src/components/blocks/BlockWrapper.tsx +61 -0
  47. package/src/components/blocks/ButtonBlock.tsx +4 -4
  48. package/src/components/blocks/ChildBlocksTree.tsx +23 -25
  49. package/src/components/blocks/CodeBlock.tsx +15 -15
  50. package/src/components/blocks/ColumnsBlock.tsx +6 -44
  51. package/src/components/blocks/DividerBlock.tsx +3 -3
  52. package/src/components/blocks/FileBlock.tsx +4 -4
  53. package/src/components/blocks/HeadingBlock.tsx +6 -38
  54. package/src/components/blocks/HeroBlock.tsx +4 -4
  55. package/src/components/blocks/ImageBlock.tsx +4 -4
  56. package/src/components/blocks/LinkBlock.tsx +4 -4
  57. package/src/components/blocks/ListBlock.tsx +3 -3
  58. package/src/components/blocks/ParagraphBlock.tsx +12 -42
  59. package/src/components/blocks/RelationshipBlock.tsx +4 -4
  60. package/src/components/blocks/RichTextBlock.tsx +4 -4
  61. package/src/components/blocks/VStackBlock.tsx +5 -37
  62. package/src/components/blocks/VideoBlock.tsx +4 -4
  63. package/src/components/blocks/types.ts +11 -0
  64. package/src/components/fields/AccordionField.tsx +1 -1
  65. package/src/components/fields/ArrayField.tsx +2 -2
  66. package/src/components/fields/ArrayLayout.tsx +93 -0
  67. package/src/components/fields/BlocksField.tsx +122 -111
  68. package/src/components/fields/ButtonField.tsx +1 -1
  69. package/src/components/fields/CheckboxField.tsx +14 -15
  70. package/src/components/fields/ChildrenField.tsx +2 -2
  71. package/src/components/fields/CodeField.tsx +3 -3
  72. package/src/components/fields/ColumnsField.tsx +2 -2
  73. package/src/components/fields/DateField.tsx +13 -26
  74. package/src/components/fields/EditorClient.tsx +26 -28
  75. package/src/components/fields/FieldLayout.tsx +52 -0
  76. package/src/components/fields/GroupLayout.tsx +35 -0
  77. package/src/components/fields/JSONField.tsx +7 -7
  78. package/src/components/fields/LinkField.tsx +1 -1
  79. package/src/components/fields/MarkdownField.tsx +1 -1
  80. package/src/components/fields/NumberField.tsx +13 -26
  81. package/src/components/fields/PortableTextField.tsx +4 -4
  82. package/src/components/fields/PortableTextRenderer.tsx +1 -1
  83. package/src/components/fields/RelationshipBlockField.tsx +31 -23
  84. package/src/components/fields/RelationshipField.tsx +14 -14
  85. package/src/components/fields/SelectField.tsx +17 -26
  86. package/src/components/fields/TabsLayout.tsx +69 -0
  87. package/src/components/fields/TextField.tsx +85 -38
  88. package/src/components/fields/UploadField.tsx +71 -41
  89. package/src/components/fields/VideoField.tsx +1 -1
  90. package/src/components/fields/extensions/blockComponents.tsx +2 -2
  91. package/src/components/fields/extensions/blocksStore.ts +207 -193
  92. package/src/components/fields/types.ts +22 -0
  93. package/src/components/layout/Layout.tsx +1 -1
  94. package/src/components/ui/ActionMenu.tsx +63 -0
  95. package/src/components/ui/Badge.tsx +59 -5
  96. package/src/components/ui/BlockDrawer.tsx +4 -5
  97. package/src/components/ui/CommandPalette.tsx +58 -36
  98. package/src/components/ui/CommandPaletteWrapper.tsx +18 -17
  99. package/src/components/ui/Dropdown.tsx +18 -16
  100. package/src/components/ui/EmptyState.tsx +25 -0
  101. package/src/components/ui/GlobalModal.tsx +49 -0
  102. package/src/components/ui/IconButton.tsx +44 -0
  103. package/src/components/ui/Modal.tsx +19 -20
  104. package/src/components/ui/PageHeader.tsx +158 -0
  105. package/src/components/ui/Pagination.tsx +61 -0
  106. package/src/components/ui/PromptModal.tsx +1 -1
  107. package/src/components/ui/SearchInput.tsx +57 -0
  108. package/src/components/ui/SeoPreview.tsx +31 -0
  109. package/src/components/ui/SessionModal.tsx +0 -0
  110. package/src/components/ui/SlidePanel.tsx +2 -0
  111. package/src/components/ui/Toast.tsx +65 -122
  112. package/src/components/ui/Toaster.tsx +18 -0
  113. package/src/components/ui/icons.tsx +112 -0
  114. package/src/components/users/UserDetail.tsx +290 -0
  115. package/src/components/users/UserForm.tsx +242 -0
  116. package/src/components/users/UsersList.tsx +338 -0
  117. package/src/env.d.ts +13 -13
  118. package/src/fields/index.ts +2 -1
  119. package/src/global.d.ts +7 -0
  120. package/src/hooks/data.ts +2 -9
  121. package/src/hooks/useAsyncData.ts +36 -0
  122. package/src/hooks/useAutoFormState.ts +527 -0
  123. package/src/hooks/useSelection.ts +49 -0
  124. package/src/hooks/useSession.ts +0 -0
  125. package/src/index.ts +11 -1
  126. package/src/integration.ts +86 -11
  127. package/src/kyro-cms.d.ts +209 -0
  128. package/src/layouts/AdminLayout.astro +128 -11
  129. package/src/layouts/AuthLayout.astro +21 -5
  130. package/src/lib/api.ts +175 -55
  131. package/src/lib/autoform-store.ts +435 -0
  132. package/src/lib/config.ts +82 -34
  133. package/src/lib/createRegistry.ts +29 -0
  134. package/src/lib/default-kyro-config.ts +4 -0
  135. package/src/lib/globals.ts +50 -0
  136. package/src/lib/media-utils.ts +18 -0
  137. package/src/lib/object-utils.ts +77 -0
  138. package/src/lib/paths.ts +61 -0
  139. package/src/lib/stores/index.ts +370 -0
  140. package/src/lib/types.ts +43 -0
  141. package/src/lib/useResourceManager.ts +105 -0
  142. package/src/pages/403.astro +67 -0
  143. package/src/pages/[collection]/[id].astro +14 -180
  144. package/src/pages/[collection]/index.astro +11 -6
  145. package/src/pages/api-explorer.astro +173 -0
  146. package/src/pages/audit/index.astro +2 -0
  147. package/src/pages/auth/login.astro +122 -0
  148. package/src/pages/auth/register.astro +167 -0
  149. package/src/pages/graphql-explorer.astro +59 -0
  150. package/src/pages/{admin/graphql.astro → graphql.astro} +51 -17
  151. package/src/pages/index.astro +577 -0
  152. package/src/pages/index_ALT.astro +3 -0
  153. package/src/pages/keys.astro +11 -0
  154. package/src/pages/marketplace.astro +11 -0
  155. package/src/pages/media.astro +3 -0
  156. package/src/pages/plugins.astro +8 -0
  157. package/src/pages/preview/[collection]/[id].astro +188 -123
  158. package/src/pages/rest-playground.astro +62 -0
  159. package/src/pages/roles/index.astro +183 -76
  160. package/src/pages/sessions.astro +8 -0
  161. package/src/pages/settings/[slug].astro +92 -114
  162. package/src/pages/settings/index.astro +5 -3
  163. package/src/pages/users/[id].astro +25 -154
  164. package/src/pages/users/index.astro +19 -130
  165. package/src/pages/users/new.astro +9 -86
  166. package/src/pages/webhooks.astro +11 -0
  167. package/src/routes.ts +80 -0
  168. package/src/styles/main.css +119 -79
  169. package/src/theme/tokens.ts +1 -0
  170. package/src/vite-env.d.ts +14 -0
  171. package/src/collections/auth/index.ts +0 -155
  172. package/src/collections/portfolio/index.ts +0 -343
  173. package/src/components/ApiExplorer.tsx +0 -325
  174. package/src/components/EnhancedListView.tsx +0 -889
  175. package/src/components/GraphQLExplorer.tsx +0 -675
  176. package/src/components/Icons.tsx +0 -23
  177. package/src/components/StatusBadge.tsx +0 -76
  178. package/src/lib/MediaService.ts +0 -541
  179. package/src/lib/auth/sqlite-adapter.ts +0 -319
  180. package/src/lib/dataStore.ts +0 -226
  181. package/src/lib/db/adapter.ts +0 -54
  182. package/src/lib/db/drizzle-mysql-adapter.ts +0 -194
  183. package/src/lib/db/drizzle-mysql-auth-adapter.ts +0 -327
  184. package/src/lib/db/drizzle-postgres-adapter.ts +0 -202
  185. package/src/lib/db/drizzle-postgres-auth-adapter.ts +0 -304
  186. package/src/lib/db/drizzle-sqlite-adapter.ts +0 -227
  187. package/src/lib/db/drizzle-sqlite-auth-adapter.ts +0 -548
  188. package/src/lib/db/index.ts +0 -449
  189. package/src/lib/db/mongodb-adapter.ts +0 -207
  190. package/src/lib/db/mongodb-auth-adapter.ts +0 -305
  191. package/src/lib/db/schema/mysql-auth.ts +0 -113
  192. package/src/lib/db/schema/mysql-content.ts +0 -20
  193. package/src/lib/db/schema/postgres-auth.ts +0 -116
  194. package/src/lib/db/schema/postgres-content.ts +0 -35
  195. package/src/lib/db/schema/postgres-media.ts +0 -52
  196. package/src/lib/db/schema/postgres-settings.ts +0 -11
  197. package/src/lib/db/schema/sqlite-auth.ts +0 -112
  198. package/src/lib/db/schema/sqlite-content.ts +0 -20
  199. package/src/lib/db/version-adapter.ts +0 -248
  200. package/src/lib/graphql/index.ts +0 -1
  201. package/src/lib/graphql/schema.ts +0 -443
  202. package/src/lib/rate-limit.ts +0 -267
  203. package/src/lib/storage.ts +0 -374
  204. package/src/lib/store.ts +0 -85
  205. package/src/middleware.ts +0 -177
  206. package/src/pages/admin/api-explorer.astro +0 -98
  207. package/src/pages/admin/graphql-explorer.astro +0 -40
  208. package/src/pages/admin/index.astro +0 -286
  209. package/src/pages/admin/keys.astro +0 -8
  210. package/src/pages/admin/rest-playground.astro +0 -44
  211. package/src/pages/admin/webhooks.astro +0 -8
  212. package/src/pages/api/[collection]/[id]/publish.ts +0 -52
  213. package/src/pages/api/[collection]/[id]/unpublish.ts +0 -42
  214. package/src/pages/api/[collection]/[id]/versions.ts +0 -66
  215. package/src/pages/api/[collection]/[id].ts +0 -213
  216. package/src/pages/api/[collection]/index.ts +0 -209
  217. package/src/pages/api/auth/[id].ts +0 -121
  218. package/src/pages/api/auth/audit-logs.ts +0 -57
  219. package/src/pages/api/auth/login.ts +0 -211
  220. package/src/pages/api/auth/logout.ts +0 -66
  221. package/src/pages/api/auth/me.ts +0 -36
  222. package/src/pages/api/auth/refresh.ts +0 -119
  223. package/src/pages/api/auth/register.ts +0 -188
  224. package/src/pages/api/auth/users.ts +0 -97
  225. package/src/pages/api/collections.ts +0 -59
  226. package/src/pages/api/globals/[slug].ts +0 -42
  227. package/src/pages/api/graphql.ts +0 -90
  228. package/src/pages/api/health.ts +0 -426
  229. package/src/pages/api/keys/[id].ts +0 -26
  230. package/src/pages/api/keys/index.ts +0 -75
  231. package/src/pages/api/media/[id].ts +0 -309
  232. package/src/pages/api/media/folders.ts +0 -609
  233. package/src/pages/api/media/index.ts +0 -146
  234. package/src/pages/api/media/resize.ts +0 -267
  235. package/src/pages/api/search.ts +0 -82
  236. package/src/pages/api/slug-availability.ts +0 -70
  237. package/src/pages/api/storage-config.ts +0 -20
  238. package/src/pages/api/storage-status.ts +0 -206
  239. package/src/pages/api/upload.ts +0 -334
  240. package/src/pages/api/webhooks/index.ts +0 -71
  241. package/src/pages/login.astro +0 -82
  242. package/src/pages/register.astro +0 -102
@@ -1,213 +0,0 @@
1
- import type { APIRoute } from "astro";
2
- import { dataStore } from "../../../lib/dataStore";
3
- import { collections } from "../../../lib/config";
4
- import { getAuthAdapter } from "../../../lib/db";
5
-
6
- dataStore.initialize(collections);
7
-
8
- const AUTH_COLLECTIONS = ["users", "roles", "audit_logs"];
9
-
10
- async function getAuthAdapterLocal() {
11
- return await getAuthAdapter();
12
- }
13
-
14
- export const GET: APIRoute = async ({ params }) => {
15
- const collection = params.collection as string;
16
- const id = params.id as string;
17
-
18
- if (AUTH_COLLECTIONS.includes(collection)) {
19
- const adapter = await getAuthAdapterLocal();
20
-
21
- if (collection === "users") {
22
- const user = await adapter.findUserById(id);
23
- if (!user) {
24
- return new Response(JSON.stringify({ error: "User not found" }), {
25
- status: 404,
26
- headers: { "Content-Type": "application/json" },
27
- });
28
- }
29
- const { passwordHash, ...safeUser } = user;
30
- return new Response(JSON.stringify({ data: safeUser }), {
31
- status: 200,
32
- headers: { "Content-Type": "application/json" },
33
- });
34
- }
35
-
36
- if (collection === "roles") {
37
- const roles = await adapter.findUserRoles();
38
- const role = roles.find((r) => r.id === id);
39
- if (!role) {
40
- return new Response(JSON.stringify({ error: "Role not found" }), {
41
- status: 404,
42
- headers: { "Content-Type": "application/json" },
43
- });
44
- }
45
- return new Response(JSON.stringify({ data: role }), {
46
- status: 200,
47
- headers: { "Content-Type": "application/json" },
48
- });
49
- }
50
-
51
- return new Response(
52
- JSON.stringify({ error: `Collection ${collection} not supported` }),
53
- { status: 404, headers: { "Content-Type": "application/json" } },
54
- );
55
- }
56
-
57
- try {
58
- let doc = await dataStore.findById(collection, id);
59
- if (!doc) {
60
- const allDocs = (
61
- await dataStore.find(collection, { page: 1, limit: 1000 })
62
- ).docs;
63
- doc = (allDocs || []).find((d: any) => d.slug === id) || null;
64
- }
65
- if (!doc) {
66
- return new Response(JSON.stringify({ error: "Document not found" }), {
67
- status: 404,
68
- });
69
- }
70
- return new Response(JSON.stringify({ data: doc }), {
71
- status: 200,
72
- headers: { "Content-Type": "application/json" },
73
- });
74
- } catch (error) {
75
- return new Response(JSON.stringify({ error: "Failed to fetch document" }), {
76
- status: 500,
77
- });
78
- }
79
- };
80
-
81
- export const PATCH: APIRoute = async ({ params, request }) => {
82
- const collection = params.collection as string;
83
- const id = params.id as string;
84
-
85
- if (AUTH_COLLECTIONS.includes(collection)) {
86
- const adapter = await getAuthAdapterLocal();
87
- const body = await request.json();
88
-
89
- if (collection === "users") {
90
- const existing = await adapter.findUserById(id);
91
- if (!existing) {
92
- return new Response(JSON.stringify({ error: "User not found" }), {
93
- status: 404,
94
- headers: { "Content-Type": "application/json" },
95
- });
96
- }
97
-
98
- const updateData: Record<string, unknown> = {};
99
- if (body.email !== undefined) updateData.email = body.email;
100
- if (body.name !== undefined) updateData.name = body.name;
101
- if (body.role !== undefined) updateData.role = body.role;
102
- if (body.password) {
103
- updateData.passwordHash = await adapter.hashPassword(body.password);
104
- }
105
-
106
- const user = await adapter.updateUser(id, updateData);
107
- if (!user) {
108
- return new Response(
109
- JSON.stringify({ error: "Failed to update user" }),
110
- {
111
- status: 500,
112
- },
113
- );
114
- }
115
-
116
- const { passwordHash, ...safeUser } = user;
117
- return new Response(JSON.stringify({ data: safeUser }), {
118
- status: 200,
119
- headers: { "Content-Type": "application/json" },
120
- });
121
- }
122
-
123
- return new Response(
124
- JSON.stringify({
125
- error: `Collection ${collection} does not support PATCH`,
126
- }),
127
- { status: 405, headers: { "Content-Type": "application/json" } },
128
- );
129
- }
130
-
131
- try {
132
- const body = await request.json();
133
- const versionStatus =
134
- body.status === "draft"
135
- ? "draft"
136
- : body.status === "published"
137
- ? "published"
138
- : undefined;
139
- const changeDescription = body._changeDescription;
140
- const { _changeDescription, ...cleanBody } = body;
141
-
142
- const doc = await dataStore.update(collection, id, cleanBody, {
143
- versionStatus,
144
- changeDescription,
145
- });
146
- if (!doc) {
147
- return new Response(JSON.stringify({ error: "Document not found" }), {
148
- status: 404,
149
- });
150
- }
151
- return new Response(JSON.stringify({ data: doc }), {
152
- status: 200,
153
- headers: { "Content-Type": "application/json" },
154
- });
155
- } catch (error) {
156
- return new Response(
157
- JSON.stringify({ error: "Failed to update document" }),
158
- {
159
- status: 500,
160
- },
161
- );
162
- }
163
- };
164
-
165
- export const DELETE: APIRoute = async ({ params }) => {
166
- const collection = params.collection as string;
167
- const id = params.id as string;
168
-
169
- if (AUTH_COLLECTIONS.includes(collection)) {
170
- const adapter = await getAuthAdapterLocal();
171
-
172
- if (collection === "users") {
173
- const existing = await adapter.findUserById(id);
174
- if (!existing) {
175
- return new Response(JSON.stringify({ error: "User not found" }), {
176
- status: 404,
177
- });
178
- }
179
- await adapter.deleteUser(id);
180
- return new Response(JSON.stringify({ success: true }), {
181
- status: 200,
182
- headers: { "Content-Type": "application/json" },
183
- });
184
- }
185
-
186
- return new Response(
187
- JSON.stringify({
188
- error: `Collection ${collection} does not support DELETE`,
189
- }),
190
- { status: 405, headers: { "Content-Type": "application/json" } },
191
- );
192
- }
193
-
194
- try {
195
- const success = await dataStore.delete(collection, id);
196
- if (!success) {
197
- return new Response(JSON.stringify({ error: "Document not found" }), {
198
- status: 404,
199
- });
200
- }
201
- return new Response(JSON.stringify({ success: true }), {
202
- status: 200,
203
- headers: { "Content-Type": "application/json" },
204
- });
205
- } catch (error) {
206
- return new Response(
207
- JSON.stringify({ error: "Failed to delete document" }),
208
- {
209
- status: 500,
210
- },
211
- );
212
- }
213
- };
@@ -1,209 +0,0 @@
1
- import type { APIRoute } from "astro";
2
- import { dataStore } from "../../../lib/dataStore";
3
- import { collections } from "../../../lib/config";
4
- import { getAuthAdapter } from "../../../lib/db";
5
-
6
- dataStore.initialize(collections);
7
-
8
- const initSeedData = async () => {
9
- const store = dataStore;
10
-
11
- // Seed products (for ecommerce)
12
- if (!(await store.isSeeded("products"))) {
13
- await store.seed("products", [
14
- {
15
- title: "Kyro Stealth Hoodie",
16
- slug: "kyro-stealth-hoodie",
17
- sku: "KSH-001",
18
- price: 89.99,
19
- status: "active",
20
- inventory: 50,
21
- description: "Premium heavy-weight cotton hoodie.",
22
- category: "apparel-1",
23
- },
24
- ]);
25
- }
26
-
27
- // Seed pages
28
- if (!(await store.isSeeded("pages"))) {
29
- await store.seed("pages", [
30
- {
31
- title: "About Us",
32
- slug: "about",
33
- content: "<p>Welcome to our about page!</p>",
34
- status: "published",
35
- },
36
- {
37
- title: "Contact",
38
- slug: "contact",
39
- content: "<p>Get in touch with us!</p>",
40
- status: "published",
41
- },
42
- ]);
43
- }
44
-
45
- // Seed posts (for blog content)
46
- if (!(await store.isSeeded("posts"))) {
47
- await store.seed("posts", [
48
- {
49
- title: "Welcome to Kyro CMS",
50
- slug: "welcome-to-kyro-cms",
51
- content:
52
- "<p>Welcome to your new CMS! This is your first blog post.</p>",
53
- excerpt: "Welcome to your new CMS!",
54
- status: "published",
55
- publishedAt: new Date().toISOString(),
56
- },
57
- ]);
58
- }
59
-
60
- // Seed categories
61
- if (!(await store.isSeeded("categories"))) {
62
- await store.seed("categories", [
63
- { title: "General", slug: "general", description: "General category" },
64
- { title: "News", slug: "news", description: "News and announcements" },
65
- { title: "Updates", slug: "updates", description: "Product updates" },
66
- ]);
67
- }
68
-
69
- // Seed navigation
70
- if (!(await store.isSeeded("navigation"))) {
71
- await store.seed("navigation", [
72
- { label: "Home", url: "/", location: "header", order: 1 },
73
- { label: "Blog", url: "/blog", location: "header", order: 2 },
74
- { label: "About", url: "/about", location: "header", order: 3 },
75
- { label: "Contact", url: "/contact", location: "header", order: 4 },
76
- { label: "Privacy", url: "/privacy", location: "footer", order: 1 },
77
- { label: "Terms", url: "/terms", location: "footer", order: 2 },
78
- ]);
79
- }
80
-
81
- // Seed site settings
82
- const siteGlobal = await store.findGlobal("site-settings");
83
- if (!siteGlobal.siteName) {
84
- await store.seedGlobal("site-settings", {
85
- siteName: "",
86
- siteDescription: "",
87
- allowRegistration: true,
88
- });
89
- }
90
-
91
- // Seed SEO settings
92
- const seoGlobal = await store.findGlobal("seo-settings");
93
- if (!seoGlobal.defaultTitle) {
94
- await store.seedGlobal("seo-settings", {
95
- defaultTitle: "",
96
- titleTemplate: "%s",
97
- defaultDescription: "",
98
- });
99
- }
100
- };
101
-
102
- initSeedData().catch(console.error);
103
-
104
- const AUTH_COLLECTIONS = ["users", "roles", "audit_logs"];
105
-
106
- async function getAuthAdapterLocal() {
107
- return await getAuthAdapter();
108
- }
109
-
110
- export const GET: APIRoute = async ({ params, url }) => {
111
- const collection = params.collection as string;
112
- const page = parseInt(url.searchParams.get("page") || "1");
113
- const limit = parseInt(url.searchParams.get("limit") || "25");
114
-
115
- if (AUTH_COLLECTIONS.includes(collection)) {
116
- const adapter = await getAuthAdapterLocal();
117
-
118
- if (collection === "users") {
119
- const users = await adapter.findAllUsers();
120
- const safeUsers = users.map(({ passwordHash, ...user }) => user);
121
- return new Response(
122
- JSON.stringify({
123
- docs: safeUsers,
124
- totalDocs: safeUsers.length,
125
- page,
126
- limit,
127
- totalPages: 1,
128
- }),
129
- { status: 200, headers: { "Content-Type": "application/json" } },
130
- );
131
- }
132
-
133
- if (collection === "roles") {
134
- const roles = await adapter.findUserRoles();
135
- return new Response(
136
- JSON.stringify({
137
- docs: roles,
138
- totalDocs: roles.length,
139
- page,
140
- limit,
141
- totalPages: 1,
142
- }),
143
- { status: 200, headers: { "Content-Type": "application/json" } },
144
- );
145
- }
146
-
147
- if (collection === "audit_logs") {
148
- const offset = (page - 1) * limit;
149
- const { logs, total } = await adapter.findAuditLogs({
150
- limit,
151
- offset,
152
- });
153
- return new Response(
154
- JSON.stringify({
155
- docs: logs,
156
- totalDocs: total,
157
- page,
158
- limit,
159
- totalPages: Math.ceil(total / limit),
160
- }),
161
- { status: 200, headers: { "Content-Type": "application/json" } },
162
- );
163
- }
164
- }
165
-
166
- try {
167
- const result = await dataStore.find(collection, { page, limit });
168
- return new Response(JSON.stringify(result), {
169
- status: 200,
170
- headers: { "Content-Type": "application/json" },
171
- });
172
- } catch (error) {
173
- return new Response(
174
- JSON.stringify({
175
- error: "Failed to fetch documents",
176
- docs: [],
177
- totalDocs: 0,
178
- }),
179
- { status: 500, headers: { "Content-Type": "application/json" } },
180
- );
181
- }
182
- };
183
-
184
- export const POST: APIRoute = async ({ params, request }) => {
185
- const collection = params.collection as string;
186
-
187
- if (AUTH_COLLECTIONS.includes(collection)) {
188
- return new Response(
189
- JSON.stringify({
190
- error: `Collection ${collection} does not support POST`,
191
- }),
192
- { status: 405, headers: { "Content-Type": "application/json" } },
193
- );
194
- }
195
-
196
- try {
197
- const body = await request.json();
198
- const doc = await dataStore.create(collection, body);
199
- return new Response(JSON.stringify({ data: doc }), {
200
- status: 201,
201
- headers: { "Content-Type": "application/json" },
202
- });
203
- } catch (error) {
204
- return new Response(
205
- JSON.stringify({ error: "Failed to create document" }),
206
- { status: 500, headers: { "Content-Type": "application/json" } },
207
- );
208
- }
209
- };
@@ -1,121 +0,0 @@
1
- import type { APIRoute } from "astro";
2
- import { getAuthAdapter } from "../../../lib/db";
3
-
4
- export const GET: APIRoute = async ({ params }) => {
5
- const { id } = params;
6
- const adapter = await getAuthAdapter();
7
-
8
- try {
9
- const user = await adapter.findUserById(id!);
10
-
11
- if (!user) {
12
- return new Response(JSON.stringify({ error: "User not found" }), {
13
- status: 404,
14
- headers: { "Content-Type": "application/json" },
15
- });
16
- }
17
-
18
- return new Response(JSON.stringify({ data: user }), {
19
- status: 200,
20
- headers: { "Content-Type": "application/json" },
21
- });
22
- } catch (error) {
23
- console.error("Error fetching user:", error);
24
- return new Response(JSON.stringify({ error: "Failed to fetch user" }), {
25
- status: 500,
26
- headers: { "Content-Type": "application/json" },
27
- });
28
- }
29
- };
30
-
31
- export const PUT: APIRoute = async ({ params, request }) => {
32
- const { id } = params;
33
- const adapter = await getAuthAdapter();
34
-
35
- try {
36
- const body = await request.json();
37
- const { email, role } = body;
38
-
39
- const user = await adapter.updateUser(id!, {
40
- email,
41
- role,
42
- });
43
-
44
- if (!user) {
45
- return new Response(JSON.stringify({ error: "User not found" }), {
46
- status: 404,
47
- headers: { "Content-Type": "application/json" },
48
- });
49
- }
50
-
51
- return new Response(JSON.stringify({ data: user }), {
52
- status: 200,
53
- headers: { "Content-Type": "application/json" },
54
- });
55
- } catch (error) {
56
- console.error("Error updating user:", error);
57
- return new Response(JSON.stringify({ error: "Failed to update user" }), {
58
- status: 500,
59
- headers: { "Content-Type": "application/json" },
60
- });
61
- }
62
- };
63
-
64
- export const PATCH: APIRoute = async ({ params, request }) => {
65
- const { id } = params;
66
- const adapter = await getAuthAdapter();
67
-
68
- try {
69
- const body = await request.json();
70
- const { locked } = body;
71
-
72
- const user = await adapter.updateUser(id!, {
73
- locked,
74
- });
75
-
76
- if (!user) {
77
- return new Response(JSON.stringify({ error: "User not found" }), {
78
- status: 404,
79
- headers: { "Content-Type": "application/json" },
80
- });
81
- }
82
-
83
- return new Response(JSON.stringify({ data: user }), {
84
- status: 200,
85
- headers: { "Content-Type": "application/json" },
86
- });
87
- } catch (error) {
88
- console.error("Error setting user locked status:", error);
89
- return new Response(JSON.stringify({ error: "Failed to update user" }), {
90
- status: 500,
91
- headers: { "Content-Type": "application/json" },
92
- });
93
- }
94
- };
95
-
96
- export const DELETE: APIRoute = async ({ params }) => {
97
- const { id } = params;
98
- const adapter = await getAuthAdapter();
99
-
100
- try {
101
- const success = await adapter.deleteUser(id!);
102
-
103
- if (!success) {
104
- return new Response(JSON.stringify({ error: "User not found" }), {
105
- status: 404,
106
- headers: { "Content-Type": "application/json" },
107
- });
108
- }
109
-
110
- return new Response(JSON.stringify({ success: true }), {
111
- status: 200,
112
- headers: { "Content-Type": "application/json" },
113
- });
114
- } catch (error) {
115
- console.error("Error deleting user:", error);
116
- return new Response(JSON.stringify({ error: "Failed to delete user" }), {
117
- status: 500,
118
- headers: { "Content-Type": "application/json" },
119
- });
120
- }
121
- };
@@ -1,57 +0,0 @@
1
- import type { APIRoute } from "astro";
2
- import { getAuthAdapter } from "../../../lib/db";
3
-
4
- export const GET: APIRoute = async ({ url }) => {
5
- const page = parseInt(url.searchParams.get("page") || "1");
6
- const limit = parseInt(url.searchParams.get("limit") || "25");
7
- const action = url.searchParams.get("action") || "";
8
- const userId = url.searchParams.get("userId") || "";
9
- const successParam = url.searchParams.get("success");
10
- const resource = url.searchParams.get("resource") || "";
11
-
12
- try {
13
- const adapter = await getAuthAdapter();
14
- const offset = (page - 1) * limit;
15
-
16
- const { logs, total } = await adapter.findAuditLogs({
17
- limit,
18
- offset,
19
- action: action || undefined,
20
- userId: userId || undefined,
21
- resource: resource || undefined,
22
- success:
23
- successParam === "true"
24
- ? true
25
- : successParam === "false"
26
- ? false
27
- : undefined,
28
- } as Parameters<typeof adapter.findAuditLogs>[0]);
29
-
30
- return new Response(
31
- JSON.stringify({
32
- docs: logs,
33
- totalDocs: total,
34
- page,
35
- limit,
36
- totalPages: Math.ceil(total / limit),
37
- }),
38
- {
39
- status: 200,
40
- headers: { "Content-Type": "application/json" },
41
- },
42
- );
43
- } catch (error) {
44
- console.error("Error fetching audit logs:", error);
45
- return new Response(
46
- JSON.stringify({
47
- error: "Failed to fetch audit logs",
48
- docs: [],
49
- totalDocs: 0,
50
- }),
51
- {
52
- status: 500,
53
- headers: { "Content-Type": "application/json" },
54
- },
55
- );
56
- }
57
- };