@kyro-cms/admin 0.1.6 → 0.1.8
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 +149 -51
- package/package.json +54 -5
- package/src/collections/auth/index.ts +2 -2
- package/src/collections/portfolio/index.ts +343 -0
- package/src/components/ActionBar.tsx +153 -16
- package/src/components/Admin.tsx +137 -28
- package/src/components/ApiExplorer.tsx +325 -0
- package/src/components/ApiKeysManager.tsx +563 -0
- package/src/components/AuditLogsPage.tsx +664 -0
- package/src/components/AutoForm.tsx +2155 -770
- package/src/components/BrandingHub.tsx +267 -0
- package/src/components/BulkActionsBar.tsx +3 -3
- package/src/components/CreateView.tsx +4 -4
- package/src/components/Dashboard.tsx +393 -0
- package/src/components/DetailView.tsx +200 -58
- package/src/components/DeveloperCenter.tsx +403 -0
- package/src/components/EnhancedListView.tsx +890 -0
- package/src/components/GraphQLExplorer.tsx +675 -0
- package/src/components/GraphQLPlayground.tsx +627 -0
- package/src/components/ListView.tsx +192 -54
- package/src/components/MediaGallery.tsx +1569 -0
- package/src/components/Modal.tsx +206 -0
- package/src/components/RestPlayground.tsx +951 -0
- package/src/components/Sidebar.astro +237 -0
- package/src/components/ThemeProvider.tsx +8 -2
- package/src/components/UserManagement.tsx +204 -0
- package/src/components/VersionHistoryPanel.tsx +3 -3
- package/src/components/WebhookManager.tsx +608 -0
- package/src/components/blocks/AccordionBlock.tsx +65 -0
- package/src/components/blocks/ArrayBlock.tsx +84 -0
- package/src/components/blocks/BlockEditModal.tsx +363 -0
- package/src/components/blocks/ButtonBlock.tsx +64 -0
- package/src/components/blocks/ChildBlocksTree.tsx +551 -0
- package/src/components/blocks/CodeBlock.tsx +114 -0
- package/src/components/blocks/ColumnsBlock.tsx +93 -0
- package/src/components/blocks/DividerBlock.tsx +43 -0
- package/src/components/blocks/FileBlock.tsx +63 -0
- package/src/components/blocks/HeadingBlock.tsx +59 -0
- package/src/components/blocks/HeroBlock.tsx +99 -0
- package/src/components/blocks/ImageBlock.tsx +82 -0
- package/src/components/blocks/LinkBlock.tsx +65 -0
- package/src/components/blocks/ListBlock.tsx +60 -0
- package/src/components/blocks/ParagraphBlock.tsx +61 -0
- package/src/components/blocks/RelationshipBlock.tsx +72 -0
- package/src/components/blocks/RichTextBlock.tsx +66 -0
- package/src/components/blocks/VStackBlock.tsx +61 -0
- package/src/components/blocks/VideoBlock.tsx +65 -0
- package/src/components/blocks/index.ts +10 -0
- package/src/components/fields/AccordionField.tsx +213 -0
- package/src/components/fields/ArrayField.tsx +241 -0
- package/src/components/fields/BlocksField.tsx +323 -0
- package/src/components/fields/ButtonField.tsx +53 -0
- package/src/components/fields/CheckboxField.tsx +18 -8
- package/src/components/fields/ChildrenField.tsx +48 -0
- package/src/components/fields/CodeField.tsx +294 -0
- package/src/components/fields/ColumnsField.tsx +137 -0
- package/src/components/fields/DateField.tsx +24 -12
- package/src/components/fields/EditorClient.tsx +537 -0
- package/src/components/fields/HeadingField.tsx +31 -0
- package/src/components/fields/HeroField.tsx +101 -0
- package/src/components/fields/JSONField.tsx +341 -0
- package/src/components/fields/LinkField.tsx +81 -0
- package/src/components/fields/ListField.tsx +74 -0
- package/src/components/fields/MarkdownField.tsx +260 -0
- package/src/components/fields/NumberField.tsx +25 -13
- package/src/components/fields/PortableTextField.tsx +155 -0
- package/src/components/fields/PortableTextRenderer.tsx +68 -0
- package/src/components/fields/RelationshipBlockField.tsx +233 -0
- package/src/components/fields/RelationshipField.tsx +278 -60
- package/src/components/fields/SelectField.tsx +28 -16
- package/src/components/fields/TextField.tsx +31 -15
- package/src/components/fields/UploadField.tsx +613 -0
- package/src/components/fields/VideoField.tsx +73 -0
- package/src/components/fields/extensions/blockComponents.tsx +247 -0
- package/src/components/fields/extensions/blocksStore.ts +273 -0
- package/src/components/fields/index.ts +24 -0
- package/src/components/index.ts +1 -2
- package/src/components/layout/Header.tsx +2 -2
- package/src/components/layout/Layout.tsx +3 -3
- package/src/components/ui/Badge.tsx +9 -4
- package/src/components/ui/BlockDrawer.tsx +79 -0
- package/src/components/ui/Button.tsx +1 -1
- package/src/components/ui/CommandPalette.tsx +362 -0
- package/src/components/ui/CommandPaletteWrapper.tsx +97 -0
- package/src/components/ui/Dropdown.tsx +1 -1
- package/src/components/ui/Modal.tsx +37 -12
- package/src/components/ui/PromptModal.tsx +94 -0
- package/src/components/ui/SlidePanel.tsx +43 -16
- package/src/components/ui/Toast.tsx +80 -14
- package/src/env.d.ts +16 -0
- package/src/env.ts +20 -0
- package/src/index.ts +0 -1
- package/src/layouts/AdminLayout.astro +164 -170
- package/src/layouts/AuthLayout.astro +23 -6
- package/src/lib/MediaService.ts +541 -0
- package/src/lib/api.ts +163 -0
- package/src/lib/auth/sqlite-adapter.ts +319 -0
- package/src/lib/config.ts +23 -7
- package/src/lib/dataStore.ts +188 -73
- package/src/lib/date-utils.ts +69 -0
- package/src/lib/db/adapter.ts +54 -0
- package/src/lib/db/drizzle-mysql-adapter.ts +194 -0
- package/src/lib/db/drizzle-mysql-auth-adapter.ts +327 -0
- package/src/lib/db/drizzle-postgres-adapter.ts +202 -0
- package/src/lib/db/drizzle-postgres-auth-adapter.ts +304 -0
- package/src/lib/db/drizzle-sqlite-adapter.ts +227 -0
- package/src/lib/db/drizzle-sqlite-auth-adapter.ts +548 -0
- package/src/lib/db/index.ts +449 -0
- package/src/lib/db/mongodb-adapter.ts +207 -0
- package/src/lib/db/mongodb-auth-adapter.ts +305 -0
- package/src/lib/db/schema/mysql-auth.ts +113 -0
- package/src/lib/db/schema/mysql-content.ts +20 -0
- package/src/lib/db/schema/postgres-auth.ts +116 -0
- package/src/lib/db/schema/postgres-content.ts +35 -0
- package/src/lib/db/schema/postgres-media.ts +52 -0
- package/src/lib/db/schema/postgres-settings.ts +11 -0
- package/src/lib/db/schema/sqlite-auth.ts +112 -0
- package/src/lib/db/schema/sqlite-content.ts +20 -0
- package/src/lib/db/version-adapter.ts +248 -0
- package/src/lib/graphql/index.ts +1 -0
- package/src/lib/graphql/schema.ts +443 -0
- package/src/lib/i18n.tsx +353 -0
- package/src/lib/rate-limit.ts +267 -0
- package/src/lib/slugify.ts +15 -0
- package/src/lib/storage.ts +374 -0
- package/src/lib/store.ts +85 -0
- package/src/lib/validation.ts +250 -0
- package/src/middleware.ts +70 -11
- package/src/pages/[collection]/[id].astro +178 -122
- package/src/pages/[collection]/index.astro +24 -156
- package/src/pages/admin/api-explorer.astro +98 -0
- package/src/pages/admin/graphql-explorer.astro +40 -0
- package/src/pages/admin/graphql.astro +97 -0
- package/src/pages/admin/index.astro +200 -139
- package/src/pages/admin/keys.astro +8 -0
- package/src/pages/admin/rest-playground.astro +44 -0
- package/src/pages/admin/webhooks.astro +8 -0
- package/src/pages/api/[collection]/[id]/publish.ts +52 -0
- package/src/pages/api/[collection]/[id]/unpublish.ts +42 -0
- package/src/pages/api/[collection]/[id]/versions.ts +66 -0
- package/src/pages/api/[collection]/[id].ts +114 -159
- package/src/pages/api/[collection]/index.ts +150 -230
- package/src/pages/api/auth/[id].ts +48 -69
- package/src/pages/api/auth/audit-logs.ts +20 -43
- package/src/pages/api/auth/login.ts +159 -45
- package/src/pages/api/auth/logout.ts +42 -24
- package/src/pages/api/auth/refresh.ts +119 -0
- package/src/pages/api/auth/register.ts +110 -40
- package/src/pages/api/auth/users.ts +22 -97
- package/src/pages/api/collections.ts +59 -0
- package/src/pages/api/globals/[slug]/test.ts +172 -0
- package/src/pages/api/globals/[slug].ts +42 -0
- package/src/pages/api/graphql.ts +90 -0
- package/src/pages/api/health.ts +417 -40
- package/src/pages/api/keys/[id].ts +26 -0
- package/src/pages/api/keys/index.ts +75 -0
- package/src/pages/api/media/[id].ts +309 -0
- package/src/pages/api/media/folders.ts +609 -0
- package/src/pages/api/media/index.ts +146 -0
- package/src/pages/api/media/resize.ts +267 -0
- package/src/pages/api/search.ts +82 -0
- package/src/pages/api/slug-availability.ts +70 -0
- package/src/pages/api/storage-config.ts +20 -0
- package/src/pages/api/storage-status.ts +206 -0
- package/src/pages/api/upload.ts +334 -0
- package/src/pages/api/webhooks/index.ts +71 -0
- package/src/pages/audit/index.astro +2 -104
- package/src/pages/login.astro +11 -11
- package/src/pages/media.astro +10 -0
- package/src/pages/preview/[collection]/[id].astro +178 -0
- package/src/pages/register.astro +13 -13
- package/src/pages/roles/index.astro +21 -21
- package/src/pages/settings/[slug].astro +162 -0
- package/src/pages/settings/index.astro +9 -0
- package/src/pages/users/[id].astro +29 -21
- package/src/pages/users/index.astro +22 -17
- package/src/pages/users/new.astro +18 -17
- package/src/styles/main.css +563 -128
- package/src/components/layout/Sidebar.tsx +0 -497
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { APIRoute } from "astro";
|
|
2
|
+
import { dataStore } from "@/lib/dataStore";
|
|
3
|
+
|
|
4
|
+
export const GET: APIRoute = async ({ params, url }) => {
|
|
5
|
+
const { collection, id } = params;
|
|
6
|
+
if (!collection || !id) return new Response(null, { status: 400 });
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const compareA = url.searchParams.get("compareA");
|
|
10
|
+
const compareB = url.searchParams.get("compareB");
|
|
11
|
+
|
|
12
|
+
if (compareA && compareB) {
|
|
13
|
+
const diffs = await dataStore.compareVersions(
|
|
14
|
+
collection,
|
|
15
|
+
id,
|
|
16
|
+
isNaN(Number(compareA)) ? compareA : Number(compareA),
|
|
17
|
+
isNaN(Number(compareB)) ? compareB : Number(compareB),
|
|
18
|
+
);
|
|
19
|
+
return new Response(JSON.stringify({ diffs }), {
|
|
20
|
+
status: 200,
|
|
21
|
+
headers: { "Content-Type": "application/json" },
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const versions = await dataStore.findVersions(collection, id);
|
|
26
|
+
return new Response(JSON.stringify({ docs: versions }), {
|
|
27
|
+
status: 200,
|
|
28
|
+
headers: { "Content-Type": "application/json" },
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
return new Response(JSON.stringify({ error: "Failed to fetch versions" }), {
|
|
32
|
+
status: 500,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const POST: APIRoute = async ({ params, request }) => {
|
|
38
|
+
const { collection, id } = params;
|
|
39
|
+
if (!collection || !id) return new Response(null, { status: 400 });
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const { versionId, action } = await request.json();
|
|
43
|
+
|
|
44
|
+
if (action === "restore" && versionId) {
|
|
45
|
+
const restored = await dataStore.restoreVersion(
|
|
46
|
+
collection,
|
|
47
|
+
id,
|
|
48
|
+
versionId,
|
|
49
|
+
);
|
|
50
|
+
if (!restored)
|
|
51
|
+
return new Response(JSON.stringify({ error: "Restore failed" }), {
|
|
52
|
+
status: 400,
|
|
53
|
+
});
|
|
54
|
+
return new Response(JSON.stringify({ data: restored }), { status: 200 });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return new Response(JSON.stringify({ error: "Invalid action" }), {
|
|
58
|
+
status: 400,
|
|
59
|
+
});
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return new Response(
|
|
62
|
+
JSON.stringify({ error: "Failed to perform version action" }),
|
|
63
|
+
{ status: 500 },
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import type { APIRoute } from "astro";
|
|
2
2
|
import { dataStore } from "@/lib/dataStore";
|
|
3
3
|
import { collections } from "@/lib/config";
|
|
4
|
+
import { getAuthAdapter } from "../../../lib/db";
|
|
4
5
|
|
|
5
6
|
dataStore.initialize(collections);
|
|
6
7
|
|
|
7
8
|
const AUTH_COLLECTIONS = ["users", "roles", "audit_logs"];
|
|
8
9
|
|
|
9
|
-
async function
|
|
10
|
-
|
|
11
|
-
return new RedisAuthAdapter({
|
|
12
|
-
url: process.env.REDIS_URL || "redis://localhost:6379",
|
|
13
|
-
tls: process.env.REDIS_TLS === "true",
|
|
14
|
-
});
|
|
10
|
+
async function getAuthAdapterLocal() {
|
|
11
|
+
return await getAuthAdapter();
|
|
15
12
|
}
|
|
16
13
|
|
|
17
14
|
export const GET: APIRoute = async ({ params }) => {
|
|
@@ -19,76 +16,55 @@ export const GET: APIRoute = async ({ params }) => {
|
|
|
19
16
|
const id = params.id as string;
|
|
20
17
|
|
|
21
18
|
if (AUTH_COLLECTIONS.includes(collection)) {
|
|
22
|
-
|
|
23
|
-
const adapter = await getAuthApi();
|
|
24
|
-
await adapter.connect();
|
|
19
|
+
const adapter = await getAuthAdapterLocal();
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return new Response(JSON.stringify({ error: "User not found" }), {
|
|
32
|
-
status: 404,
|
|
33
|
-
headers: { "Content-Type": "application/json" },
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const { passwordHash, ...safeUser } = user;
|
|
38
|
-
return new Response(JSON.stringify({ data: safeUser }), {
|
|
39
|
-
status: 200,
|
|
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,
|
|
40
26
|
headers: { "Content-Type": "application/json" },
|
|
41
27
|
});
|
|
42
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
|
+
}
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
status: 404,
|
|
53
|
-
headers: { "Content-Type": "application/json" },
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return new Response(
|
|
58
|
-
JSON.stringify({
|
|
59
|
-
data: {
|
|
60
|
-
id: logData.id,
|
|
61
|
-
action: logData.action,
|
|
62
|
-
userId: logData.userId,
|
|
63
|
-
userEmail: logData.userEmail,
|
|
64
|
-
role: logData.role,
|
|
65
|
-
resource: logData.resource,
|
|
66
|
-
ipAddress: logData.ipAddress,
|
|
67
|
-
success: logData.success === "true",
|
|
68
|
-
error: logData.error,
|
|
69
|
-
timestamp: logData.timestamp,
|
|
70
|
-
},
|
|
71
|
-
}),
|
|
72
|
-
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
73
|
-
);
|
|
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
|
+
});
|
|
74
44
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return new Response(
|
|
80
|
-
JSON.stringify({ error: `Failed to fetch ${collection}` }),
|
|
81
|
-
{ status: 500, headers: { "Content-Type": "application/json" } },
|
|
82
|
-
);
|
|
45
|
+
return new Response(JSON.stringify({ data: role }), {
|
|
46
|
+
status: 200,
|
|
47
|
+
headers: { "Content-Type": "application/json" },
|
|
48
|
+
});
|
|
83
49
|
}
|
|
50
|
+
|
|
51
|
+
return new Response(
|
|
52
|
+
JSON.stringify({ error: `Collection ${collection} not supported` }),
|
|
53
|
+
{ status: 404, headers: { "Content-Type": "application/json" } },
|
|
54
|
+
);
|
|
84
55
|
}
|
|
85
56
|
|
|
86
57
|
try {
|
|
87
|
-
|
|
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
|
+
}
|
|
88
65
|
if (!doc) {
|
|
89
66
|
return new Response(JSON.stringify({ error: "Document not found" }), {
|
|
90
67
|
status: 404,
|
|
91
|
-
headers: { "Content-Type": "application/json" },
|
|
92
68
|
});
|
|
93
69
|
}
|
|
94
70
|
return new Response(JSON.stringify({ data: doc }), {
|
|
@@ -98,7 +74,6 @@ export const GET: APIRoute = async ({ params }) => {
|
|
|
98
74
|
} catch (error) {
|
|
99
75
|
return new Response(JSON.stringify({ error: "Failed to fetch document" }), {
|
|
100
76
|
status: 500,
|
|
101
|
-
headers: { "Content-Type": "application/json" },
|
|
102
77
|
});
|
|
103
78
|
}
|
|
104
79
|
};
|
|
@@ -108,77 +83,69 @@ export const PATCH: APIRoute = async ({ params, request }) => {
|
|
|
108
83
|
const id = params.id as string;
|
|
109
84
|
|
|
110
85
|
if (AUTH_COLLECTIONS.includes(collection)) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
await adapter.connect();
|
|
114
|
-
|
|
115
|
-
const body = await request.json();
|
|
116
|
-
|
|
117
|
-
if (collection === "users") {
|
|
118
|
-
const existing = await adapter.findUserById(id);
|
|
119
|
-
if (!existing) {
|
|
120
|
-
await adapter.disconnect();
|
|
121
|
-
return new Response(JSON.stringify({ error: "User not found" }), {
|
|
122
|
-
status: 404,
|
|
123
|
-
headers: { "Content-Type": "application/json" },
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const updateData: Record<string, unknown> = {};
|
|
128
|
-
if (body.email !== undefined) updateData.email = body.email;
|
|
129
|
-
if (body.role !== undefined) updateData.role = body.role;
|
|
130
|
-
if (body.tenantId !== undefined) updateData.tenantId = body.tenantId;
|
|
131
|
-
if (body.locked !== undefined) updateData.locked = body.locked;
|
|
132
|
-
if (body.emailVerified !== undefined)
|
|
133
|
-
updateData.emailVerified = body.emailVerified;
|
|
134
|
-
|
|
135
|
-
if (body.password) {
|
|
136
|
-
updateData.passwordHash = await adapter.hashPassword(body.password);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const user = await adapter.updateUser(id, updateData);
|
|
140
|
-
await adapter.disconnect();
|
|
141
|
-
|
|
142
|
-
if (!user) {
|
|
143
|
-
return new Response(
|
|
144
|
-
JSON.stringify({ error: "Failed to update user" }),
|
|
145
|
-
{
|
|
146
|
-
status: 500,
|
|
147
|
-
headers: { "Content-Type": "application/json" },
|
|
148
|
-
},
|
|
149
|
-
);
|
|
150
|
-
}
|
|
86
|
+
const adapter = await getAuthAdapterLocal();
|
|
87
|
+
const body = await request.json();
|
|
151
88
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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,
|
|
155
94
|
headers: { "Content-Type": "application/json" },
|
|
156
95
|
});
|
|
157
96
|
}
|
|
158
97
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
+
});
|
|
172
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
|
+
);
|
|
173
129
|
}
|
|
174
130
|
|
|
175
131
|
try {
|
|
176
132
|
const body = await request.json();
|
|
177
|
-
const
|
|
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
|
+
});
|
|
178
146
|
if (!doc) {
|
|
179
147
|
return new Response(JSON.stringify({ error: "Document not found" }), {
|
|
180
148
|
status: 404,
|
|
181
|
-
headers: { "Content-Type": "application/json" },
|
|
182
149
|
});
|
|
183
150
|
}
|
|
184
151
|
return new Response(JSON.stringify({ data: doc }), {
|
|
@@ -188,7 +155,9 @@ export const PATCH: APIRoute = async ({ params, request }) => {
|
|
|
188
155
|
} catch (error) {
|
|
189
156
|
return new Response(
|
|
190
157
|
JSON.stringify({ error: "Failed to update document" }),
|
|
191
|
-
{
|
|
158
|
+
{
|
|
159
|
+
status: 500,
|
|
160
|
+
},
|
|
192
161
|
);
|
|
193
162
|
}
|
|
194
163
|
};
|
|
@@ -198,51 +167,35 @@ export const DELETE: APIRoute = async ({ params }) => {
|
|
|
198
167
|
const id = params.id as string;
|
|
199
168
|
|
|
200
169
|
if (AUTH_COLLECTIONS.includes(collection)) {
|
|
201
|
-
|
|
202
|
-
const adapter = await getAuthApi();
|
|
203
|
-
await adapter.connect();
|
|
204
|
-
|
|
205
|
-
if (collection === "users") {
|
|
206
|
-
const existing = await adapter.findUserById(id);
|
|
207
|
-
if (!existing) {
|
|
208
|
-
await adapter.disconnect();
|
|
209
|
-
return new Response(JSON.stringify({ error: "User not found" }), {
|
|
210
|
-
status: 404,
|
|
211
|
-
headers: { "Content-Type": "application/json" },
|
|
212
|
-
});
|
|
213
|
-
}
|
|
170
|
+
const adapter = await getAuthAdapterLocal();
|
|
214
171
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
return new Response(JSON.stringify({
|
|
219
|
-
status:
|
|
220
|
-
headers: { "Content-Type": "application/json" },
|
|
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,
|
|
221
177
|
});
|
|
222
178
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}),
|
|
229
|
-
{ status: 405, headers: { "Content-Type": "application/json" } },
|
|
230
|
-
);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
console.error(`Error deleting ${collection}:`, error);
|
|
233
|
-
return new Response(
|
|
234
|
-
JSON.stringify({ error: `Failed to delete ${collection}` }),
|
|
235
|
-
{ status: 500, headers: { "Content-Type": "application/json" } },
|
|
236
|
-
);
|
|
179
|
+
await adapter.deleteUser(id);
|
|
180
|
+
return new Response(JSON.stringify({ success: true }), {
|
|
181
|
+
status: 200,
|
|
182
|
+
headers: { "Content-Type": "application/json" },
|
|
183
|
+
});
|
|
237
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
|
+
);
|
|
238
192
|
}
|
|
239
193
|
|
|
240
194
|
try {
|
|
241
|
-
const success = dataStore.delete(collection, id);
|
|
195
|
+
const success = await dataStore.delete(collection, id);
|
|
242
196
|
if (!success) {
|
|
243
197
|
return new Response(JSON.stringify({ error: "Document not found" }), {
|
|
244
198
|
status: 404,
|
|
245
|
-
headers: { "Content-Type": "application/json" },
|
|
246
199
|
});
|
|
247
200
|
}
|
|
248
201
|
return new Response(JSON.stringify({ success: true }), {
|
|
@@ -252,7 +205,9 @@ export const DELETE: APIRoute = async ({ params }) => {
|
|
|
252
205
|
} catch (error) {
|
|
253
206
|
return new Response(
|
|
254
207
|
JSON.stringify({ error: "Failed to delete document" }),
|
|
255
|
-
{
|
|
208
|
+
{
|
|
209
|
+
status: 500,
|
|
210
|
+
},
|
|
256
211
|
);
|
|
257
212
|
}
|
|
258
213
|
};
|