@kyro-cms/admin 0.1.2

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 (102) hide show
  1. package/.astro/content.d.ts +154 -0
  2. package/.astro/settings.json +5 -0
  3. package/.astro/types.d.ts +2 -0
  4. package/astro.config.mjs +28 -0
  5. package/bun.lock +1374 -0
  6. package/dist/client/_astro/AdminLayout.DkDpng53.css +1 -0
  7. package/dist/client/_astro/AutoForm.3eJCmCJp.js +1 -0
  8. package/dist/client/_astro/client.DyczpTbx.js +9 -0
  9. package/dist/client/_astro/index.B02hbnpo.js +1 -0
  10. package/dist/client/fonts/Serotiva-Black.woff2 +0 -0
  11. package/dist/client/fonts/Serotiva-Bold.woff2 +0 -0
  12. package/dist/client/fonts/Serotiva-Medium.woff2 +0 -0
  13. package/dist/client/fonts/Serotiva-Regular.woff2 +0 -0
  14. package/dist/client/fonts/Serotiva-SemiBold.woff2 +0 -0
  15. package/dist/server/chunks/AdminLayout_D-_JeUqC.mjs +26 -0
  16. package/dist/server/chunks/_id__BzI_o0qT.mjs +50 -0
  17. package/dist/server/chunks/_id__Cd-jOuY3.mjs +238 -0
  18. package/dist/server/chunks/_id__DvbD--iR.mjs +992 -0
  19. package/dist/server/chunks/_id__vpVaEo16.mjs +128 -0
  20. package/dist/server/chunks/_virtual_astro_server-island-manifest_CQQ1F5PF.mjs +7 -0
  21. package/dist/server/chunks/_virtual_astro_session-driver_Bk3Q189E.mjs +4 -0
  22. package/dist/server/chunks/astro-component_Dbx3T2Nh.mjs +37 -0
  23. package/dist/server/chunks/audit-logs_DrnUMRvY.mjs +74 -0
  24. package/dist/server/chunks/config_CPXslElD.mjs +4221 -0
  25. package/dist/server/chunks/dataStore_Dl7cA2Qp.mjs +89 -0
  26. package/dist/server/chunks/index_CVqOkerS.mjs +2960 -0
  27. package/dist/server/chunks/index_CX8SQ4BF.mjs +55 -0
  28. package/dist/server/chunks/index_CYofDU51.mjs +58 -0
  29. package/dist/server/chunks/index_DdNRhuaM.mjs +55 -0
  30. package/dist/server/chunks/index_DupPvtIF.mjs +42 -0
  31. package/dist/server/chunks/index_YTS_M-B9.mjs +263 -0
  32. package/dist/server/chunks/index_YeCzuVps.mjs +53 -0
  33. package/dist/server/chunks/login_DLyqMRO8.mjs +93 -0
  34. package/dist/server/chunks/logout_CSbt5wea.mjs +50 -0
  35. package/dist/server/chunks/me_C04jlYhH.mjs +41 -0
  36. package/dist/server/chunks/new_BbQ9b55M.mjs +92 -0
  37. package/dist/server/chunks/node_9bvTewss.mjs +1014 -0
  38. package/dist/server/chunks/noop-entrypoint_BOlrdqWF.mjs +3 -0
  39. package/dist/server/chunks/sequence_9cl7AJy-.mjs +2503 -0
  40. package/dist/server/chunks/server_peBx9VXG.mjs +8117 -0
  41. package/dist/server/chunks/sharp_pmJ7nHES.mjs +142 -0
  42. package/dist/server/chunks/users_Dzddy_YR.mjs +137 -0
  43. package/dist/server/entry.mjs +5 -0
  44. package/dist/server/virtual_astro_middleware.mjs +48 -0
  45. package/package.json +33 -0
  46. package/public/fonts/Serotiva-Black.woff2 +0 -0
  47. package/public/fonts/Serotiva-Bold.woff2 +0 -0
  48. package/public/fonts/Serotiva-Medium.woff2 +0 -0
  49. package/public/fonts/Serotiva-Regular.woff2 +0 -0
  50. package/public/fonts/Serotiva-SemiBold.woff2 +0 -0
  51. package/src/collections/auth/index.ts +155 -0
  52. package/src/components/ActionBar.tsx +215 -0
  53. package/src/components/Admin.tsx +214 -0
  54. package/src/components/AutoForm.tsx +1123 -0
  55. package/src/components/BulkActionsBar.tsx +80 -0
  56. package/src/components/CreateView.tsx +99 -0
  57. package/src/components/DetailView.tsx +329 -0
  58. package/src/components/Icons.tsx +23 -0
  59. package/src/components/ListView.tsx +192 -0
  60. package/src/components/StatusBadge.tsx +76 -0
  61. package/src/components/ThemeProvider.tsx +155 -0
  62. package/src/components/VersionHistoryPanel.tsx +205 -0
  63. package/src/components/fields/CheckboxField.tsx +37 -0
  64. package/src/components/fields/DateField.tsx +42 -0
  65. package/src/components/fields/NumberField.tsx +44 -0
  66. package/src/components/fields/RelationshipField.tsx +87 -0
  67. package/src/components/fields/SelectField.tsx +56 -0
  68. package/src/components/fields/TextField.tsx +49 -0
  69. package/src/components/index.ts +30 -0
  70. package/src/components/layout/Breadcrumbs.tsx +36 -0
  71. package/src/components/layout/Header.tsx +37 -0
  72. package/src/components/layout/Layout.tsx +25 -0
  73. package/src/components/layout/Sidebar.tsx +462 -0
  74. package/src/components/ui/Badge.tsx +14 -0
  75. package/src/components/ui/Button.tsx +41 -0
  76. package/src/components/ui/Dropdown.tsx +82 -0
  77. package/src/components/ui/Modal.tsx +135 -0
  78. package/src/components/ui/SlidePanel.tsx +73 -0
  79. package/src/components/ui/Spinner.tsx +24 -0
  80. package/src/components/ui/Toast.tsx +78 -0
  81. package/src/layouts/AdminLayout.astro +197 -0
  82. package/src/lib/config.ts +68 -0
  83. package/src/lib/dataStore.ts +111 -0
  84. package/src/middleware.ts +48 -0
  85. package/src/pages/[collection]/[id].astro +176 -0
  86. package/src/pages/[collection]/index.astro +180 -0
  87. package/src/pages/api/[collection]/[id].ts +258 -0
  88. package/src/pages/api/[collection]/index.ts +289 -0
  89. package/src/pages/api/auth/[id].ts +142 -0
  90. package/src/pages/api/auth/audit-logs.ts +80 -0
  91. package/src/pages/api/auth/login.ts +101 -0
  92. package/src/pages/api/auth/logout.ts +48 -0
  93. package/src/pages/api/auth/me.ts +36 -0
  94. package/src/pages/api/auth/users.ts +150 -0
  95. package/src/pages/audit/index.astro +110 -0
  96. package/src/pages/index.astro +225 -0
  97. package/src/pages/roles/index.astro +114 -0
  98. package/src/pages/users/[id].astro +174 -0
  99. package/src/pages/users/index.astro +142 -0
  100. package/src/pages/users/new.astro +91 -0
  101. package/src/styles/main.css +1449 -0
  102. package/tsconfig.json +12 -0
