@kyro-cms/admin 0.3.1 → 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.
- package/dist/EditorClient-XEUOVAAC.js +466 -0
- package/dist/EditorClient-XEUOVAAC.js.map +1 -0
- package/dist/EditorClient-YLCGVDXY.cjs +468 -0
- package/dist/EditorClient-YLCGVDXY.cjs.map +1 -0
- package/dist/chunk-7KPIUCGT.js +384 -0
- package/dist/chunk-7KPIUCGT.js.map +1 -0
- package/dist/chunk-GOACG6R7.cjs +473 -0
- package/dist/chunk-GOACG6R7.cjs.map +1 -0
- package/dist/index.cjs +14861 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1661 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +563 -0
- package/dist/index.js +14784 -0
- package/dist/index.js.map +1 -0
- package/package.json +19 -19
- package/src/components/ActionBar.tsx +7 -43
- package/src/components/Admin.tsx +138 -277
- package/src/components/ApiKeysManager.tsx +428 -419
- package/src/components/AuditLogsPage.tsx +35 -39
- package/src/components/AuthBridge.tsx +51 -0
- package/src/components/AutoForm.tsx +495 -1230
- package/src/components/BrandingHub.tsx +18 -19
- package/src/components/BulkActionsBar.tsx +1 -1
- package/src/components/CreateView.tsx +22 -36
- package/src/components/Dashboard.tsx +60 -84
- package/src/components/DetailView.tsx +113 -91
- package/src/components/DeveloperCenter.tsx +200 -198
- package/src/components/FieldRenderer.tsx +206 -0
- package/src/components/GraphQLPlayground.tsx +340 -480
- package/src/components/ListView.tsx +828 -254
- package/src/components/LoginPage.tsx +3 -4
- package/src/components/MarketplaceManager.tsx +254 -0
- package/src/components/MediaGallery.tsx +856 -1192
- package/src/components/PluginsManager.tsx +277 -0
- package/src/components/RestPlayground.tsx +398 -560
- package/src/components/SessionsManager.tsx +211 -0
- package/src/components/Sidebar.astro +179 -151
- package/src/components/ThemeProvider.tsx +7 -161
- package/src/components/UserManagement.tsx +162 -146
- package/src/components/UserMenu.tsx +110 -0
- package/src/components/WebhookManager.tsx +305 -367
- package/src/components/blocks/AccordionBlock.tsx +4 -4
- package/src/components/blocks/ArrayBlock.tsx +3 -3
- package/src/components/blocks/BlockEditModal.tsx +8 -8
- package/src/components/blocks/BlockWrapper.tsx +61 -0
- package/src/components/blocks/ButtonBlock.tsx +4 -4
- package/src/components/blocks/ChildBlocksTree.tsx +23 -25
- package/src/components/blocks/CodeBlock.tsx +15 -15
- package/src/components/blocks/ColumnsBlock.tsx +6 -44
- package/src/components/blocks/DividerBlock.tsx +3 -3
- package/src/components/blocks/FileBlock.tsx +4 -4
- package/src/components/blocks/HeadingBlock.tsx +6 -38
- package/src/components/blocks/HeroBlock.tsx +4 -4
- package/src/components/blocks/ImageBlock.tsx +4 -4
- package/src/components/blocks/LinkBlock.tsx +4 -4
- package/src/components/blocks/ListBlock.tsx +3 -3
- package/src/components/blocks/ParagraphBlock.tsx +12 -42
- package/src/components/blocks/RelationshipBlock.tsx +4 -4
- package/src/components/blocks/RichTextBlock.tsx +4 -4
- package/src/components/blocks/VStackBlock.tsx +5 -37
- package/src/components/blocks/VideoBlock.tsx +4 -4
- package/src/components/blocks/types.ts +11 -0
- package/src/components/fields/AccordionField.tsx +1 -1
- package/src/components/fields/ArrayField.tsx +2 -2
- package/src/components/fields/ArrayLayout.tsx +93 -0
- package/src/components/fields/BlocksField.tsx +122 -111
- package/src/components/fields/ButtonField.tsx +1 -1
- package/src/components/fields/CheckboxField.tsx +14 -15
- package/src/components/fields/ChildrenField.tsx +2 -2
- package/src/components/fields/CodeField.tsx +3 -3
- package/src/components/fields/ColumnsField.tsx +2 -2
- package/src/components/fields/DateField.tsx +13 -26
- package/src/components/fields/EditorClient.tsx +26 -28
- package/src/components/fields/FieldLayout.tsx +52 -0
- package/src/components/fields/GroupLayout.tsx +35 -0
- package/src/components/fields/JSONField.tsx +7 -7
- package/src/components/fields/LinkField.tsx +1 -1
- package/src/components/fields/MarkdownField.tsx +1 -1
- package/src/components/fields/NumberField.tsx +13 -26
- package/src/components/fields/PortableTextField.tsx +4 -4
- package/src/components/fields/PortableTextRenderer.tsx +1 -1
- package/src/components/fields/RelationshipBlockField.tsx +31 -23
- package/src/components/fields/RelationshipField.tsx +14 -14
- package/src/components/fields/SelectField.tsx +17 -26
- package/src/components/fields/TabsLayout.tsx +69 -0
- package/src/components/fields/TextField.tsx +85 -38
- package/src/components/fields/UploadField.tsx +71 -41
- package/src/components/fields/VideoField.tsx +1 -1
- package/src/components/fields/extensions/blockComponents.tsx +2 -2
- package/src/components/fields/extensions/blocksStore.ts +207 -193
- package/src/components/fields/types.ts +22 -0
- package/src/components/layout/Layout.tsx +1 -1
- package/src/components/ui/ActionMenu.tsx +63 -0
- package/src/components/ui/Badge.tsx +59 -5
- package/src/components/ui/BlockDrawer.tsx +4 -5
- package/src/components/ui/CommandPalette.tsx +58 -36
- package/src/components/ui/CommandPaletteWrapper.tsx +18 -17
- package/src/components/ui/Dropdown.tsx +18 -16
- package/src/components/ui/EmptyState.tsx +25 -0
- package/src/components/ui/GlobalModal.tsx +49 -0
- package/src/components/ui/IconButton.tsx +44 -0
- package/src/components/ui/Modal.tsx +19 -20
- package/src/components/ui/PageHeader.tsx +158 -0
- package/src/components/ui/Pagination.tsx +61 -0
- package/src/components/ui/PromptModal.tsx +1 -1
- package/src/components/ui/SearchInput.tsx +57 -0
- package/src/components/ui/SeoPreview.tsx +31 -0
- package/src/components/ui/SessionModal.tsx +0 -0
- package/src/components/ui/SlidePanel.tsx +2 -0
- package/src/components/ui/Toast.tsx +65 -122
- package/src/components/ui/Toaster.tsx +18 -0
- package/src/components/ui/icons.tsx +112 -0
- package/src/components/users/UserDetail.tsx +290 -0
- package/src/components/users/UserForm.tsx +242 -0
- package/src/components/users/UsersList.tsx +338 -0
- package/src/env.d.ts +13 -13
- package/src/fields/index.ts +2 -1
- package/src/global.d.ts +7 -0
- package/src/hooks/data.ts +2 -9
- package/src/hooks/useAsyncData.ts +36 -0
- package/src/hooks/useAutoFormState.ts +527 -0
- package/src/hooks/useSelection.ts +49 -0
- package/src/hooks/useSession.ts +0 -0
- package/src/index.ts +11 -1
- package/src/integration.ts +86 -11
- package/src/kyro-cms.d.ts +209 -0
- package/src/layouts/AdminLayout.astro +128 -11
- package/src/layouts/AuthLayout.astro +21 -5
- package/src/lib/api.ts +175 -55
- package/src/lib/autoform-store.ts +435 -0
- package/src/lib/config.ts +82 -34
- package/src/lib/createRegistry.ts +29 -0
- package/src/lib/default-kyro-config.ts +4 -0
- package/src/lib/globals.ts +50 -0
- package/src/lib/media-utils.ts +18 -0
- package/src/lib/object-utils.ts +77 -0
- package/src/lib/paths.ts +61 -0
- package/src/lib/stores/index.ts +370 -0
- package/src/lib/types.ts +43 -0
- package/src/lib/useResourceManager.ts +105 -0
- package/src/pages/403.astro +67 -0
- package/src/pages/[collection]/[id].astro +14 -180
- package/src/pages/[collection]/index.astro +11 -6
- package/src/pages/api-explorer.astro +173 -0
- package/src/pages/audit/index.astro +2 -0
- package/src/pages/auth/login.astro +122 -0
- package/src/pages/auth/register.astro +167 -0
- package/src/pages/graphql-explorer.astro +59 -0
- package/src/pages/{admin/graphql.astro → graphql.astro} +51 -17
- package/src/pages/index.astro +577 -0
- package/src/pages/index_ALT.astro +3 -0
- package/src/pages/keys.astro +11 -0
- package/src/pages/marketplace.astro +11 -0
- package/src/pages/media.astro +3 -0
- package/src/pages/plugins.astro +8 -0
- package/src/pages/preview/[collection]/[id].astro +188 -123
- package/src/pages/rest-playground.astro +62 -0
- package/src/pages/roles/index.astro +183 -76
- package/src/pages/sessions.astro +8 -0
- package/src/pages/settings/[slug].astro +92 -114
- package/src/pages/settings/index.astro +5 -3
- package/src/pages/users/[id].astro +25 -154
- package/src/pages/users/index.astro +19 -130
- package/src/pages/users/new.astro +9 -86
- package/src/pages/webhooks.astro +11 -0
- package/src/routes.ts +80 -0
- package/src/styles/main.css +119 -79
- package/src/theme/tokens.ts +1 -0
- package/src/vite-env.d.ts +14 -0
- package/src/collections/auth/index.ts +0 -155
- package/src/collections/portfolio/index.ts +0 -343
- package/src/components/ApiExplorer.tsx +0 -325
- package/src/components/EnhancedListView.tsx +0 -889
- package/src/components/GraphQLExplorer.tsx +0 -675
- package/src/components/Icons.tsx +0 -23
- package/src/components/StatusBadge.tsx +0 -76
- package/src/lib/MediaService.ts +0 -541
- package/src/lib/auth/sqlite-adapter.ts +0 -319
- package/src/lib/dataStore.ts +0 -226
- package/src/lib/db/adapter.ts +0 -54
- package/src/lib/db/drizzle-mysql-adapter.ts +0 -194
- package/src/lib/db/drizzle-mysql-auth-adapter.ts +0 -327
- package/src/lib/db/drizzle-postgres-adapter.ts +0 -202
- package/src/lib/db/drizzle-postgres-auth-adapter.ts +0 -304
- package/src/lib/db/drizzle-sqlite-adapter.ts +0 -227
- package/src/lib/db/drizzle-sqlite-auth-adapter.ts +0 -548
- package/src/lib/db/index.ts +0 -449
- package/src/lib/db/mongodb-adapter.ts +0 -207
- package/src/lib/db/mongodb-auth-adapter.ts +0 -305
- package/src/lib/db/schema/mysql-auth.ts +0 -113
- package/src/lib/db/schema/mysql-content.ts +0 -20
- package/src/lib/db/schema/postgres-auth.ts +0 -116
- package/src/lib/db/schema/postgres-content.ts +0 -35
- package/src/lib/db/schema/postgres-media.ts +0 -52
- package/src/lib/db/schema/postgres-settings.ts +0 -11
- package/src/lib/db/schema/sqlite-auth.ts +0 -112
- package/src/lib/db/schema/sqlite-content.ts +0 -20
- package/src/lib/db/version-adapter.ts +0 -248
- package/src/lib/graphql/index.ts +0 -1
- package/src/lib/graphql/schema.ts +0 -443
- package/src/lib/rate-limit.ts +0 -267
- package/src/lib/storage.ts +0 -374
- package/src/lib/store.ts +0 -85
- package/src/middleware.ts +0 -177
- package/src/pages/admin/api-explorer.astro +0 -98
- package/src/pages/admin/graphql-explorer.astro +0 -40
- package/src/pages/admin/index.astro +0 -286
- package/src/pages/admin/keys.astro +0 -8
- package/src/pages/admin/rest-playground.astro +0 -44
- package/src/pages/admin/webhooks.astro +0 -8
- package/src/pages/api/[collection]/[id]/publish.ts +0 -52
- package/src/pages/api/[collection]/[id]/unpublish.ts +0 -42
- package/src/pages/api/[collection]/[id]/versions.ts +0 -66
- package/src/pages/api/[collection]/[id].ts +0 -213
- package/src/pages/api/[collection]/index.ts +0 -209
- package/src/pages/api/auth/[id].ts +0 -121
- package/src/pages/api/auth/audit-logs.ts +0 -57
- package/src/pages/api/auth/login.ts +0 -211
- package/src/pages/api/auth/logout.ts +0 -66
- package/src/pages/api/auth/me.ts +0 -36
- package/src/pages/api/auth/refresh.ts +0 -119
- package/src/pages/api/auth/register.ts +0 -188
- package/src/pages/api/auth/users.ts +0 -97
- package/src/pages/api/collections.ts +0 -59
- package/src/pages/api/globals/[slug].ts +0 -42
- package/src/pages/api/graphql.ts +0 -90
- package/src/pages/api/health.ts +0 -426
- package/src/pages/api/keys/[id].ts +0 -26
- package/src/pages/api/keys/index.ts +0 -75
- package/src/pages/api/media/[id].ts +0 -309
- package/src/pages/api/media/folders.ts +0 -609
- package/src/pages/api/media/index.ts +0 -146
- package/src/pages/api/media/resize.ts +0 -267
- package/src/pages/api/search.ts +0 -82
- package/src/pages/api/slug-availability.ts +0 -70
- package/src/pages/api/storage-config.ts +0 -20
- package/src/pages/api/storage-status.ts +0 -206
- package/src/pages/api/upload.ts +0 -334
- package/src/pages/api/webhooks/index.ts +0 -71
- package/src/pages/login.astro +0 -82
- 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
|
-
};
|