@payload-onpage/plugin 0.0.0-stage → 0.2.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -2
  3. package/dist/access.d.ts +20 -0
  4. package/dist/access.d.ts.map +1 -0
  5. package/dist/access.js +51 -0
  6. package/dist/access.js.map +1 -0
  7. package/dist/admin/OnPageAdminControls.d.ts +9 -0
  8. package/dist/admin/OnPageAdminControls.d.ts.map +1 -0
  9. package/dist/admin/OnPageAdminControls.js +59 -0
  10. package/dist/admin/OnPageAdminControls.js.map +1 -0
  11. package/dist/admin/index.d.ts +3 -0
  12. package/dist/admin/index.d.ts.map +1 -0
  13. package/dist/admin/index.js +2 -0
  14. package/dist/admin/index.js.map +1 -0
  15. package/dist/endpoints.d.ts +11 -0
  16. package/dist/endpoints.d.ts.map +1 -0
  17. package/dist/endpoints.js +223 -0
  18. package/dist/endpoints.js.map +1 -0
  19. package/dist/hooks.d.ts +38 -0
  20. package/dist/hooks.d.ts.map +1 -0
  21. package/dist/hooks.js +42 -0
  22. package/dist/hooks.js.map +1 -0
  23. package/dist/http.d.ts +23 -0
  24. package/dist/http.d.ts.map +1 -0
  25. package/dist/http.js +53 -0
  26. package/dist/http.js.map +1 -0
  27. package/dist/index.d.ts +10 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +148 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/options.d.ts +59 -0
  32. package/dist/options.d.ts.map +1 -0
  33. package/dist/options.js +4 -0
  34. package/dist/options.js.map +1 -0
  35. package/dist/paths.d.ts +11 -0
  36. package/dist/paths.d.ts.map +1 -0
  37. package/dist/paths.js +58 -0
  38. package/dist/paths.js.map +1 -0
  39. package/dist/schema.d.ts +34 -0
  40. package/dist/schema.d.ts.map +1 -0
  41. package/dist/schema.js +209 -0
  42. package/dist/schema.js.map +1 -0
  43. package/dist/tokens.d.ts +18 -0
  44. package/dist/tokens.d.ts.map +1 -0
  45. package/dist/tokens.js +24 -0
  46. package/dist/tokens.js.map +1 -0
  47. package/dist/translations.d.ts +45 -0
  48. package/dist/translations.d.ts.map +1 -0
  49. package/dist/translations.js +44 -0
  50. package/dist/translations.js.map +1 -0
  51. package/package.json +65 -4
  52. package/src/access.ts +65 -0
  53. package/src/admin/OnPageAdminControls.tsx +99 -0
  54. package/src/admin/index.ts +2 -0
  55. package/src/endpoints.ts +269 -0
  56. package/src/hooks.ts +79 -0
  57. package/src/http.ts +57 -0
  58. package/src/index.ts +167 -0
  59. package/src/options.ts +65 -0
  60. package/src/paths.ts +59 -0
  61. package/src/schema.ts +251 -0
  62. package/src/tokens.ts +46 -0
  63. package/src/translations.ts +45 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 jellologic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,16 @@