@@ -0,0 +1,50 @@
1
+ import { c as createComponent } from './astro-component_Dbx3T2Nh.mjs';
2
+ import 'piccolore';
3
+ import { Q as renderTemplate, F as Fragment, a3 as addAttribute, B as maybeRenderHead } from './sequence_9cl7AJy-.mjs';
4
+ import { r as renderComponent } from './server_peBx9VXG.mjs';
5
+ import { $ as $$AdminLayout } from './AdminLayout_D-_JeUqC.mjs';
6
+
7
+ var __freeze = Object.freeze;
8
+ var __defProp = Object.defineProperty;
9
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(raw || cooked.slice()) }));
10
+ var _a;
11
+ const $$id = createComponent(async ($$result, $$props, $$slots) => {
12
+ const Astro2 = $$result.createAstro($$props, $$slots);
13
+ Astro2.self = $$id;
14
+ const { id } = Astro2.params;
15
+ let user = null;
16
+ let error = null;
17
+ if (id) {
18
+ try {
19
+ const response = await fetch(`${Astro2.url.origin}/api/users/${id}`);
20
+ if (response.ok) {
21
+ const data = await response.json();
22
+ user = data.data;
23
+ } else {
24
+ error = "User not found";
25
+ }
26
+ } catch (e) {
27
+ error = "Failed to fetch user";
28
+ }
29
+ }
30
+ const roleOptions = ["super_admin", "admin", "editor", "author", "customer", "guest"];
31
+ return renderTemplate`${renderComponent($$result, "AdminLayout", $$AdminLayout, { "title": user ? user.email : "User" }, { "default": async ($$result2) => renderTemplate(_a || (_a = __template([" ", '<div class="flex-1 overflow-y-auto p-8 pr-12 space-y-8"> ', " </div> <script>\n document.addEventListener('DOMContentLoaded', () => {\n const userId = window.location.pathname.split('/').pop();\n const saveBtn = document.getElementById('btn-save');\n const lockBtn = document.getElementById('btn-toggle-lock');\n const deleteBtn = document.getElementById('btn-delete-user');\n const roleSelect = document.getElementById('field-role');\n\n if (saveBtn && roleSelect) {\n saveBtn.addEventListener('click', async () => {\n const role = roleSelect.value;\n const res = await fetch(`/api/users/${userId}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ role }),\n });\n if (res.ok) {\n saveBtn.textContent = 'Saved!';\n setTimeout(() => { saveBtn.textContent = 'Save Changes'; }, 2000);\n }\n });\n }\n\n if (lockBtn) {\n lockBtn.addEventListener('click', async () => {\n const isLocked = lockBtn.textContent?.includes('Unlock');\n const res = await fetch(`/api/users/${userId}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ locked: isLocked }),\n });\n if (res.ok) location.reload();\n });\n }\n\n if (deleteBtn) {\n deleteBtn.addEventListener('click', async () => {\n if (confirm('Delete this user? This cannot be undone.')) {\n const res = await fetch(`/api/users/${userId}`, { method: 'DELETE' });\n if (res.ok) window.location.href = '/users';\n }\n });\n }\n });\n <\/script> "], [" ", '<div class="flex-1 overflow-y-auto p-8 pr-12 space-y-8"> ', " </div> <script>\n document.addEventListener('DOMContentLoaded', () => {\n const userId = window.location.pathname.split('/').pop();\n const saveBtn = document.getElementById('btn-save');\n const lockBtn = document.getElementById('btn-toggle-lock');\n const deleteBtn = document.getElementById('btn-delete-user');\n const roleSelect = document.getElementById('field-role');\n\n if (saveBtn && roleSelect) {\n saveBtn.addEventListener('click', async () => {\n const role = roleSelect.value;\n const res = await fetch(\\`/api/users/\\${userId}\\`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ role }),\n });\n if (res.ok) {\n saveBtn.textContent = 'Saved!';\n setTimeout(() => { saveBtn.textContent = 'Save Changes'; }, 2000);\n }\n });\n }\n\n if (lockBtn) {\n lockBtn.addEventListener('click', async () => {\n const isLocked = lockBtn.textContent?.includes('Unlock');\n const res = await fetch(\\`/api/users/\\${userId}\\`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ locked: isLocked }),\n });\n if (res.ok) location.reload();\n });\n }\n\n if (deleteBtn) {\n deleteBtn.addEventListener('click', async () => {\n if (confirm('Delete this user? This cannot be undone.')) {\n const res = await fetch(\\`/api/users/\\${userId}\\`, { method: 'DELETE' });\n if (res.ok) window.location.href = '/users';\n }\n });\n }\n });\n <\/script> "])), maybeRenderHead(), error ? renderTemplate`<div class="surface-tile p-8"> <div class="text-center"> <p class="text-lg font-bold text-red-600">${error}</p> <a href="/users" class="mt-4 inline-block text-[#0b1222] font-bold underline">← Back to users</a> </div> </div>` : user ? renderTemplate`${renderComponent($$result2, "Fragment", Fragment, {}, { "default": async ($$result3) => renderTemplate` <div class="surface-tile p-6 flex items-center justify-between"> <div class="flex items-center gap-4"> <div class="w-14 h-14 rounded-full bg-[#0b1222] text-white flex items-center justify-center font-bold text-xl"> ${user.email.charAt(0).toUpperCase()} </div> <div> <h1 class="text-2xl font-black tracking-tighter text-[#0b1222]">${user.email}</h1> <p class="text-sm text-[#64748b] font-medium">User ID: ${user.id}</p> </div> </div> <div class="flex gap-2"> <button id="btn-toggle-lock" class="px-4 py-2 border border-gray-200 rounded-xl text-sm font-bold text-[#64748b] hover:bg-gray-50 transition-colors"> ${user.locked ? "Unlock User" : "Lock User"} </button> <button id="btn-delete-user" class="px-4 py-2 border border-red-200 rounded-xl text-sm font-bold text-red-600 hover:bg-red-50 transition-colors">
32
+ Delete
33
+ </button> </div> </div> <div class="surface-tile p-6"> <h2 class="text-lg font-black text-[#0b1222] tracking-tighter mb-6">Details</h2> <div class="grid grid-cols-2 gap-6"> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Email</label> <p class="mt-1 font-bold text-[#0b1222]" id="field-email">${user.email}</p> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Role</label> <select id="field-role" class="mt-1 w-full px-3 py-2 border border-gray-200 rounded-lg text-sm font-bold text-[#0b1222]"> ${roleOptions.map((role) => renderTemplate`<option${addAttribute(role, "value")}${addAttribute(user.role === role, "selected")}>${role}</option>`)} </select> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Email Verified</label> <p class="mt-1"> <span${addAttribute(`inline-flex items-center px-3 py-1 rounded-lg text-xs font-bold ${user.emailVerified ? "bg-green-50 text-green-600" : "bg-yellow-50 text-yellow-600"}`, "class")}> ${user.emailVerified ? "Verified" : "Not verified"} </span> </p> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Status</label> <p class="mt-1"> <span${addAttribute(`inline-flex items-center px-3 py-1 rounded-lg text-xs font-bold ${user.locked ? "bg-red-50 text-red-600" : "bg-green-50 text-green-600"}`, "class")}> ${user.locked ? "Locked" : "Active"} </span> </p> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Last Login</label> <p class="mt-1 text-sm text-[#64748b]" id="field-last-login"> ${user.lastLogin ? new Date(user.lastLogin).toLocaleString() : "Never"} </p> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Failed Attempts</label> <p class="mt-1 text-sm font-bold text-[#0b1222]" id="field-failed-attempts"> ${user.failedLoginAttempts || 0} </p> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Created</label> <p class="mt-1 text-sm text-[#64748b]"> ${user.createdAt ? new Date(user.createdAt).toLocaleString() : "—"} </p> </div> <div> <label class="text-xs font-bold text-[#64748b] uppercase tracking-wider">Updated</label> <p class="mt-1 text-sm text-[#64748b]"> ${user.updatedAt ? new Date(user.updatedAt).toLocaleString() : "—"} </p> </div> </div> <div class="mt-6 flex justify-end"> <button id="btn-save" class="px-6 py-2 bg-[#0b1222] text-white rounded-xl text-sm font-bold hover:bg-[#1a2332] transition-colors">
34
+ Save Changes
35
+ </button> </div> </div> ` })}` : renderTemplate`<div class="surface-tile p-8 text-center"> <p class="text-lg font-bold text-[#64748b]">Loading...</p> </div>`) })}`;
36
+ }, "/Users/macbook/Dev/Web/Astro/kyro-cms/admin/src/pages/users/[id].astro", void 0);
37
+
38
+ const $$file = "/Users/macbook/Dev/Web/Astro/kyro-cms/admin/src/pages/users/[id].astro";
39
+ const $$url = "/users/[id]";
40
+
41
+ const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
42
+ __proto__: null,
43
+ default: $$id,
44
+ file: $$file,
45
+ url: $$url
46
+ }, Symbol.toStringTag, { value: 'Module' }));
47
+
48
+ const page = () => _page;
49
+
50
+ export { page };
@@ -0,0 +1,238 @@
1
+ import { d as dataStore } from './dataStore_Dl7cA2Qp.mjs';
2
+ import { c as collections } from './config_CPXslElD.mjs';
3
+
4
+ dataStore.initialize(collections);
5
+ const AUTH_COLLECTIONS = ["users", "roles", "audit_logs"];
6
+ async function getAuthApi() {
7
+ const { RedisAuthAdapter } = await import('./index_CVqOkerS.mjs');
8
+ return new RedisAuthAdapter({
9
+ url: process.env.REDIS_URL || "redis://localhost:6379",
10
+ tls: process.env.REDIS_TLS === "true"
11
+ });
12
+ }
13
+ const GET = async ({ params }) => {
14
+ const collection = params.collection;
15
+ const id = params.id;
16
+ if (AUTH_COLLECTIONS.includes(collection)) {
17
+ try {
18
+ const adapter = await getAuthApi();
19
+ await adapter.connect();
20
+ if (collection === "users") {
21
+ const user = await adapter.findUserById(id);
22
+ await adapter.disconnect();
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
+ if (collection === "audit_logs") {
36
+ const logData = await adapter.redis.hgetall(
37
+ `kyro:auth:audit:${id}`
38
+ );
39
+ await adapter.disconnect();
40
+ if (!logData || !logData.id) {
41
+ return new Response(JSON.stringify({ error: "Log not found" }), {
42
+ status: 404,
43
+ headers: { "Content-Type": "application/json" }
44
+ });
45
+ }
46
+ return new Response(
47
+ JSON.stringify({
48
+ data: {
49
+ id: logData.id,
50
+ action: logData.action,
51
+ userId: logData.userId,
52
+ userEmail: logData.userEmail,
53
+ role: logData.role,
54
+ resource: logData.resource,
55
+ ipAddress: logData.ipAddress,
56
+ success: logData.success === "true",
57
+ error: logData.error,
58
+ timestamp: logData.timestamp
59
+ }
60
+ }),
61
+ { status: 200, headers: { "Content-Type": "application/json" } }
62
+ );
63
+ }
64
+ await adapter.disconnect();
65
+ } catch (error) {
66
+ console.error(`Error fetching ${collection}:`, error);
67
+ return new Response(
68
+ JSON.stringify({ error: `Failed to fetch ${collection}` }),
69
+ { status: 500, headers: { "Content-Type": "application/json" } }
70
+ );
71
+ }
72
+ }
73
+ try {
74
+ const doc = dataStore.findById(collection, id);
75
+ if (!doc) {
76
+ return new Response(JSON.stringify({ error: "Document not found" }), {
77
+ status: 404,
78
+ headers: { "Content-Type": "application/json" }
79
+ });
80
+ }
81
+ return new Response(JSON.stringify({ data: doc }), {
82
+ status: 200,
83
+ headers: { "Content-Type": "application/json" }
84
+ });
85
+ } catch (error) {
86
+ return new Response(JSON.stringify({ error: "Failed to fetch document" }), {
87
+ status: 500,
88
+ headers: { "Content-Type": "application/json" }
89
+ });
90
+ }
91
+ };
92
+ const PATCH = async ({ params, request }) => {
93
+ const collection = params.collection;
94
+ const id = params.id;
95
+ if (AUTH_COLLECTIONS.includes(collection)) {
96
+ try {
97
+ const adapter = await getAuthApi();
98
+ await adapter.connect();
99
+ const body = await request.json();
100
+ if (collection === "users") {
101
+ const existing = await adapter.findUserById(id);
102
+ if (!existing) {
103
+ await adapter.disconnect();
104
+ return new Response(JSON.stringify({ error: "User not found" }), {
105
+ status: 404,
106
+ headers: { "Content-Type": "application/json" }
107
+ });
108
+ }
109
+ const updateData = {};
110
+ if (body.email !== void 0) updateData.email = body.email;
111
+ if (body.role !== void 0) updateData.role = body.role;
112
+ if (body.tenantId !== void 0) updateData.tenantId = body.tenantId;
113
+ if (body.locked !== void 0) updateData.locked = body.locked;
114
+ if (body.emailVerified !== void 0)
115
+ updateData.emailVerified = body.emailVerified;
116
+ if (body.password) {
117
+ updateData.passwordHash = await adapter.hashPassword(body.password);
118
+ }
119
+ const user = await adapter.updateUser(id, updateData);
120
+ await adapter.disconnect();
121
+ if (!user) {
122
+ return new Response(
123
+ JSON.stringify({ error: "Failed to update user" }),
124
+ {
125
+ status: 500,
126
+ headers: { "Content-Type": "application/json" }
127
+ }
128
+ );
129
+ }
130
+ const { passwordHash, ...safeUser } = user;
131
+ return new Response(JSON.stringify({ data: safeUser }), {
132
+ status: 200,
133
+ headers: { "Content-Type": "application/json" }
134
+ });
135
+ }
136
+ await adapter.disconnect();
137
+ return new Response(
138
+ JSON.stringify({
139
+ error: `Collection ${collection} does not support PATCH`
140
+ }),
141
+ { status: 405, headers: { "Content-Type": "application/json" } }
142
+ );
143
+ } catch (error) {
144
+ console.error(`Error updating ${collection}:`, error);
145
+ return new Response(
146
+ JSON.stringify({ error: `Failed to update ${collection}` }),
147
+ { status: 500, headers: { "Content-Type": "application/json" } }
148
+ );
149
+ }
150
+ }
151
+ try {
152
+ const body = await request.json();
153
+ const doc = dataStore.update(collection, id, body);
154
+ if (!doc) {
155
+ return new Response(JSON.stringify({ error: "Document not found" }), {
156
+ status: 404,
157
+ headers: { "Content-Type": "application/json" }
158
+ });
159
+ }
160
+ return new Response(JSON.stringify({ data: doc }), {
161
+ status: 200,
162
+ headers: { "Content-Type": "application/json" }
163
+ });
164
+ } catch (error) {
165
+ return new Response(
166
+ JSON.stringify({ error: "Failed to update document" }),
167
+ { status: 500, headers: { "Content-Type": "application/json" } }
168
+ );
169
+ }
170
+ };
171
+ const DELETE = async ({ params }) => {
172
+ const collection = params.collection;
173
+ const id = params.id;
174
+ if (AUTH_COLLECTIONS.includes(collection)) {
175
+ try {
176
+ const adapter = await getAuthApi();
177
+ await adapter.connect();
178
+ if (collection === "users") {
179
+ const existing = await adapter.findUserById(id);
180
+ if (!existing) {
181
+ await adapter.disconnect();
182
+ return new Response(JSON.stringify({ error: "User not found" }), {
183
+ status: 404,
184
+ headers: { "Content-Type": "application/json" }
185
+ });
186
+ }
187
+ await adapter.deleteUser(id);
188
+ await adapter.disconnect();
189
+ return new Response(JSON.stringify({ success: true }), {
190
+ status: 200,
191
+ headers: { "Content-Type": "application/json" }
192
+ });
193
+ }
194
+ await adapter.disconnect();
195
+ return new Response(
196
+ JSON.stringify({
197
+ error: `Collection ${collection} does not support DELETE`
198
+ }),
199
+ { status: 405, headers: { "Content-Type": "application/json" } }
200
+ );
201
+ } catch (error) {
202
+ console.error(`Error deleting ${collection}:`, error);
203
+ return new Response(
204
+ JSON.stringify({ error: `Failed to delete ${collection}` }),
205
+ { status: 500, headers: { "Content-Type": "application/json" } }
206
+ );
207
+ }
208
+ }
209
+ try {
210
+ const success = dataStore.delete(collection, id);
211
+ if (!success) {
212
+ return new Response(JSON.stringify({ error: "Document not found" }), {
213
+ status: 404,
214
+ headers: { "Content-Type": "application/json" }
215
+ });
216
+ }
217
+ return new Response(JSON.stringify({ success: true }), {
218
+ status: 200,
219
+ headers: { "Content-Type": "application/json" }
220
+ });
221
+ } catch (error) {
222
+ return new Response(
223
+ JSON.stringify({ error: "Failed to delete document" }),
224
+ { status: 500, headers: { "Content-Type": "application/json" } }
225
+ );
226
+ }
227
+ };
228
+
229
+ const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
230
+ __proto__: null,
231
+ DELETE,
232
+ GET,
233
+ PATCH
234
+ }, Symbol.toStringTag, { value: 'Module' }));
235
+
236
+ const page = () => _page;
237
+
238
+ export { page };