@delmaredigital/payload-puck 0.1.0
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/LICENSE +73 -0
- package/README.md +1580 -0
- package/dist/AccordionClient.d.mts +24 -0
- package/dist/AccordionClient.d.ts +24 -0
- package/dist/AccordionClient.js +786 -0
- package/dist/AccordionClient.js.map +1 -0
- package/dist/AccordionClient.mjs +784 -0
- package/dist/AccordionClient.mjs.map +1 -0
- package/dist/AnimatedWrapper.d.mts +30 -0
- package/dist/AnimatedWrapper.d.ts +30 -0
- package/dist/AnimatedWrapper.js +379 -0
- package/dist/AnimatedWrapper.js.map +1 -0
- package/dist/AnimatedWrapper.mjs +377 -0
- package/dist/AnimatedWrapper.mjs.map +1 -0
- package/dist/admin/client.d.mts +108 -0
- package/dist/admin/client.d.ts +108 -0
- package/dist/admin/client.js +177 -0
- package/dist/admin/client.js.map +1 -0
- package/dist/admin/client.mjs +173 -0
- package/dist/admin/client.mjs.map +1 -0
- package/dist/admin/index.d.mts +157 -0
- package/dist/admin/index.d.ts +157 -0
- package/dist/admin/index.js +31 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/index.mjs +29 -0
- package/dist/admin/index.mjs.map +1 -0
- package/dist/api/index.d.mts +460 -0
- package/dist/api/index.d.ts +460 -0
- package/dist/api/index.js +588 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/index.mjs +578 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/components/index.css +339 -0
- package/dist/components/index.css.map +1 -0
- package/dist/components/index.d.mts +222 -0
- package/dist/components/index.d.ts +222 -0
- package/dist/components/index.js +9177 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +9130 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/config/config.editor.css +339 -0
- package/dist/config/config.editor.css.map +1 -0
- package/dist/config/config.editor.d.mts +153 -0
- package/dist/config/config.editor.d.ts +153 -0
- package/dist/config/config.editor.js +9400 -0
- package/dist/config/config.editor.js.map +1 -0
- package/dist/config/config.editor.mjs +9368 -0
- package/dist/config/config.editor.mjs.map +1 -0
- package/dist/config/index.d.mts +68 -0
- package/dist/config/index.d.ts +68 -0
- package/dist/config/index.js +2017 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.mjs +1991 -0
- package/dist/config/index.mjs.map +1 -0
- package/dist/editor/index.d.mts +784 -0
- package/dist/editor/index.d.ts +784 -0
- package/dist/editor/index.js +4517 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/editor/index.mjs +4483 -0
- package/dist/editor/index.mjs.map +1 -0
- package/dist/fields/index.css +339 -0
- package/dist/fields/index.css.map +1 -0
- package/dist/fields/index.d.mts +600 -0
- package/dist/fields/index.d.ts +600 -0
- package/dist/fields/index.js +7739 -0
- package/dist/fields/index.js.map +1 -0
- package/dist/fields/index.mjs +7590 -0
- package/dist/fields/index.mjs.map +1 -0
- package/dist/index-CQu6SzDg.d.mts +327 -0
- package/dist/index-CoUQnyC3.d.ts +327 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +569 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +555 -0
- package/dist/index.mjs.map +1 -0
- package/dist/layouts/index.d.mts +96 -0
- package/dist/layouts/index.d.ts +96 -0
- package/dist/layouts/index.js +394 -0
- package/dist/layouts/index.js.map +1 -0
- package/dist/layouts/index.mjs +378 -0
- package/dist/layouts/index.mjs.map +1 -0
- package/dist/plugin/index.d.mts +289 -0
- package/dist/plugin/index.d.ts +289 -0
- package/dist/plugin/index.js +569 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/index.mjs +555 -0
- package/dist/plugin/index.mjs.map +1 -0
- package/dist/render/index.d.mts +109 -0
- package/dist/render/index.d.ts +109 -0
- package/dist/render/index.js +2146 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/index.mjs +2123 -0
- package/dist/render/index.mjs.map +1 -0
- package/dist/shared-DMAF1AcH.d.mts +545 -0
- package/dist/shared-DMAF1AcH.d.ts +545 -0
- package/dist/theme/index.d.mts +155 -0
- package/dist/theme/index.d.ts +155 -0
- package/dist/theme/index.js +201 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/index.mjs +186 -0
- package/dist/theme/index.mjs.map +1 -0
- package/dist/types-D7D3rZ1J.d.mts +116 -0
- package/dist/types-D7D3rZ1J.d.ts +116 -0
- package/dist/types-_6MvjyKv.d.mts +104 -0
- package/dist/types-_6MvjyKv.d.ts +104 -0
- package/dist/utils/index.d.mts +267 -0
- package/dist/utils/index.d.ts +267 -0
- package/dist/utils/index.js +426 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +412 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils-DaRs9t0J.d.mts +85 -0
- package/dist/utils-gAvt0Vhw.d.ts +85 -0
- package/examples/README.md +240 -0
- package/examples/api/puck/pages/[id]/route.ts +64 -0
- package/examples/api/puck/pages/[id]/versions/route.ts +47 -0
- package/examples/api/puck/pages/route.ts +45 -0
- package/examples/app/(frontend)/page.tsx +94 -0
- package/examples/app/[...slug]/page.tsx +101 -0
- package/examples/app/pages/[id]/edit/page.tsx +148 -0
- package/examples/components/CustomBanner.tsx +368 -0
- package/examples/config/custom-config.ts +223 -0
- package/examples/config/payload.config.example.ts +64 -0
- package/examples/lib/puck-layouts.ts +258 -0
- package/examples/lib/puck-theme.ts +94 -0
- package/examples/styles/puck-theme.css +171 -0
- package/package.json +157 -0
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getPayload } from 'payload';
|
|
3
|
+
|
|
4
|
+
// src/api/createPuckApiRoutes.ts
|
|
5
|
+
var DEFAULT_PUCK_DATA = {
|
|
6
|
+
root: {
|
|
7
|
+
props: {
|
|
8
|
+
title: ""
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
content: [],
|
|
12
|
+
zones: {}
|
|
13
|
+
};
|
|
14
|
+
function createPuckApiRoutes(routeConfig) {
|
|
15
|
+
const {
|
|
16
|
+
collection = "pages",
|
|
17
|
+
payloadConfig,
|
|
18
|
+
auth,
|
|
19
|
+
defaultPuckData = DEFAULT_PUCK_DATA,
|
|
20
|
+
enableDrafts = true,
|
|
21
|
+
onError
|
|
22
|
+
} = routeConfig;
|
|
23
|
+
async function GET(request, _context) {
|
|
24
|
+
try {
|
|
25
|
+
const authResult = await auth.authenticate(request);
|
|
26
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
27
|
+
return NextResponse.json(
|
|
28
|
+
{ error: authResult.error || "Unauthorized" },
|
|
29
|
+
{ status: 401 }
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
if (auth.canList) {
|
|
33
|
+
const permission = await auth.canList(authResult.user);
|
|
34
|
+
if (!permission.allowed) {
|
|
35
|
+
return NextResponse.json(
|
|
36
|
+
{ error: permission.error || "Forbidden" },
|
|
37
|
+
{ status: 403 }
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const { searchParams } = new URL(request.url);
|
|
42
|
+
const page = parseInt(searchParams.get("page") || "1", 10);
|
|
43
|
+
const limit = Math.min(parseInt(searchParams.get("limit") || "10", 10), 100);
|
|
44
|
+
const search = searchParams.get("search") || "";
|
|
45
|
+
const status = searchParams.get("status");
|
|
46
|
+
const editorVersion = searchParams.get("editorVersion");
|
|
47
|
+
const sort = searchParams.get("sort") || "-updatedAt";
|
|
48
|
+
const config = await payloadConfig;
|
|
49
|
+
const payload = await getPayload({ config });
|
|
50
|
+
const conditions = [];
|
|
51
|
+
if (search) {
|
|
52
|
+
conditions.push({ title: { contains: search } });
|
|
53
|
+
}
|
|
54
|
+
if (status && status !== "all") {
|
|
55
|
+
conditions.push({ _status: { equals: status } });
|
|
56
|
+
}
|
|
57
|
+
if (editorVersion && editorVersion !== "all") {
|
|
58
|
+
conditions.push({ editorVersion: { equals: editorVersion } });
|
|
59
|
+
}
|
|
60
|
+
const where = conditions.length > 0 ? conditions.length === 1 ? conditions[0] : { and: conditions } : void 0;
|
|
61
|
+
const result = await payload.find({
|
|
62
|
+
collection,
|
|
63
|
+
page,
|
|
64
|
+
limit,
|
|
65
|
+
sort,
|
|
66
|
+
where
|
|
67
|
+
});
|
|
68
|
+
return NextResponse.json(result);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (onError) {
|
|
71
|
+
onError(error, { operation: "list", request });
|
|
72
|
+
}
|
|
73
|
+
console.error("Error listing pages:", error);
|
|
74
|
+
return NextResponse.json(
|
|
75
|
+
{ error: "Failed to list pages" },
|
|
76
|
+
{ status: 500 }
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function POST(request, _context) {
|
|
81
|
+
try {
|
|
82
|
+
const authResult = await auth.authenticate(request);
|
|
83
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
84
|
+
return NextResponse.json(
|
|
85
|
+
{ error: authResult.error || "Unauthorized" },
|
|
86
|
+
{ status: 401 }
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
if (auth.canCreate) {
|
|
90
|
+
const permission = await auth.canCreate(authResult.user);
|
|
91
|
+
if (!permission.allowed) {
|
|
92
|
+
return NextResponse.json(
|
|
93
|
+
{ error: permission.error || "Forbidden" },
|
|
94
|
+
{ status: 403 }
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const body = await request.json();
|
|
99
|
+
const { title, slug, puckData, status = "draft" } = body;
|
|
100
|
+
if (!title || !slug) {
|
|
101
|
+
return NextResponse.json(
|
|
102
|
+
{ error: "Title and slug are required" },
|
|
103
|
+
{ status: 400 }
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const config = await payloadConfig;
|
|
107
|
+
const payload = await getPayload({ config });
|
|
108
|
+
const existing = await payload.find({
|
|
109
|
+
collection,
|
|
110
|
+
where: { slug: { equals: slug } },
|
|
111
|
+
limit: 1
|
|
112
|
+
});
|
|
113
|
+
if (existing.docs.length > 0) {
|
|
114
|
+
return NextResponse.json(
|
|
115
|
+
{ error: "A page with this slug already exists" },
|
|
116
|
+
{ status: 409 }
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
const initialPuckData = puckData || {
|
|
120
|
+
...defaultPuckData,
|
|
121
|
+
root: {
|
|
122
|
+
...defaultPuckData.root,
|
|
123
|
+
props: {
|
|
124
|
+
...defaultPuckData.root?.props,
|
|
125
|
+
title
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const newPage = await payload.create({
|
|
130
|
+
collection,
|
|
131
|
+
draft: enableDrafts,
|
|
132
|
+
data: {
|
|
133
|
+
title,
|
|
134
|
+
slug,
|
|
135
|
+
editorVersion: "puck",
|
|
136
|
+
puckData: initialPuckData,
|
|
137
|
+
_status: status
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
return NextResponse.json({ doc: newPage }, { status: 201 });
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (onError) {
|
|
143
|
+
onError(error, { operation: "create", request });
|
|
144
|
+
}
|
|
145
|
+
console.error("Error creating page:", error);
|
|
146
|
+
return NextResponse.json(
|
|
147
|
+
{ error: "Failed to create page" },
|
|
148
|
+
{ status: 500 }
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { GET, POST };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/api/utils/mapRootProps.ts
|
|
156
|
+
var DEFAULT_ROOT_PROPS_MAPPINGS = [
|
|
157
|
+
// Core page fields
|
|
158
|
+
{ from: "title", to: "title" },
|
|
159
|
+
{ from: "slug", to: "slug" },
|
|
160
|
+
{ from: "pageLayout", to: "pageLayout" },
|
|
161
|
+
{ from: "pageType", to: "pageType" },
|
|
162
|
+
{ from: "isHomepage", to: "isHomepage" },
|
|
163
|
+
// SEO/Meta fields (uses official @payloadcms/plugin-seo convention)
|
|
164
|
+
{ from: "metaTitle", to: "meta.title" },
|
|
165
|
+
{ from: "metaDescription", to: "meta.description" },
|
|
166
|
+
{ from: "noindex", to: "meta.noindex" },
|
|
167
|
+
{ from: "nofollow", to: "meta.nofollow" },
|
|
168
|
+
{ from: "excludeFromSitemap", to: "meta.excludeFromSitemap" },
|
|
169
|
+
// Conversion tracking fields
|
|
170
|
+
{ from: "isConversionPage", to: "conversionTracking.isConversionPage" },
|
|
171
|
+
{ from: "conversionType", to: "conversionTracking.conversionType" },
|
|
172
|
+
{ from: "conversionValue", to: "conversionTracking.conversionValue" }
|
|
173
|
+
];
|
|
174
|
+
function setNestedValue(obj, path, value) {
|
|
175
|
+
const keys = path.split(".");
|
|
176
|
+
let current = obj;
|
|
177
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
178
|
+
const key = keys[i];
|
|
179
|
+
if (!(key in current) || typeof current[key] !== "object") {
|
|
180
|
+
current[key] = {};
|
|
181
|
+
}
|
|
182
|
+
current = current[key];
|
|
183
|
+
}
|
|
184
|
+
const finalKey = keys[keys.length - 1];
|
|
185
|
+
current[finalKey] = value;
|
|
186
|
+
}
|
|
187
|
+
function getNestedValue(obj, path) {
|
|
188
|
+
const keys = path.split(".");
|
|
189
|
+
let current = obj;
|
|
190
|
+
for (const key of keys) {
|
|
191
|
+
if (current === null || current === void 0) {
|
|
192
|
+
return void 0;
|
|
193
|
+
}
|
|
194
|
+
if (typeof current !== "object") {
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
current = current[key];
|
|
198
|
+
}
|
|
199
|
+
return current;
|
|
200
|
+
}
|
|
201
|
+
function mergeMappings(customMappings) {
|
|
202
|
+
if (!customMappings || customMappings.length === 0) {
|
|
203
|
+
return DEFAULT_ROOT_PROPS_MAPPINGS;
|
|
204
|
+
}
|
|
205
|
+
const mappingMap = /* @__PURE__ */ new Map();
|
|
206
|
+
for (const mapping of DEFAULT_ROOT_PROPS_MAPPINGS) {
|
|
207
|
+
mappingMap.set(mapping.from, mapping);
|
|
208
|
+
}
|
|
209
|
+
for (const mapping of customMappings) {
|
|
210
|
+
mappingMap.set(mapping.from, mapping);
|
|
211
|
+
}
|
|
212
|
+
return Array.from(mappingMap.values());
|
|
213
|
+
}
|
|
214
|
+
function mapRootPropsToPayloadFields(rootProps, customMappings) {
|
|
215
|
+
const mappings = mergeMappings(customMappings);
|
|
216
|
+
const result = {};
|
|
217
|
+
for (const mapping of mappings) {
|
|
218
|
+
const value = rootProps[mapping.from];
|
|
219
|
+
if (value === void 0) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const transformedValue = mapping.transform ? mapping.transform(value) : value;
|
|
223
|
+
setNestedValue(result, mapping.to, transformedValue);
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
function deepMerge(target, source) {
|
|
228
|
+
for (const key of Object.keys(source)) {
|
|
229
|
+
const sourceValue = source[key];
|
|
230
|
+
const targetValue = target[key];
|
|
231
|
+
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
232
|
+
target[key] = deepMerge(
|
|
233
|
+
targetValue,
|
|
234
|
+
sourceValue
|
|
235
|
+
);
|
|
236
|
+
} else {
|
|
237
|
+
target[key] = sourceValue;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return target;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// src/api/createPuckApiRoutesWithId.ts
|
|
244
|
+
function createPuckApiRoutesWithId(routeConfig) {
|
|
245
|
+
const {
|
|
246
|
+
collection = "pages",
|
|
247
|
+
payloadConfig,
|
|
248
|
+
auth,
|
|
249
|
+
rootPropsMapping,
|
|
250
|
+
onError
|
|
251
|
+
} = routeConfig;
|
|
252
|
+
async function GET(request, context) {
|
|
253
|
+
try {
|
|
254
|
+
const params = await context.params;
|
|
255
|
+
const id = params.id;
|
|
256
|
+
if (!id) {
|
|
257
|
+
return NextResponse.json(
|
|
258
|
+
{ error: "Page ID is required" },
|
|
259
|
+
{ status: 400 }
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
const authResult = await auth.authenticate(request);
|
|
263
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
264
|
+
return NextResponse.json(
|
|
265
|
+
{ error: authResult.error || "Unauthorized" },
|
|
266
|
+
{ status: 401 }
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (auth.canView) {
|
|
270
|
+
const permission = await auth.canView(authResult.user, id);
|
|
271
|
+
if (!permission.allowed) {
|
|
272
|
+
return NextResponse.json(
|
|
273
|
+
{ error: permission.error || "Forbidden" },
|
|
274
|
+
{ status: 403 }
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const config = await payloadConfig;
|
|
279
|
+
const payload = await getPayload({ config });
|
|
280
|
+
const url = new URL(request.url);
|
|
281
|
+
const wantsDraft = url.searchParams.get("draft") !== "false";
|
|
282
|
+
const page = await payload.findByID({
|
|
283
|
+
collection,
|
|
284
|
+
id,
|
|
285
|
+
draft: wantsDraft
|
|
286
|
+
// Load draft version by default for editing
|
|
287
|
+
});
|
|
288
|
+
if (!page) {
|
|
289
|
+
return NextResponse.json({ error: "Page not found" }, { status: 404 });
|
|
290
|
+
}
|
|
291
|
+
return NextResponse.json({ doc: page });
|
|
292
|
+
} catch (error) {
|
|
293
|
+
const params = await context.params;
|
|
294
|
+
if (onError) {
|
|
295
|
+
onError(error, { operation: "read", request, pageId: params.id });
|
|
296
|
+
}
|
|
297
|
+
console.error("Error fetching page:", error);
|
|
298
|
+
return NextResponse.json(
|
|
299
|
+
{ error: "Failed to fetch page" },
|
|
300
|
+
{ status: 500 }
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
async function PATCH(request, context) {
|
|
305
|
+
try {
|
|
306
|
+
const params = await context.params;
|
|
307
|
+
const id = params.id;
|
|
308
|
+
if (!id) {
|
|
309
|
+
return NextResponse.json(
|
|
310
|
+
{ error: "Page ID is required" },
|
|
311
|
+
{ status: 400 }
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
const authResult = await auth.authenticate(request);
|
|
315
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
316
|
+
return NextResponse.json(
|
|
317
|
+
{ error: authResult.error || "Unauthorized" },
|
|
318
|
+
{ status: 401 }
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
if (auth.canEdit) {
|
|
322
|
+
const permission = await auth.canEdit(authResult.user, id);
|
|
323
|
+
if (!permission.allowed) {
|
|
324
|
+
return NextResponse.json(
|
|
325
|
+
{ error: permission.error || "Forbidden" },
|
|
326
|
+
{ status: 403 }
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const body = await request.json();
|
|
331
|
+
const { puckData, title, slug, status, draft } = body;
|
|
332
|
+
if (status === "published") {
|
|
333
|
+
const canPublish = auth.canPublish || auth.canEdit;
|
|
334
|
+
if (canPublish) {
|
|
335
|
+
const permission = await canPublish(authResult.user, id);
|
|
336
|
+
if (!permission.allowed) {
|
|
337
|
+
return NextResponse.json(
|
|
338
|
+
{ error: permission.error || "Not authorized to publish pages" },
|
|
339
|
+
{ status: 403 }
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const config = await payloadConfig;
|
|
345
|
+
const payload = await getPayload({ config });
|
|
346
|
+
const rootProps = puckData?.root?.props || {};
|
|
347
|
+
const updateData = {
|
|
348
|
+
editorVersion: "puck"
|
|
349
|
+
};
|
|
350
|
+
if (puckData) {
|
|
351
|
+
updateData.puckData = puckData;
|
|
352
|
+
}
|
|
353
|
+
const mappedFields = mapRootPropsToPayloadFields(rootProps, rootPropsMapping);
|
|
354
|
+
deepMerge(updateData, mappedFields);
|
|
355
|
+
if (title !== void 0) {
|
|
356
|
+
updateData.title = title;
|
|
357
|
+
}
|
|
358
|
+
if (slug !== void 0) {
|
|
359
|
+
updateData.slug = slug;
|
|
360
|
+
}
|
|
361
|
+
if (status) {
|
|
362
|
+
updateData._status = status;
|
|
363
|
+
}
|
|
364
|
+
const updatedPage = await payload.update({
|
|
365
|
+
collection,
|
|
366
|
+
id,
|
|
367
|
+
data: updateData,
|
|
368
|
+
draft: draft === true
|
|
369
|
+
});
|
|
370
|
+
return NextResponse.json({ doc: updatedPage });
|
|
371
|
+
} catch (error) {
|
|
372
|
+
const params = await context.params;
|
|
373
|
+
if (onError) {
|
|
374
|
+
onError(error, { operation: "update", request, pageId: params.id });
|
|
375
|
+
}
|
|
376
|
+
console.error("Error updating page:", error);
|
|
377
|
+
if (error instanceof Error && error.name === "ValidationError") {
|
|
378
|
+
const validationError = error;
|
|
379
|
+
const fieldErrors = validationError.data?.errors || [];
|
|
380
|
+
const slugError = fieldErrors.find((e) => e.field === "slug");
|
|
381
|
+
if (slugError) {
|
|
382
|
+
return NextResponse.json(
|
|
383
|
+
{
|
|
384
|
+
error: "A page with this slug already exists. Please choose a different slug.",
|
|
385
|
+
field: "slug",
|
|
386
|
+
details: fieldErrors
|
|
387
|
+
},
|
|
388
|
+
{ status: 400 }
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return NextResponse.json(
|
|
392
|
+
{
|
|
393
|
+
error: `Validation failed: ${fieldErrors.map((e) => e.message || e.field).join(", ")}`,
|
|
394
|
+
details: fieldErrors
|
|
395
|
+
},
|
|
396
|
+
{ status: 400 }
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
return NextResponse.json(
|
|
400
|
+
{ error: "Failed to update page" },
|
|
401
|
+
{ status: 500 }
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
async function DELETE(request, context) {
|
|
406
|
+
try {
|
|
407
|
+
const params = await context.params;
|
|
408
|
+
const id = params.id;
|
|
409
|
+
if (!id) {
|
|
410
|
+
return NextResponse.json(
|
|
411
|
+
{ error: "Page ID is required" },
|
|
412
|
+
{ status: 400 }
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
const authResult = await auth.authenticate(request);
|
|
416
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
417
|
+
return NextResponse.json(
|
|
418
|
+
{ error: authResult.error || "Unauthorized" },
|
|
419
|
+
{ status: 401 }
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
if (auth.canDelete) {
|
|
423
|
+
const permission = await auth.canDelete(authResult.user, id);
|
|
424
|
+
if (!permission.allowed) {
|
|
425
|
+
return NextResponse.json(
|
|
426
|
+
{ error: permission.error || "Forbidden" },
|
|
427
|
+
{ status: 403 }
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
const config = await payloadConfig;
|
|
432
|
+
const payload = await getPayload({ config });
|
|
433
|
+
await payload.delete({
|
|
434
|
+
collection,
|
|
435
|
+
id
|
|
436
|
+
});
|
|
437
|
+
return NextResponse.json({ success: true });
|
|
438
|
+
} catch (error) {
|
|
439
|
+
const params = await context.params;
|
|
440
|
+
if (onError) {
|
|
441
|
+
onError(error, { operation: "delete", request, pageId: params.id });
|
|
442
|
+
}
|
|
443
|
+
console.error("Error deleting page:", error);
|
|
444
|
+
return NextResponse.json(
|
|
445
|
+
{ error: "Failed to delete page" },
|
|
446
|
+
{ status: 500 }
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return { GET, PATCH, DELETE };
|
|
451
|
+
}
|
|
452
|
+
function createPuckApiRoutesVersions(routeConfig) {
|
|
453
|
+
const {
|
|
454
|
+
collection = "pages",
|
|
455
|
+
payloadConfig,
|
|
456
|
+
auth,
|
|
457
|
+
onError
|
|
458
|
+
} = routeConfig;
|
|
459
|
+
async function GET(request, context) {
|
|
460
|
+
try {
|
|
461
|
+
const params = await context.params;
|
|
462
|
+
const id = params.id;
|
|
463
|
+
if (!id) {
|
|
464
|
+
return NextResponse.json(
|
|
465
|
+
{ error: "Page ID is required" },
|
|
466
|
+
{ status: 400 }
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
const authResult = await auth.authenticate(request);
|
|
470
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
471
|
+
return NextResponse.json(
|
|
472
|
+
{ error: authResult.error || "Unauthorized" },
|
|
473
|
+
{ status: 401 }
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
if (auth.canView) {
|
|
477
|
+
const permission = await auth.canView(authResult.user, id);
|
|
478
|
+
if (!permission.allowed) {
|
|
479
|
+
return NextResponse.json(
|
|
480
|
+
{ error: permission.error || "Forbidden" },
|
|
481
|
+
{ status: 403 }
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const config = await payloadConfig;
|
|
486
|
+
const payload = await getPayload({ config });
|
|
487
|
+
const url = new URL(request.url);
|
|
488
|
+
const limit = parseInt(url.searchParams.get("limit") || "20", 10);
|
|
489
|
+
const page = parseInt(url.searchParams.get("page") || "1", 10);
|
|
490
|
+
const versions = await payload.findVersions({
|
|
491
|
+
collection,
|
|
492
|
+
where: {
|
|
493
|
+
parent: { equals: id }
|
|
494
|
+
},
|
|
495
|
+
sort: "-updatedAt",
|
|
496
|
+
limit,
|
|
497
|
+
page
|
|
498
|
+
});
|
|
499
|
+
return NextResponse.json({
|
|
500
|
+
docs: versions.docs,
|
|
501
|
+
totalDocs: versions.totalDocs,
|
|
502
|
+
totalPages: versions.totalPages,
|
|
503
|
+
page: versions.page,
|
|
504
|
+
limit: versions.limit,
|
|
505
|
+
hasPrevPage: versions.hasPrevPage,
|
|
506
|
+
hasNextPage: versions.hasNextPage
|
|
507
|
+
});
|
|
508
|
+
} catch (error) {
|
|
509
|
+
const params = await context.params;
|
|
510
|
+
if (onError) {
|
|
511
|
+
onError(error, { operation: "listVersions", request, pageId: params.id });
|
|
512
|
+
}
|
|
513
|
+
console.error("Error fetching versions:", error);
|
|
514
|
+
return NextResponse.json(
|
|
515
|
+
{ error: "Failed to fetch versions" },
|
|
516
|
+
{ status: 500 }
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
async function POST(request, context) {
|
|
521
|
+
try {
|
|
522
|
+
const params = await context.params;
|
|
523
|
+
const id = params.id;
|
|
524
|
+
if (!id) {
|
|
525
|
+
return NextResponse.json(
|
|
526
|
+
{ error: "Page ID is required" },
|
|
527
|
+
{ status: 400 }
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
const authResult = await auth.authenticate(request);
|
|
531
|
+
if (!authResult.authenticated || !authResult.user) {
|
|
532
|
+
return NextResponse.json(
|
|
533
|
+
{ error: authResult.error || "Unauthorized" },
|
|
534
|
+
{ status: 401 }
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
if (auth.canEdit) {
|
|
538
|
+
const permission = await auth.canEdit(authResult.user, id);
|
|
539
|
+
if (!permission.allowed) {
|
|
540
|
+
return NextResponse.json(
|
|
541
|
+
{ error: permission.error || "Forbidden" },
|
|
542
|
+
{ status: 403 }
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const body = await request.json();
|
|
547
|
+
const { versionId } = body;
|
|
548
|
+
if (!versionId) {
|
|
549
|
+
return NextResponse.json(
|
|
550
|
+
{ error: "Version ID is required" },
|
|
551
|
+
{ status: 400 }
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
const config = await payloadConfig;
|
|
555
|
+
const payload = await getPayload({ config });
|
|
556
|
+
const restoredDoc = await payload.restoreVersion({
|
|
557
|
+
collection,
|
|
558
|
+
id: versionId
|
|
559
|
+
});
|
|
560
|
+
return NextResponse.json({ doc: restoredDoc });
|
|
561
|
+
} catch (error) {
|
|
562
|
+
const params = await context.params;
|
|
563
|
+
if (onError) {
|
|
564
|
+
onError(error, { operation: "restoreVersion", request, pageId: params.id });
|
|
565
|
+
}
|
|
566
|
+
console.error("Error restoring version:", error);
|
|
567
|
+
return NextResponse.json(
|
|
568
|
+
{ error: "Failed to restore version" },
|
|
569
|
+
{ status: 500 }
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return { GET, POST };
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
export { DEFAULT_ROOT_PROPS_MAPPINGS, createPuckApiRoutes, createPuckApiRoutesVersions, createPuckApiRoutesWithId, deepMerge, getNestedValue, mapRootPropsToPayloadFields, mergeMappings, setNestedValue };
|
|
577
|
+
//# sourceMappingURL=index.mjs.map
|
|
578
|
+
//# sourceMappingURL=index.mjs.map
|