1
- # Temporary Holding Version
1
+ # @payload-onpage/plugin
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The Payload side: endpoints (enter/mode/exit/preview links/schema), access through Payload's own `docAccessOperation`, the editor schema, marker hooks, a stale-write guard, and **Edit on page** / **Copy preview link** in the admin.
4
+
5
+ ```ts
6
+ import { onpage } from '@payload-onpage/plugin'
7
+ import { nextSession } from '@payload-onpage/next/session'
8
+
9
+ plugins: [onpage({ collections: ['pages'], globals: ['header'], session: nextSession() })]
10
+ ```
11
+
12
+ Options: `collections`, `globals` (with per-document `fields` and `url`), `access`, `session`, `encode`, `previewLinkTTL`, `validatePreviewLink`, `secret`, `authCookie`, `routePrefix`, `enabled`. See [security](https://github.com/jellologic/payload-onpage/blob/main/docs/concepts/security.md).
13
+
14
+ Part of [**payload-onpage**](https://github.com/jellologic/payload-onpage): on-page editing and draft previews for Payload CMS + Next.js. Start with the [getting started guide](https://github.com/jellologic/payload-onpage/blob/main/docs/getting-started.md).
15
+
16
+ MIT licensed.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Who may use on-page editing, and edit which documents. Document access is
3
+ * evaluated by Payload itself (`docAccessOperation`), so row-level rules
4
+ * (access functions that return a query) and field permissions behave exactly
5
+ * as in the admin.
6
+ */
7
+ import type { DocRef } from '@payload-onpage/core';
8
+ import { type PayloadRequest, type SanitizedCollectionPermission, type SanitizedGlobalPermission } from 'payload';
9
+ import type { OnPageOptions } from './options.ts';
10
+ /** Signed in as an admin user (or allowed by the `access` option). */
11
+ export declare function canUseOnPage(req: PayloadRequest, options: OnPageOptions): Promise<boolean>;
12
+ /** Payload's sanitized permissions for one document (or the collection, without an id). */
13
+ export declare function documentPermissions(req: PayloadRequest, ref: DocRef | {
14
+ kind: 'collection';
15
+ slug: string;
16
+ id?: undefined;
17
+ }): Promise<SanitizedCollectionPermission | SanitizedGlobalPermission | null>;
18
+ /** May this user edit this document on the page? */
19
+ export declare function canEditDocument(req: PayloadRequest, ref: DocRef, options: OnPageOptions): Promise<boolean>;
20
+ //# sourceMappingURL=access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,6BAA6B,EAClC,KAAK,yBAAyB,EAC/B,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,sEAAsE;AACtE,wBAAsB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhG;AAED,2FAA2F;AAC3F,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,SAAS,CAAA;CAAE,GACjE,OAAO,CAAC,6BAA6B,GAAG,yBAAyB,GAAG,IAAI,CAAC,CAY3E;AAED,oDAAoD;AACpD,wBAAsB,eAAe,CACnC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,OAAO,CAAC,CAkBlB"}
package/dist/access.js ADDED
@@ -0,0 +1,51 @@
1
+ import { docAccessOperation, docAccessOperationGlobal, } from 'payload';
2
+ /** Signed in as an admin user (or allowed by the `access` option). */
3
+ export async function canUseOnPage(req, options) {
4
+ if (!req.user)
5
+ return false;
6
+ if (options.access)
7
+ return Boolean(await options.access({ req }));
8
+ return req.user.collection === req.payload.config.admin.user;
9
+ }
10
+ /** Payload's sanitized permissions for one document (or the collection, without an id). */
11
+ export async function documentPermissions(req, ref) {
12
+ try {
13
+ if (ref.kind === 'global') {
14
+ const globalConfig = req.payload.globals.config.find((g) => g.slug === ref.slug);
15
+ return globalConfig ? await docAccessOperationGlobal({ globalConfig, req }) : null;
16
+ }
17
+ const collection = req.payload.collections[ref.slug];
18
+ if (!collection)
19
+ return null;
20
+ return await docAccessOperation({ collection, id: ref.id, req });
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /** May this user edit this document on the page? */
27
+ export async function canEditDocument(req, ref, options) {
28
+ if (!req.user)
29
+ return false;
30
+ if (options.access)
31
+ return Boolean(await options.access({ req, ref }));
32
+ if (!(await canUseOnPage(req, options)))
33
+ return false;
34
+ const perms = await documentPermissions(req, ref);
35
+ const update = perms?.update;
36
+ if (update === true)
37
+ return true;
38
+ if (!update?.permission)
39
+ return false;
40
+ // A row-level rule comes back as a query: check that this document matches it.
41
+ if (!update.where || ref.kind !== 'collection')
42
+ return !update.where;
43
+ const { totalDocs } = await req.payload.count({
44
+ collection: ref.slug,
45
+ where: { and: [{ id: { equals: ref.id } }, update.where] },
46
+ overrideAccess: true,
47
+ req,
48
+ });
49
+ return totalDocs > 0;
50
+ }
51
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GAIzB,MAAM,SAAS,CAAA;AAGhB,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAmB,EAAE,OAAsB;IAC5E,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IAC3B,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IACjE,OAAO,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAA;AAC9D,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAmB,EACnB,GAAkE;IAElE,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,CAAA;YAChF,OAAO,YAAY,CAAC,CAAC,CAAC,MAAM,wBAAwB,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACpF,CAAC;QACD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACpD,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAA;QAC5B,OAAO,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAmB,EACnB,GAAW,EACX,OAAsB;IAEtB,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IAC3B,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IACtE,IAAI,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IACrD,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,KAAK,EAAE,MACwD,CAAA;IAC9E,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAChC,IAAI,CAAC,MAAM,EAAE,UAAU;QAAE,OAAO,KAAK,CAAA;IACrC,+EAA+E;IAC/E,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;IACpE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;QAC5C,UAAU,EAAE,GAAG,CAAC,IAAa;QAC7B,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EAAW;QACnE,cAAc,EAAE,IAAI;QACpB,GAAG;KACJ,CAAC,CAAA;IACF,OAAO,SAAS,GAAG,CAAC,CAAA;AACtB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface OnPageAdminControlsProps {
2
+ kind: 'collection' | 'global';
3
+ slug: string;
4
+ /** Plugin endpoint prefix (`routePrefix`). */
5
+ prefix: string;
6
+ }
7
+ export declare function OnPageAdminControls({ kind, slug, prefix }: OnPageAdminControlsProps): import("react").JSX.Element | null;
8
+ export default OnPageAdminControls;
9
+ //# sourceMappingURL=OnPageAdminControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OnPageAdminControls.d.ts","sourceRoot":"","sources":["../../src/admin/OnPageAdminControls.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAA;CACf;AAgBD,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,wBAAwB,sCAwDnF;AAED,eAAe,mBAAmB,CAAA"}
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Document controls added by payload-onpage: open this document's page in edit
5
+ * mode, or copy a sealed read-only preview link. Hidden for users who can't
6
+ * update the document.
7
+ */
8
+ import { payloadRest } from '@payload-onpage/core/payload';
9
+ import { Button, toast, useConfig, useDocumentInfo, useLocale, useTranslation, } from '@payloadcms/ui';
10
+ import { useMemo, useState } from 'react';
11
+ /**
12
+ * Same-origin POST (the endpoint refuses cross-site requests) opened in a new tab.
13
+ * A detached form: these controls render inside the admin's document <form>, and forms can't nest.
14
+ */
15
+ function postInNewTab(action) {
16
+ const form = document.createElement('form');
17
+ form.method = 'post';
18
+ form.action = action;
19
+ form.target = '_blank';
20
+ document.body.appendChild(form);
21
+ form.submit();
22
+ form.remove();
23
+ }
24
+ export function OnPageAdminControls({ kind, slug, prefix }) {
25
+ const { id, hasSavePermission } = useDocumentInfo();
26
+ const { config } = useConfig();
27
+ const locale = useLocale();
28
+ const { t: translate } = useTranslation();
29
+ const t = (key, vars) => translate(key, vars);
30
+ const [busy, setBusy] = useState(false);
31
+ const apiBase = `${config.serverURL ?? ''}${config.routes.api}`;
32
+ const dataSource = useMemo(() => payloadRest({ apiBase, prefix }), [apiBase, prefix]);
33
+ if ((kind === 'collection' && !id) || hasSavePermission === false)
34
+ return null;
35
+ const ref = kind === 'global' ? { kind, slug } : { kind, slug, id: id };
36
+ const params = new URLSearchParams({ kind, slug, mode: 'edit' });
37
+ if (kind === 'collection')
38
+ params.set('id', String(id));
39
+ if (locale?.code)
40
+ params.set('locale', locale.code);
41
+ const copyLink = async () => {
42
+ setBusy(true);
43
+ try {
44
+ const link = await dataSource.createPreviewLink(ref, { locale: locale?.code });
45
+ await navigator.clipboard.writeText(link.url);
46
+ toast.success(`Preview link copied — valid until ${new Date(link.expiresAt).toLocaleString()}`);
47
+ }
48
+ catch (e) {
49
+ toast.error(t('onpage:linkFailed', { message: e.message }));
50
+ }
51
+ finally {
52
+ setBusy(false);
53
+ }
54
+ };
55
+ const style = { whiteSpace: 'nowrap', flexShrink: 0 };
56
+ return (_jsxs("div", { style: { display: 'flex', gap: 6 }, "data-testid": "onpage-admin-controls", children: [_jsx(Button, { buttonStyle: "secondary", size: "medium", onClick: () => postInNewTab(`${apiBase}${prefix}/enter?${params}`), extraButtonProps: { style, 'data-testid': 'onpage-edit-on-page' }, children: t('onpage:editOnPage') }), _jsx(Button, { buttonStyle: "subtle", size: "medium", onClick: () => void copyLink(), disabled: busy, tooltip: t('onpage:copyPreviewLinkHint'), extraButtonProps: { style, 'data-testid': 'onpage-copy-preview-link' }, children: t('onpage:copyPreviewLink') })] }));
57
+ }
58
+ export default OnPageAdminControls;
59
+ //# sourceMappingURL=OnPageAdminControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OnPageAdminControls.js","sourceRoot":"","sources":["../../src/admin/OnPageAdminControls.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { OnPageAdminControls } from './OnPageAdminControls.tsx';
2
+ export type { OnPageAdminControlsProps } from './OnPageAdminControls.tsx';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { OnPageAdminControls } from "./OnPageAdminControls.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA2B,CAAA"}
@@ -0,0 +1,11 @@
1
+ import type { Endpoint, PayloadRequest } from 'payload';
2
+ import type { Entry, OnPageOptions } from './options.ts';
3
+ export interface EndpointContext {
4
+ options: OnPageOptions;
5
+ prefix: string;
6
+ apiRoute: string;
7
+ entry: (kind: string, slug: string) => Entry | undefined;
8
+ }
9
+ export declare const secretOf: (req: PayloadRequest, options: OnPageOptions) => string;
10
+ export declare function createEndpoints(ctx: EndpointContext): Endpoint[];
11
+ //# sourceMappingURL=endpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoints.d.ts","sourceRoot":"","sources":["../src/endpoints.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAoB,QAAQ,EAAgB,cAAc,EAAE,MAAM,SAAS,CAAA;AAavF,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAKxD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,CAAA;CACzD;AAID,eAAO,MAAM,QAAQ,GAAI,KAAK,cAAc,EAAE,SAAS,aAAa,KAAG,MAC1B,CAAA;AAc7C,wBAAgB,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,QAAQ,EAAE,CAyMhE"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * The plugin's endpoints, under `${api}${routePrefix}` (default /api/onpage):
3
+ *
4
+ * GET /schema/:kind/:slug editable field schema for the signed-in editor
5
+ * POST /enter start editing or previewing a document's page
6
+ * POST /mode switch the current page between editing and previewing
7
+ * POST /exit leave edit/preview mode
8
+ * POST /preview-link create a sealed, expiring read-only link (JSON)
9
+ * GET /preview?token= open a preview link
10
+ *
11
+ * State-changing endpoints are same-origin POSTs (CSRF-safe). Every
12
+ * authorization decision goes through ./access (Payload's own access rules).
13
+ */
14
+ import { parseRefKey, pathnameOf, refKey, safePath, samePath, SEAL_PURPOSE, seal, } from '@payload-onpage/core';
15
+ import { hasAutosaveEnabled, hasDraftsEnabled, getAutosaveInterval } from 'payload/shared';
16
+ import { canEditDocument, canUseOnPage, documentPermissions } from "./access.js";
17
+ import { isSecure, json, originOf, queryOf, readRef, redirectTo, rejectCrossSite, text, } from "./http.js";
18
+ import { resolvePath } from "./paths.js";
19
+ import { relationTargets, serializeFields } from "./schema.js";
20
+ import { createPreviewToken, verifyPreviewToken } from "./tokens.js";
21
+ const DAY = 24 * 3600;
22
+ export const secretOf = (req, options) => options.secret ?? req.payload.config.secret;
23
+ /** Name of the auth cookie an editor's mode is bound to. */
24
+ const authCookieOf = (req, options) => options.authCookie ?? `${req.payload.config.cookiePrefix || 'payload'}-token`;
25
+ function requireSession(options) {
26
+ if (!options.session)
27
+ throw new Error('payload-onpage: pass `session` (e.g. nextSession()) to use the enter, mode, exit and preview endpoints');
28
+ return options.session;
29
+ }
30
+ export function createEndpoints(ctx) {
31
+ const { options, prefix, apiRoute } = ctx;
32
+ const schema = {
33
+ path: `${prefix}/schema/:kind/:slug`,
34
+ method: 'get',
35
+ handler: async (req) => {
36
+ const kind = req.routeParams?.kind === 'global' ? 'global' : 'collection';
37
+ const slug = typeof req.routeParams?.slug === 'string' ? req.routeParams.slug : '';
38
+ const entry = ctx.entry(kind, slug);
39
+ const cfg = kind === 'global'
40
+ ? req.payload.globals.config.find((g) => g.slug === slug)
41
+ : req.payload.collections[slug]?.config;
42
+ if (!entry || !cfg)
43
+ return json({ error: 'Not enabled for on-page editing' }, 404);
44
+ if (!(await canUseOnPage(req, options)))
45
+ return json({ error: 'Forbidden' }, 403);
46
+ const perms = await documentPermissions(req, kind === 'global' ? { kind, slug } : { kind, slug });
47
+ const pending = [];
48
+ const all = serializeFields(cfg.fields, {
49
+ i18n: req.i18n,
50
+ blocks: req.payload.config.blocks,
51
+ permissions: perms?.fields,
52
+ defaults: { req, pending },
53
+ });
54
+ await Promise.all(pending);
55
+ const fields = entry.options.fields
56
+ ? all.filter((f) => entry.options.fields.includes(f.name))
57
+ : all;
58
+ const relations = {};
59
+ for (const target of relationTargets(fields)) {
60
+ const c = req.payload.collections[target]?.config;
61
+ if (!c)
62
+ continue;
63
+ relations[target] = {
64
+ titleField: c.admin?.useAsTitle ?? 'id',
65
+ label: typeof c.labels?.singular === 'string' ? c.labels.singular : target,
66
+ };
67
+ }
68
+ const localization = req.payload.config.localization;
69
+ const labelOf = (v) => (typeof v === 'string' ? v : slug);
70
+ const body = {
71
+ kind,
72
+ slug,
73
+ labels: kind === 'global'
74
+ ? {
75
+ singular: labelOf(cfg.label),
76
+ plural: labelOf(cfg.label),
77
+ }
78
+ : {
79
+ singular: labelOf(cfg.labels?.singular),
80
+ plural: labelOf(cfg.labels?.plural),
81
+ },
82
+ editable: fields.map((f) => f.name),
83
+ fields,
84
+ drafts: hasDraftsEnabled(cfg),
85
+ ...(hasAutosaveEnabled(cfg) ? { autosaveInterval: getAutosaveInterval(cfg) } : {}),
86
+ ...(kind === 'collection' && cfg.admin?.useAsTitle
87
+ ? { useAsTitle: cfg.admin.useAsTitle }
88
+ : {}),
89
+ ...(Object.keys(relations).length ? { relations } : {}),
90
+ ...(localization
91
+ ? {
92
+ defaultLocale: localization.defaultLocale,
93
+ locales: localization.locales.map((l) => (typeof l === 'string' ? l : l.code)),
94
+ }
95
+ : {}),
96
+ };
97
+ return json(body);
98
+ },
99
+ };
100
+ const enter = {
101
+ path: `${prefix}/enter`,
102
+ method: 'post',
103
+ handler: async (req) => {
104
+ const refused = rejectCrossSite(req);
105
+ if (refused)
106
+ return refused;
107
+ const q = queryOf(req);
108
+ const ref = readRef({ kind: q.get('kind'), slug: q.get('slug'), id: q.get('id') });
109
+ const entry = ref && ctx.entry(ref.kind, ref.slug);
110
+ if (!ref || !entry)
111
+ return text('Unknown document', 400);
112
+ if (!req.user)
113
+ return text('Sign in to the admin first', 401);
114
+ if (!(await canEditDocument(req, ref, options)))
115
+ return text('You cannot edit this document', 403);
116
+ const locale = q.get('locale') ?? undefined;
117
+ const path = safePath(q.get('path')) ?? (await resolvePath(req, ref, entry, locale));
118
+ if (!path)
119
+ return text('This document has no page to open', 404);
120
+ const mode = q.get('mode') === 'view' ? 'view' : 'edit';
121
+ await requireSession(options).enable(mode, {
122
+ secure: isSecure(req),
123
+ bindTo: authCookieOf(req, options),
124
+ });
125
+ return redirectTo(req, path);
126
+ },
127
+ };
128
+ const mode = {
129
+ path: `${prefix}/mode`,
130
+ method: 'post',
131
+ handler: async (req) => {
132
+ const refused = rejectCrossSite(req);
133
+ if (refused)
134
+ return refused;
135
+ if (!(await canUseOnPage(req, options)))
136
+ return text('Sign in as an editor first', 401);
137
+ const q = queryOf(req);
138
+ await requireSession(options).enable(q.get('mode') === 'view' ? 'view' : 'edit', {
139
+ secure: isSecure(req),
140
+ bindTo: authCookieOf(req, options),
141
+ });
142
+ return redirectTo(req, q.get('path'));
143
+ },
144
+ };
145
+ const exit = {
146
+ path: `${prefix}/exit`,
147
+ method: 'post',
148
+ handler: async (req) => {
149
+ const refused = rejectCrossSite(req);
150
+ if (refused)
151
+ return refused;
152
+ await requireSession(options).disable();
153
+ return redirectTo(req, queryOf(req).get('path'));
154
+ },
155
+ };
156
+ const previewLink = {
157
+ path: `${prefix}/preview-link`,
158
+ method: 'post',
159
+ handler: async (req) => {
160
+ const refused = rejectCrossSite(req);
161
+ if (refused)
162
+ return refused;
163
+ if (!req.headers.get('content-type')?.includes('application/json'))
164
+ return json({ error: 'Expected JSON' }, 415);
165
+ const body = ((await req.json?.().catch(() => null)) ?? {});
166
+ const ref = readRef(body);
167
+ const entry = ref && ctx.entry(ref.kind, ref.slug);
168
+ if (!ref || !entry)
169
+ return json({ error: 'Unknown document' }, 400);
170
+ if (!(await canEditDocument(req, ref, options)))
171
+ return json({ error: 'Forbidden' }, 403);
172
+ const locale = typeof body.locale === 'string' ? body.locale : undefined;
173
+ // The path is always derived on the server: a link opens this document's page and nothing else.
174
+ const path = await resolvePath(req, ref, entry, locale);
175
+ if (!path)
176
+ return json({ error: 'This document has no page' }, 404);
177
+ const ttl = options.previewLinkTTL ?? DAY;
178
+ const { token, payload } = await createPreviewToken({ ref: refKey(ref), path, locale }, secretOf(req, options), ttl);
179
+ return json({
180
+ url: `${originOf(req)}${apiRoute}${prefix}/preview?token=${encodeURIComponent(token)}`,
181
+ expiresAt: new Date(payload.exp * 1000).toISOString(),
182
+ id: payload.jti,
183
+ });
184
+ },
185
+ };
186
+ const preview = {
187
+ path: `${prefix}/preview`,
188
+ method: 'get',
189
+ handler: async (req) => {
190
+ const invalid = () => text('This preview link is invalid or has expired.', 403);
191
+ const secret = secretOf(req, options);
192
+ const token = await verifyPreviewToken(queryOf(req).get('token') ?? '', secret);
193
+ const ref = token && parseRefKey(token.ref);
194
+ const entry = ref && ctx.entry(ref.kind, ref.slug);
195
+ if (!token || !ref || !entry)
196
+ return invalid();
197
+ // Still the document's page? (It may have been deleted, or its slug changed.)
198
+ const current = await resolvePath(req, ref, entry, token.locale);
199
+ if (!current || !samePath(current, token.path))
200
+ return invalid();
201
+ if (options.validatePreviewLink &&
202
+ !(await options.validatePreviewLink({
203
+ req,
204
+ ref,
205
+ path: token.path,
206
+ issuedAt: token.iat,
207
+ id: token.jti,
208
+ }))) {
209
+ return invalid();
210
+ }
211
+ const expiresAt = new Date(token.exp * 1000);
212
+ await requireSession(options).enableLink({
213
+ secure: isSecure(req),
214
+ path: pathnameOf(token.path),
215
+ expiresAt,
216
+ seal: (draftSecret) => seal({ path: pathnameOf(token.path), ref: token.ref, exp: token.exp, draft: draftSecret }, secret, SEAL_PURPOSE.previewCookie),
217
+ });
218
+ return redirectTo(req, token.path, 307);
219
+ },
220
+ };
221
+ return [schema, enter, mode, exit, previewLink, preview];
222
+ }
223
+ //# sourceMappingURL=endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoints.js","sourceRoot":"","sources":["../src/endpoints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Collection/global hooks added by the plugin:
3
+ * - afterRead: auto-mapping markers, only on reads that ask (`context.onpage`)
4
+ * - beforeValidate/beforeChange: strip markers from every write, so they can't be stored
5
+ * - beforeChange: stale-write guard (409) when the editor sends the version it last saw
6
+ */
7
+ import { type EncodeFilter, type SchemaField } from '@payload-onpage/core';
8
+ import { type PayloadRequest } from 'payload';
9
+ /** True when a read asked for auto-mapping markers (see `onpageContext()`). */
10
+ export declare const wantsMarkers: (context: unknown) => boolean;
11
+ export declare const stripMarkers: ({ data }: {
12
+ data?: unknown;
13
+ }) => unknown;
14
+ export declare function encodeOnRead(opts: {
15
+ kind: 'collection' | 'global';
16
+ slug: string;
17
+ fields: () => SchemaField[];
18
+ only?: string[];
19
+ filter?: EncodeFilter;
20
+ }): ({ doc, req, context, }: {
21
+ doc: Record<string, unknown>;
22
+ req: PayloadRequest;
23
+ context: unknown;
24
+ }) => Record<string, unknown>;
25
+ /**
26
+ * Optimistic concurrency: the editor sends `x-onpage-if-unmodified-since` with
27
+ * the `updatedAt` it last saw; if the document changed since, the write fails
28
+ * with 409 and the editor offers to reload. Writes without the header (admin,
29
+ * API, other tools) are untouched.
30
+ */
31
+ export declare const guardStaleWrite: <T>({ data, req, originalDoc, }: {
32
+ data: T;
33
+ req: PayloadRequest;
34
+ originalDoc?: {
35
+ updatedAt?: unknown;
36
+ };
37
+ }) => T;
38
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAKL,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAEvD,+EAA+E;AAC/E,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,OACoD,CAAA;AAEpG,eAAO,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,YAAyC,CAAA;AAElG,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,WAAW,EAAE,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB,IACS,wBAIL;IACD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5B,GAAG,EAAE,cAAc,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;CACjB,6BAYF;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,6BAIhC;IACD,IAAI,EAAE,CAAC,CAAA;IACP,GAAG,EAAE,cAAc,CAAA;IACnB,WAAW,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CACtC,KAAG,CAaH,CAAA"}
package/dist/hooks.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Collection/global hooks added by the plugin:
3
+ * - afterRead: auto-mapping markers, only on reads that ask (`context.onpage`)
4
+ * - beforeValidate/beforeChange: strip markers from every write, so they can't be stored
5
+ * - beforeChange: stale-write guard (409) when the editor sends the version it last saw
6
+ */
7
+ import { encodeDocument, HEADER, refKey, stegaCleanDeep, } from '@payload-onpage/core';
8
+ import { APIError } from 'payload';
9
+ /** True when a read asked for auto-mapping markers (see `onpageContext()`). */
10
+ export const wantsMarkers = (context) => !!(context && typeof context === 'object' && context.onpage === true);
11
+ export const stripMarkers = ({ data }) => (data ? stegaCleanDeep(data) : data);
12
+ export function encodeOnRead(opts) {
13
+ return ({ doc, req, context, }) => {
14
+ if (!wantsMarkers(context) || req.locale === 'all' || !doc)
15
+ return doc;
16
+ const ref = opts.kind === 'global'
17
+ ? refKey({ kind: 'global', slug: opts.slug })
18
+ : doc.id != null
19
+ ? refKey({ kind: 'collection', slug: opts.slug, id: doc.id })
20
+ : null;
21
+ return ref
22
+ ? encodeDocument(doc, opts.fields(), ref, { only: opts.only, filter: opts.filter })
23
+ : doc;
24
+ };
25
+ }
26
+ /**
27
+ * Optimistic concurrency: the editor sends `x-onpage-if-unmodified-since` with
28
+ * the `updatedAt` it last saw; if the document changed since, the write fails
29
+ * with 409 and the editor offers to reload. Writes without the header (admin,
30
+ * API, other tools) are untouched.
31
+ */
32
+ export const guardStaleWrite = ({ data, req, originalDoc, }) => {
33
+ const seen = req.headers?.get(HEADER.ifUnmodifiedSince);
34
+ const current = originalDoc?.updatedAt;
35
+ if (!seen || typeof current !== 'string')
36
+ return data;
37
+ if (new Date(seen).getTime() !== new Date(current).getTime()) {
38
+ throw new APIError('This document was changed by someone else since you loaded it.', 409, undefined, true);
39
+ }
40
+ return data;
41
+ };
42
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,cAAc,EACd,MAAM,EACN,MAAM,EACN,cAAc,GAGf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAuB,MAAM,SAAS,CAAA;AAEvD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAgB,EAAW,EAAE,CACxD,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAK,OAAmC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAA;AAEpG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,IAAI,EAAsB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AAElG,MAAM,UAAU,YAAY,CAAC,IAM5B;IACC,OAAO,CAAC,EACN,GAAG,EACH,GAAG,EACH,OAAO,GAKR,EAAE,EAAE;QACH,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,GAAG;YAAE,OAAO,GAAG,CAAA;QACtE,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,KAAK,QAAQ;YACpB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7C,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI;gBACd,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAqB,EAAE,CAAC;gBAChF,CAAC,CAAC,IAAI,CAAA;QACZ,OAAO,GAAG;YACR,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YACnF,CAAC,CAAC,GAAG,CAAA;IACT,CAAC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAI,EACjC,IAAI,EACJ,GAAG,EACH,WAAW,GAKZ,EAAK,EAAE;IACN,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAA;IACvD,MAAM,OAAO,GAAG,WAAW,EAAE,SAAS,CAAA;IACtC,IAAI,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACrD,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7D,MAAM,IAAI,QAAQ,CAChB,gEAAgE,EAChE,GAAG,EACH,SAAS,EACT,IAAI,CACL,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /** Request helpers shared by the endpoints. */
2
+ import { type DocRef } from '@payload-onpage/core';
3
+ import type { PayloadRequest } from 'payload';
4
+ /** The site origin: `serverURL` when configured, else the request's own origin. */
5
+ export declare function originOf(req: PayloadRequest): string;
6
+ export declare const isSecure: (req: PayloadRequest) => boolean;
7
+ export declare const queryOf: (req: PayloadRequest) => URLSearchParams;
8
+ export declare const text: (body: string, status: number) => Response;
9
+ export declare const json: (body: unknown, status?: number) => Response;
10
+ /** Redirect to a same-origin path (anything unsafe becomes "/"). 303 turns a POST into a GET. */
11
+ export declare const redirectTo: (req: PayloadRequest, path: unknown, status?: 303 | 307) => Response;
12
+ /**
13
+ * CSRF guard for state-changing endpoints: a POST from this site (Origin, or
14
+ * Sec-Fetch-Site when Origin is absent). Returns an error response or null.
15
+ */
16
+ export declare function rejectCrossSite(req: PayloadRequest): Response | null;
17
+ /** A document ref from `kind`, `slug`, `id` query/body values. */
18
+ export declare function readRef(values: {
19
+ kind?: unknown;
20
+ slug?: unknown;
21
+ id?: unknown;
22
+ }): DocRef | null;
23
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAyB,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAA;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAUpD;AAED,eAAO,MAAM,QAAQ,GAAI,KAAK,cAAc,KAAG,OAA6C,CAAA;AAE5F,eAAO,MAAM,OAAO,GAAI,KAAK,cAAc,KAAG,eACY,CAAA;AAE1D,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,QAAQ,MAAM,KAAG,QAIhD,CAAA;AAEJ,eAAO,MAAM,IAAI,GAAI,MAAM,OAAO,EAAE,eAAY,KAAG,QACiC,CAAA;AAEpF,iGAAiG;AACjG,eAAO,MAAM,UAAU,GAAI,KAAK,cAAc,EAAE,MAAM,OAAO,EAAE,SAAQ,GAAG,GAAG,GAAS,KAAG,QACf,CAAA;AAE1E;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,GAAG,IAAI,CAMpE;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,MAAM,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAQ/F"}