@remkoj/optimizely-cms-nextjs 1.0.3
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 +13 -0
- package/README.md +2 -0
- package/dist/auth.d.ts +73 -0
- package/dist/auth.js +154 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +8 -0
- package/dist/client.js +22 -0
- package/dist/client.js.map +1 -0
- package/dist/cms-page/data.d.ts +39 -0
- package/dist/cms-page/data.js +43 -0
- package/dist/cms-page/data.js.map +1 -0
- package/dist/cms-page/index.d.ts +5 -0
- package/dist/cms-page/index.js +3 -0
- package/dist/cms-page/index.js.map +1 -0
- package/dist/cms-page/layout.d.ts +16 -0
- package/dist/cms-page/layout.js +81 -0
- package/dist/cms-page/layout.js.map +1 -0
- package/dist/cms-page/page.d.ts +28 -0
- package/dist/cms-page/page.js +108 -0
- package/dist/cms-page/page.js.map +1 -0
- package/dist/cms-page/utils.d.ts +5 -0
- package/dist/cms-page/utils.js +19 -0
- package/dist/cms-page/utils.js.map +1 -0
- package/dist/components/on-page-edit.d.ts +24 -0
- package/dist/components/on-page-edit.js +85 -0
- package/dist/components/on-page-edit.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata.d.ts +18 -0
- package/dist/metadata.js +36 -0
- package/dist/metadata.js.map +1 -0
- package/dist/ope/data.d.ts +2 -0
- package/dist/ope/data.js +28 -0
- package/dist/ope/data.js.map +1 -0
- package/dist/ope/index.d.ts +4 -0
- package/dist/ope/index.js +5 -0
- package/dist/ope/index.js.map +1 -0
- package/dist/ope/page.d.ts +17 -0
- package/dist/ope/page.js +141 -0
- package/dist/ope/page.js.map +1 -0
- package/dist/ope/types.d.ts +73 -0
- package/dist/ope/types.js +2 -0
- package/dist/ope/types.js.map +1 -0
- package/dist/page.d.ts +2 -0
- package/dist/page.js +6 -0
- package/dist/page.js.map +1 -0
- package/dist/publish/index.d.ts +10 -0
- package/dist/publish/index.js +54 -0
- package/dist/publish/index.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ChannelDefinition } from "@remkoj/optimizely-graph-client";
|
|
2
|
+
export declare function urlToPath(baseUrl: URL, language: string): string[];
|
|
3
|
+
export declare function localeToGraphLocale(channel: ChannelDefinition, locale: string): string;
|
|
4
|
+
export declare function slugToLocale<T extends string | undefined | null>(channel: ChannelDefinition, slug: string, defaultValue: T): string | T;
|
|
5
|
+
export declare function slugToGraphLocale<T extends string | undefined | null>(channel: ChannelDefinition, slug: string, defaultValue: T): string | T;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Extract the path as string array from a given URL
|
|
2
|
+
export function urlToPath(baseUrl, language) {
|
|
3
|
+
let slugs = baseUrl.pathname.split('/').filter(s => s);
|
|
4
|
+
if (slugs[0] == language)
|
|
5
|
+
slugs.shift();
|
|
6
|
+
return slugs;
|
|
7
|
+
}
|
|
8
|
+
export function localeToGraphLocale(channel, locale) {
|
|
9
|
+
return channel.localeToGraphLocale(locale) ?? locale.replaceAll("-", "_");
|
|
10
|
+
}
|
|
11
|
+
export function slugToLocale(channel, slug, defaultValue) {
|
|
12
|
+
const route = channel.locales.filter(x => x.slug == slug)[0];
|
|
13
|
+
return route?.code || defaultValue;
|
|
14
|
+
}
|
|
15
|
+
export function slugToGraphLocale(channel, slug, defaultValue) {
|
|
16
|
+
const route = channel.locales.filter(x => x.slug == slug)[0];
|
|
17
|
+
return route?.graphLocale || defaultValue?.replaceAll("-", "_");
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cms-page/utils.ts"],"names":[],"mappings":"AAEA,oDAAoD;AACpD,MAAM,UAAU,SAAS,CAAC,OAAY,EAAE,QAAgB;IACpD,IAAI,KAAK,GAAc,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACjE,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,QAAQ;QACpB,KAAK,CAAC,KAAK,EAAE,CAAA;IACjB,OAAO,KAAK,CAAA;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAA0B,EAAE,MAAc;IAE1E,OAAO,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,EAAC,GAAG,CAAC,CAAA;AAC5E,CAAC;AAED,MAAM,UAAU,YAAY,CAAsC,OAA0B,EAAE,IAAY,EAAE,YAAe;IAEvH,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5D,OAAO,KAAK,EAAE,IAAI,IAAI,YAAY,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAsC,OAA0B,EAAE,IAAY,EAAE,YAAe;IAE5H,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5D,OAAO,KAAK,EAAE,WAAW,IAAI,YAAY,EAAE,UAAU,CAAC,GAAG,EAAC,GAAG,CAAM,CAAA;AACvE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type FunctionComponent, type PropsWithChildren } from 'react';
|
|
2
|
+
export type OnPageEditProps = PropsWithChildren<{
|
|
3
|
+
mode?: 'edit' | 'preview';
|
|
4
|
+
className?: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}>;
|
|
7
|
+
export type OptimizelyCmsContext = {
|
|
8
|
+
ready: boolean;
|
|
9
|
+
inEditMode: boolean;
|
|
10
|
+
isEditable: boolean;
|
|
11
|
+
subscribe: (event: string, handler: (...args: any) => void) => void;
|
|
12
|
+
};
|
|
13
|
+
export type OptimizelyCmsContentSavedEvent = {
|
|
14
|
+
contentLink: string;
|
|
15
|
+
editUrl: string;
|
|
16
|
+
previewUrl: string;
|
|
17
|
+
};
|
|
18
|
+
declare global {
|
|
19
|
+
interface Window {
|
|
20
|
+
epi?: OptimizelyCmsContext;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export declare const OnPageEdit: FunctionComponent<OnPageEditProps>;
|
|
24
|
+
export default OnPageEdit;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
const DEV = process.env.NODE_ENV == 'development';
|
|
6
|
+
export const OnPageEdit = ({ mode, children, className, timeout }) => {
|
|
7
|
+
const router = useRouter();
|
|
8
|
+
const [optiCmsReady, setOptiCmsReady] = useState(false);
|
|
9
|
+
const [showMask, setShowMask] = useState(false);
|
|
10
|
+
timeout = timeout ?? 1500;
|
|
11
|
+
// Bind to the CMS & CMS Ready State
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
console.log("Reading Opti CMS Context");
|
|
14
|
+
const fxCms = tryGetCms();
|
|
15
|
+
const cmsReady = fxCms?.ready ?? false;
|
|
16
|
+
setOptiCmsReady(cmsReady);
|
|
17
|
+
if (!cmsReady) {
|
|
18
|
+
const cancelToken = setInterval(() => {
|
|
19
|
+
const updateCms = tryGetCms();
|
|
20
|
+
const updatedCmsReady = updateCms?.ready ?? false;
|
|
21
|
+
if (updatedCmsReady) {
|
|
22
|
+
clearInterval(cancelToken);
|
|
23
|
+
setOptiCmsReady(updatedCmsReady);
|
|
24
|
+
}
|
|
25
|
+
}, 250);
|
|
26
|
+
return () => {
|
|
27
|
+
clearInterval(cancelToken);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
// Bind to the Saved event
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!optiCmsReady)
|
|
34
|
+
return;
|
|
35
|
+
const previewUrl = window.location.href;
|
|
36
|
+
let handlerEnabled = true;
|
|
37
|
+
// Define event handler
|
|
38
|
+
let maskTimer = false;
|
|
39
|
+
function onContentSaved(eventData) {
|
|
40
|
+
setShowMask(true);
|
|
41
|
+
if (maskTimer != false)
|
|
42
|
+
clearTimeout(maskTimer);
|
|
43
|
+
console.log(`Delaying refresh with ${timeout}ms to allow Optimizely Graph to update`);
|
|
44
|
+
maskTimer = setTimeout(() => {
|
|
45
|
+
const contentId = window.location.pathname.split(',,')[1];
|
|
46
|
+
const newContentId = eventData.contentLink;
|
|
47
|
+
if (previewUrl == eventData.previewUrl) {
|
|
48
|
+
console.log(`Refreshing preview: ${contentId} => ${newContentId}`);
|
|
49
|
+
router.refresh();
|
|
50
|
+
//setShowMask(false)
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const newUrl = new URL(eventData.previewUrl);
|
|
54
|
+
console.log(`Navigating to new preview: ${contentId} => ${newContentId}`);
|
|
55
|
+
router.push(newUrl.pathname + newUrl.search);
|
|
56
|
+
setShowMask(false);
|
|
57
|
+
}
|
|
58
|
+
}, timeout);
|
|
59
|
+
}
|
|
60
|
+
// Subscribe to event
|
|
61
|
+
console.log(`Subscribing to ContentSaved Event`);
|
|
62
|
+
const opti = tryGetCms();
|
|
63
|
+
opti?.subscribe('contentSaved', (eventData) => {
|
|
64
|
+
if (!handlerEnabled)
|
|
65
|
+
return;
|
|
66
|
+
onContentSaved(eventData);
|
|
67
|
+
});
|
|
68
|
+
// Unsubscribe when needed
|
|
69
|
+
return () => {
|
|
70
|
+
console.log(`Navigating away, disabling ContentSaved event handler`);
|
|
71
|
+
handlerEnabled = false;
|
|
72
|
+
};
|
|
73
|
+
}, [optiCmsReady, router, timeout]);
|
|
74
|
+
return _jsx(_Fragment, { children: showMask && _jsx("div", { className: `loading-mask ${className}`.trimEnd(), children: children }) });
|
|
75
|
+
};
|
|
76
|
+
function tryGetCms() {
|
|
77
|
+
try {
|
|
78
|
+
return window.epi;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export default OnPageEdit;
|
|
85
|
+
//# sourceMappingURL=on-page-edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-page-edit.js","sourceRoot":"","sources":["../../src/components/on-page-edit.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAA;AAC9B,OAAO,KAAK,UAAU,MAAM,OAAO,CAAA;AACnC,OAAO,KAAK,OAAO,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ComponentFactory, type ContentLink } from '@remkoj/optimizely-cms-react';
|
|
2
|
+
import { type OptimizelyGraphConfig, type IOptiGraphClient } from '@remkoj/optimizely-graph-client';
|
|
3
|
+
import { Metadata } from 'next';
|
|
4
|
+
export declare class MetaDataResolver {
|
|
5
|
+
private _cgClient;
|
|
6
|
+
constructor(clientOrConfig?: OptimizelyGraphConfig | IOptiGraphClient);
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the meta data for a component, if it has a meta-data method exposed.
|
|
9
|
+
*
|
|
10
|
+
* @param factory The component factory used to load the component
|
|
11
|
+
* @param contentLink The link to the component for which the meta-data should be retrieved
|
|
12
|
+
* @param contentType The content type of the component
|
|
13
|
+
* @param locale The locale to be used, in a ContentGraph locale format
|
|
14
|
+
* @returns A Promise for the metadata of the given content type & instance
|
|
15
|
+
*/
|
|
16
|
+
resolve(factory: ComponentFactory, contentLink: ContentLink, contentType: string[], locale: string): Promise<Metadata>;
|
|
17
|
+
}
|
|
18
|
+
export default MetaDataResolver;
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import createClient, { isContentGraphClient } from '@remkoj/optimizely-graph-client';
|
|
2
|
+
import { isOptimizelyNextPageWithMetaData } from './page';
|
|
3
|
+
const DEBUG = process.env.DXP_DEBUG == '1';
|
|
4
|
+
export class MetaDataResolver {
|
|
5
|
+
_cgClient;
|
|
6
|
+
constructor(clientOrConfig) {
|
|
7
|
+
this._cgClient = isContentGraphClient(clientOrConfig) ? clientOrConfig : createClient(clientOrConfig);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the meta data for a component, if it has a meta-data method exposed.
|
|
11
|
+
*
|
|
12
|
+
* @param factory The component factory used to load the component
|
|
13
|
+
* @param contentLink The link to the component for which the meta-data should be retrieved
|
|
14
|
+
* @param contentType The content type of the component
|
|
15
|
+
* @param locale The locale to be used, in a ContentGraph locale format
|
|
16
|
+
* @returns A Promise for the metadata of the given content type & instance
|
|
17
|
+
*/
|
|
18
|
+
async resolve(factory, contentLink, contentType, locale) {
|
|
19
|
+
if (DEBUG)
|
|
20
|
+
console.log("[MetaDataResolver] Resolving metadata for:", contentLink, contentType, locale);
|
|
21
|
+
if (locale.includes("-"))
|
|
22
|
+
throw new Error("Invalid character detected within the locale");
|
|
23
|
+
const Component = factory.resolve(contentType);
|
|
24
|
+
if (!Component)
|
|
25
|
+
return {};
|
|
26
|
+
if (isOptimizelyNextPageWithMetaData(Component) && Component.getMetaData) {
|
|
27
|
+
const meta = await Component.getMetaData(contentLink, locale, this._cgClient);
|
|
28
|
+
if (DEBUG)
|
|
29
|
+
console.log("[MetaDataResolver] Resolved metadata to:", meta);
|
|
30
|
+
return meta;
|
|
31
|
+
}
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export default MetaDataResolver;
|
|
36
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,EAAE,EAAE,oBAAoB,EAAqD,MAAM,iCAAiC,CAAA;AAEvI,OAAO,EAAE,gCAAgC,EAAE,MAAM,QAAQ,CAAA;AAEzD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,GAAG,CAAA;AAE1C,MAAM,OAAO,gBAAgB;IAEjB,SAAS,CAAmB;IAEpC,YAAmB,cAAyD;QAExE,IAAI,CAAC,SAAS,GAAG,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;IACzG,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,OAAO,CAAC,OAAyB,EAAE,WAAwB,EAAE,WAAqB,EAAE,MAAc;QAE3G,IAAI,KAAK;YACL,OAAO,CAAC,GAAG,CAAC,4CAA4C,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;QAE/F,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;QAEnE,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;QAC9C,IAAI,CAAC,SAAS;YACV,OAAO,EAAE,CAAA;QAEb,IAAI,gCAAgC,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,WAAW,EAAE,CAAC;YACvE,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;YAC7E,IAAI,KAAK;gBACL,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,IAAI,CAAC,CAAA;YACjE,OAAO,IAAI,CAAA;QACf,CAAC;QACD,OAAO,EAAE,CAAA;IACb,CAAC;CACJ;AAED,eAAe,gBAAgB,CAAA"}
|
package/dist/ope/data.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { gql } from 'graphql-request';
|
|
2
|
+
export const getContentById = async (client, variables) => {
|
|
3
|
+
return await client.request(gqlQuery, variables);
|
|
4
|
+
};
|
|
5
|
+
const gqlQuery = gql `query getContentByIdBase($id: Int, $workId: Int, $guidValue: String, $locale: [Locales!], $isCommonDraft: Boolean) {
|
|
6
|
+
Content(
|
|
7
|
+
where: {
|
|
8
|
+
ContentLink: { Id: { eq: $id }, WorkId: { eq: $workId }, GuidValue: { eq: $guidValue } }
|
|
9
|
+
IsCommonDraft: { eq: $isCommonDraft }
|
|
10
|
+
}
|
|
11
|
+
locale: $locale
|
|
12
|
+
) {
|
|
13
|
+
total
|
|
14
|
+
items {
|
|
15
|
+
contentType: ContentType
|
|
16
|
+
id: ContentLink {
|
|
17
|
+
id: Id
|
|
18
|
+
workId: WorkId
|
|
19
|
+
guidValue: GuidValue
|
|
20
|
+
}
|
|
21
|
+
locale: Language {
|
|
22
|
+
name: Name
|
|
23
|
+
}
|
|
24
|
+
path: RelativePath
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}`;
|
|
28
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../src/ope/data.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAErC,MAAM,CAAC,MAAM,cAAc,GAA0B,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;IAE7E,OAAO,MAAM,MAAM,CAAC,OAAO,CAA8C,QAAQ,EAAE,SAAS,CAAC,CAAA;AACjG,CAAC,CAAA;AAED,MAAM,QAAQ,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;EAsBlB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ope/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,cAAc,QAAQ,CAAA;AACtB,OAAO,EAAE,uBAAuB,IAAI,OAAO,EAAE,MAAM,QAAQ,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import type { EditPageComponent, EditViewOptions } from './types';
|
|
3
|
+
import { type Services } from '@remkoj/optimizely-graph-client';
|
|
4
|
+
import { type ComponentFactory } from '@remkoj/optimizely-cms-react/rsc';
|
|
5
|
+
/**
|
|
6
|
+
* Create the EditPage component needed by Next.JS to render the "On Page
|
|
7
|
+
* Editing" variant of the content item selected by the editor.
|
|
8
|
+
*
|
|
9
|
+
* @param dxpUrl The domain of the CMS instance
|
|
10
|
+
* @param client The Apollo GraphQL client to use
|
|
11
|
+
* @param channel The static site definition to use
|
|
12
|
+
* @param factory The component factory to be used
|
|
13
|
+
* @param options The optional options to use to control the edit page
|
|
14
|
+
* @returns The React Component that can be used by Next.JS to render the page
|
|
15
|
+
*/
|
|
16
|
+
export declare function createEditPageComponent(channel: Readonly<Services.ChannelDefinition>, factory: ComponentFactory, options?: Partial<EditViewOptions>): EditPageComponent;
|
|
17
|
+
export default createEditPageComponent;
|
package/dist/ope/page.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import 'server-only';
|
|
3
|
+
import { AuthMode } from '@remkoj/optimizely-graph-client';
|
|
4
|
+
import { Utils } from '@remkoj/optimizely-cms-react';
|
|
5
|
+
import { CmsContent, getServerContext } from '@remkoj/optimizely-cms-react/rsc';
|
|
6
|
+
import { notFound } from 'next/navigation';
|
|
7
|
+
import OnPageEdit from '../components/on-page-edit';
|
|
8
|
+
import { getAuthorizedServerClient } from '../client';
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import Script from 'next/script';
|
|
11
|
+
import { getContentById } from './data';
|
|
12
|
+
const defaultOptions = {
|
|
13
|
+
refreshDelay: 2000,
|
|
14
|
+
refreshNotice: () => _jsx("div", { className: 'optly-refresh-notice', children: "Updating preview, please wait...." }),
|
|
15
|
+
errorNotice: props => _jsxs("div", { className: 'optly-error-notice', children: [_jsx("div", { className: 'optly-error-title', children: props.title }), _jsx("div", { className: 'optly-error-message', children: props.message })] }),
|
|
16
|
+
layout: props => _jsx("div", { className: 'optly-edit-page', "data-locale": props.locale, children: props.children }),
|
|
17
|
+
loader: getContentById,
|
|
18
|
+
clientFactory: (token) => getAuthorizedServerClient(token)
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Create the EditPage component needed by Next.JS to render the "On Page
|
|
22
|
+
* Editing" variant of the content item selected by the editor.
|
|
23
|
+
*
|
|
24
|
+
* @param dxpUrl The domain of the CMS instance
|
|
25
|
+
* @param client The Apollo GraphQL client to use
|
|
26
|
+
* @param channel The static site definition to use
|
|
27
|
+
* @param factory The component factory to be used
|
|
28
|
+
* @param options The optional options to use to control the edit page
|
|
29
|
+
* @returns The React Component that can be used by Next.JS to render the page
|
|
30
|
+
*/
|
|
31
|
+
export function createEditPageComponent(channel, factory, options) {
|
|
32
|
+
const { layout: PageLayout, refreshNotice: RefreshNotice, refreshDelay, errorNotice: ErrorNotice, loader: getContentById, clientFactory } = { ...defaultOptions, ...options };
|
|
33
|
+
const dxpUrl = channel.getCmsUrl();
|
|
34
|
+
async function EditPage({ params, searchParams }) {
|
|
35
|
+
// Create context
|
|
36
|
+
const context = getServerContext();
|
|
37
|
+
// Validate the search parameters
|
|
38
|
+
const epiEditMode = searchParams?.epieditmode?.toLowerCase();
|
|
39
|
+
if (epiEditMode != 'true' && epiEditMode != 'false') {
|
|
40
|
+
console.error("[OnPageEdit] Edit mode requested without valid EpiEditMode, refused to render the page. Mode set:", searchParams.epieditmode);
|
|
41
|
+
return notFound();
|
|
42
|
+
}
|
|
43
|
+
// Allow use-hmac as magic token to be used only on a development environment, otherwise require a minimal length string as token
|
|
44
|
+
const token = searchParams.preview_token;
|
|
45
|
+
const validDev = context.isDevelopment && (searchParams.preview_token == AuthMode.HMAC || searchParams.preview_token == AuthMode.Basic);
|
|
46
|
+
if (!token || (token.length < 20 && !validDev)) {
|
|
47
|
+
console.error("[OnPageEdit] Edit mode requested without valid Preview Token, refused to render the page");
|
|
48
|
+
return notFound();
|
|
49
|
+
}
|
|
50
|
+
if (context.isDebug)
|
|
51
|
+
console.log(`[OnPageEdit] Valid edit mode request: EpiEditMode=${searchParams.epieditmode}`);
|
|
52
|
+
// Helper function to read the ContentID & WorkID
|
|
53
|
+
function getContentIds() {
|
|
54
|
+
try {
|
|
55
|
+
// When using HMAC authentication, fall back to information in the URL
|
|
56
|
+
if (validDev) {
|
|
57
|
+
const contentString = slugs.join('/').split(',,').pop() ?? '';
|
|
58
|
+
const [contentId, workId] = contentString.split('_', 3);
|
|
59
|
+
return [Number.parseInt(contentId), workId ? Number.parseInt(workId) : null];
|
|
60
|
+
}
|
|
61
|
+
// Normally take the information from the token
|
|
62
|
+
const jwt = JSON.parse(Buffer.from((token || '..').split('.', 3)[1], 'base64').toString());
|
|
63
|
+
const contentId = Number.parseInt(jwt?.c_id || '-1', 10);
|
|
64
|
+
const workId = Number.parseInt(jwt?.c_ver || '0') || null;
|
|
65
|
+
if ((jwt.exp * 1000) < Date.now())
|
|
66
|
+
console.warn("[OnPageEdit] Token has expired, it is unlikely that you are able to fetch content with it");
|
|
67
|
+
return [contentId, workId];
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return [-1, null];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Build context
|
|
74
|
+
const client = clientFactory(token);
|
|
75
|
+
context.setOptimizelyGraphClient(client);
|
|
76
|
+
context.setComponentFactory(factory);
|
|
77
|
+
context.setInEditMode(epiEditMode == 'true');
|
|
78
|
+
// Get information from the Request URI
|
|
79
|
+
const requestPath = ('/' + params.path.map(decodeURIComponent).join('/')).replace(/^(\/ui){0,1}(\/cms){0,1}(\/content){0,1}\//i, '');
|
|
80
|
+
const slugs = requestPath.split('/');
|
|
81
|
+
const locale = channel.locales.some(x => x.slug == slugs[0]) ? slugs[0] : channel.defaultLocale;
|
|
82
|
+
if (context.isDebug)
|
|
83
|
+
console.log(`[OnPageEdit] Inferred content locale from path: ${locale}`);
|
|
84
|
+
const [contentId, workId] = getContentIds();
|
|
85
|
+
context.setLocale(channel.localeToGraphLocale(locale));
|
|
86
|
+
const contentLink = {
|
|
87
|
+
id: contentId,
|
|
88
|
+
workId: workId,
|
|
89
|
+
guidValue: null,
|
|
90
|
+
locale: locale
|
|
91
|
+
};
|
|
92
|
+
const variables = {
|
|
93
|
+
...contentLink,
|
|
94
|
+
locale: contentLink.locale,
|
|
95
|
+
isCommonDraft: !contentLink.workId ? true : null
|
|
96
|
+
};
|
|
97
|
+
if (context.isDebug) {
|
|
98
|
+
console.log("[OnPageEdit] Requested content:", JSON.stringify(variables));
|
|
99
|
+
console.log("[OnPageEdit] Creating GraphQL Client:", token);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const contentInfo = await getContentById(client, variables);
|
|
103
|
+
const contentItem = (contentInfo?.Content?.items ?? [])[0];
|
|
104
|
+
const contentType = Utils.normalizeContentType(contentItem?.contentType);
|
|
105
|
+
// Return a 404 if the content item or type could not be resolved
|
|
106
|
+
if (!contentItem) {
|
|
107
|
+
console.warn(`[OnPageEdit] The content item for ${JSON.stringify(variables)} could not be loaded from Optimizely Graph`);
|
|
108
|
+
return notFound();
|
|
109
|
+
}
|
|
110
|
+
if (!contentType) {
|
|
111
|
+
console.warn(`[OnPageEdit] The content item for ${JSON.stringify(variables)} did not contain content type information`);
|
|
112
|
+
return notFound();
|
|
113
|
+
}
|
|
114
|
+
if (context.isDebug) {
|
|
115
|
+
const contentItemId = contentItem?.id;
|
|
116
|
+
console.log("[OnPageEdit] Resolved content:", JSON.stringify({
|
|
117
|
+
id: contentItemId?.id,
|
|
118
|
+
workId: contentItemId?.workId,
|
|
119
|
+
guidValue: contentItemId?.guidValue,
|
|
120
|
+
locale: contentItem.locale?.name,
|
|
121
|
+
type: (contentItem.contentType ?? []).slice(0, -1).join('/')
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
// Store the editable content so it can be tested
|
|
125
|
+
context.setEditableContentId(contentLink);
|
|
126
|
+
// Render the content, with edit mode context
|
|
127
|
+
const isPage = contentItem.contentType?.some(x => x?.toLowerCase() == "page") ?? false;
|
|
128
|
+
const loadedContentId = Utils.normalizeContentLinkWithLocale({ ...contentItem?.id, locale: contentItem?.locale?.name });
|
|
129
|
+
const Layout = isPage ? PageLayout : React.Fragment;
|
|
130
|
+
const output = _jsxs(_Fragment, { children: [context.inEditMode && _jsx(Script, { src: `${dxpUrl}/ui/CMS/latest/clientresources/communicationinjector.js`, strategy: 'afterInteractive' }), _jsxs(Layout, { locale: locale, children: [_jsx(OnPageEdit, { timeout: refreshDelay, mode: context.inEditMode ? 'edit' : 'preview', className: 'bg-slate-900 absolute top-0 left-0 w-screen h-screen opacity-60 z-50', children: _jsx(RefreshNotice, {}) }), _jsx(CmsContent, { contentType: contentType, contentLink: contentLink, fragmentData: contentItem })] }), _jsxs("div", { className: 'optly-contentLink', children: ["ID: ", loadedContentId?.id ?? "-", " | Version: ", loadedContentId?.workId ?? "-", " | Global ID: ", loadedContentId?.guidValue ?? "-", " | Locale: ", loadedContentId?.locale ?? ""] })] });
|
|
131
|
+
return output;
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
console.error("[OnPageEdit] Caught error", e);
|
|
135
|
+
return notFound();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return EditPage;
|
|
139
|
+
}
|
|
140
|
+
export default createEditPageComponent;
|
|
141
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/ope/page.tsx"],"names":[],"mappings":";AAAA,OAAO,aAAa,CAAA;AAGpB,OAAO,EAAiB,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AACzE,OAAO,EAAE,KAAK,EAA8B,MAAM,8BAA8B,CAAA;AAChF,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAyB,MAAM,kCAAkC,CAAA;AACtG,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,UAAU,MAAM,4BAA4B,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AACrD,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAEvC,MAAM,cAAc,GAAqB;IACrC,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE,GAAG,EAAE,CAAC,cAAK,SAAS,EAAC,sBAAsB,kDAAwC;IAClG,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,eAAK,SAAS,EAAC,oBAAoB,aACrD,cAAK,SAAS,EAAC,mBAAmB,YAAG,KAAK,CAAC,KAAK,GAAQ,EACxD,cAAK,SAAS,EAAC,qBAAqB,YAAG,KAAK,CAAC,OAAO,GAAQ,IAC1D;IACN,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,cAAK,SAAS,EAAC,iBAAiB,iBAAe,KAAK,CAAC,MAAM,YACtE,KAAK,CAAC,QAAQ,GACd;IACN,MAAM,EAAE,cAAc;IACtB,aAAa,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,yBAAyB,CAAC,KAAK,CAAC;CACtE,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACnC,OAA6C,EAC7C,OAAyB,EACzB,OAAkC;IAIlC,MAAM,EACF,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,aAAa,EAC5B,YAAY,EACZ,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,cAAc,EACtB,aAAa,EAChB,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,OAAO,EAAE,CAAA;IAErC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;IAElC,KAAK,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAE,YAAY,EAAiB;QAE3D,iBAAiB;QACjB,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAA;QAElC,iCAAiC;QACjC,MAAM,WAAW,GAAG,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,CAAA;QAC5D,IAAI,WAAW,IAAI,MAAM,IAAI,WAAW,IAAI,OAAO,EAAE,CAAC;YAClD,OAAO,CAAC,KAAK,CAAC,mGAAmG,EAAE,YAAY,CAAC,WAAW,CAAC,CAAA;YAC5I,OAAO,QAAQ,EAAE,CAAA;QACrB,CAAC;QAED,iIAAiI;QACjI,MAAM,KAAK,GAAG,YAAY,CAAC,aAAa,CAAA;QACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,YAAY,CAAC,aAAa,IAAI,QAAQ,CAAC,IAAI,IAAI,YAAY,CAAC,aAAa,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAA;QACvI,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,0FAA0F,CAAC,CAAA;YACzG,OAAO,QAAQ,EAAE,CAAA;QACrB,CAAC;QACD,IAAI,OAAO,CAAC,OAAO;YACf,OAAO,CAAC,GAAG,CAAC,qDAAsD,YAAY,CAAC,WAAY,EAAE,CAAC,CAAA;QAElG,iDAAiD;QACjD,SAAS,aAAa;YAElB,IAAI,CAAC;gBACD,sEAAsE;gBACtE,IAAI,QAAQ,EAAE,CAAC;oBACX,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAA;oBAC7D,MAAM,CAAE,SAAS,EAAE,MAAM,CAAE,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,EAAC,CAAC,CAAC,CAAA;oBACxD,OAAO,CAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAE,CAAA;gBAClF,CAAC;gBAED,+CAA+C;gBAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;gBACzF,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC,CAAA;gBACxD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,CAAA;gBACzD,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE;oBAC7B,OAAO,CAAC,IAAI,CAAC,2FAA2F,CAAC,CAAA;gBAC7G,OAAO,CAAE,SAAS,EAAE,MAAM,CAAE,CAAA;YAChC,CAAC;YAAC,MAAM,CAAC;gBACL,OAAO,CAAE,CAAC,CAAC,EAAE,IAAI,CAAE,CAAA;YACvB,CAAC;QACL,CAAC;QACD,gBAAgB;QAChB,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;QACnC,OAAO,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAA;QACxC,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAA;QACpC,OAAO,CAAC,aAAa,CAAC,WAAW,IAAI,MAAM,CAAC,CAAA;QAE5C,uCAAuC;QACvC,MAAM,WAAW,GAAG,CAAC,GAAG,GAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,6CAA6C,EAAE,EAAE,CAAC,CAAA;QAClI,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACpC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAA;QAC/F,IAAI,OAAO,CAAC,OAAO;YACf,OAAO,CAAC,GAAG,CAAC,mDAAoD,MAAO,EAAE,CAAC,CAAA;QAC9E,MAAM,CAAE,SAAS,EAAE,MAAM,CAAE,GAAG,aAAa,EAAE,CAAA;QAC7C,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAA;QAEtD,MAAM,WAAW,GAA2B;YACxC,EAAE,EAAE,SAAS;YACb,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,MAAM;SACjB,CAAA;QACD,MAAM,SAAS,GAAG;YACd,GAAG,WAAW;YACd,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,aAAa,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;SACnD,CAAA;QACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAA;YACzE,OAAO,CAAC,GAAG,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAA;QAC/D,CAAC;QAED,IAAI,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;YAC3D,MAAM,WAAW,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1D,MAAM,WAAW,GAAG,KAAK,CAAC,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;YAExE,iEAAiE;YACjE,IAAI,CAAC,WAAW,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,qCAAsC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAE,4CAA4C,CAAC,CAAA;gBAC1H,OAAO,QAAQ,EAAE,CAAA;YACrB,CAAC;YACD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,qCAAsC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAE,2CAA2C,CAAC,CAAA;gBACzH,OAAO,QAAQ,EAAE,CAAA;YACrB,CAAC;YAED,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM,aAAa,GAAG,WAAW,EAAE,EAAE,CAAA;gBACrC,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,IAAI,CAAC,SAAS,CAAC;oBACzD,EAAE,EAAE,aAAa,EAAE,EAAE;oBACrB,MAAM,EAAE,aAAa,EAAE,MAAM;oBAC7B,SAAS,EAAE,aAAa,EAAE,SAAS;oBACnC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI;oBAChC,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;iBAC9D,CAAC,CAAC,CAAA;YACP,CAAC;YAED,iDAAiD;YACjD,OAAO,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAA;YAEzC,6CAA6C;YAC7C,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,MAAM,CAAC,IAAI,KAAK,CAAA;YACtF,MAAM,eAAe,GAAG,KAAK,CAAC,8BAA8B,CAAC,EAAE,GAAG,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;YACvH,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAA;YACnD,MAAM,MAAM,GAAI,8BACV,OAAO,CAAC,UAAU,IAAI,KAAC,MAAM,IAAC,GAAG,EAAE,GAAI,MAAO,yDAAyD,EAAE,QAAQ,EAAC,kBAAkB,GAAG,EACzI,MAAC,MAAM,IAAC,MAAM,EAAG,MAAM,aACnB,KAAC,UAAU,IAAC,OAAO,EAAG,YAAY,EAAG,IAAI,EAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAG,SAAS,EAAC,sEAAsE,YAClK,KAAC,aAAa,KAAG,GACR,EACb,KAAC,UAAU,IAAC,WAAW,EAAG,WAAW,EAAG,WAAW,EAAG,WAAW,EAAG,YAAY,EAAG,WAAW,GAAK,IAC9F,EACT,eAAK,SAAS,EAAC,mBAAmB,qBAAO,eAAe,EAAE,EAAE,IAAI,GAAG,kBAAe,eAAe,EAAE,MAAM,IAAI,GAAG,oBAAiB,eAAe,EAAE,SAAS,IAAI,GAAG,iBAAc,eAAe,EAAE,MAAM,IAAI,EAAE,IAAO,IACrN,CAAA;YACH,OAAO,MAAM,CAAA;QACjB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAA;YAC7C,OAAO,QAAQ,EAAE,CAAA;QACrB,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAA;AACnB,CAAC;AAED,eAAe,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ComponentType, PropsWithChildren } from 'react';
|
|
2
|
+
import type { ClientFactory } from '@remkoj/optimizely-graph-client';
|
|
3
|
+
import type { GraphQLClient } from 'graphql-request';
|
|
4
|
+
type ServerPageProps = {
|
|
5
|
+
params: Record<string, string | Array<string>>;
|
|
6
|
+
searchParams: Record<string, string>;
|
|
7
|
+
};
|
|
8
|
+
export type EditPageComponent<T extends ServerPageProps = EditPageProps> = ({ params, searchParams }: T) => Promise<JSX.Element>;
|
|
9
|
+
export type EditPageProps = {
|
|
10
|
+
params: {
|
|
11
|
+
path: string[];
|
|
12
|
+
};
|
|
13
|
+
searchParams: Partial<{
|
|
14
|
+
epieditmode: string;
|
|
15
|
+
preview_token: string;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
export type EditViewOptions = {
|
|
19
|
+
/**
|
|
20
|
+
* The number of miliseconds to wait between receiving the 'dataSaved'
|
|
21
|
+
* event from the Optimizely CMS and actually refreshing the preview.
|
|
22
|
+
*/
|
|
23
|
+
refreshDelay: number;
|
|
24
|
+
/**
|
|
25
|
+
* The message to show to the editor when awaiting the data to be updated
|
|
26
|
+
* in ContentGraph
|
|
27
|
+
*/
|
|
28
|
+
refreshNotice: ComponentType<{}>;
|
|
29
|
+
/**
|
|
30
|
+
* The message to show to the editor when an error occured in rendering the
|
|
31
|
+
* on page editing mode
|
|
32
|
+
*/
|
|
33
|
+
errorNotice: ComponentType<{
|
|
34
|
+
title: string;
|
|
35
|
+
message: string;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* The layout to use when rendering a page component
|
|
39
|
+
*/
|
|
40
|
+
layout: ComponentType<PropsWithChildren<{
|
|
41
|
+
locale: string;
|
|
42
|
+
}>>;
|
|
43
|
+
/**
|
|
44
|
+
* The base content loader to be used for the edit view
|
|
45
|
+
*/
|
|
46
|
+
loader: GetContentByIdMethod;
|
|
47
|
+
clientFactory: ClientFactory;
|
|
48
|
+
};
|
|
49
|
+
export type GetContentByIdVariables = {
|
|
50
|
+
id?: number;
|
|
51
|
+
workId?: number | null;
|
|
52
|
+
guidValue?: string | null;
|
|
53
|
+
locale?: string | Array<string>;
|
|
54
|
+
isCommonDraft?: boolean | null;
|
|
55
|
+
};
|
|
56
|
+
export type GetContentByIdData = {
|
|
57
|
+
Content: {
|
|
58
|
+
items: {
|
|
59
|
+
contentType?: Array<string | null> | null;
|
|
60
|
+
id: {
|
|
61
|
+
id?: number | null;
|
|
62
|
+
workId?: number | null;
|
|
63
|
+
guidValue?: string | null;
|
|
64
|
+
};
|
|
65
|
+
locale?: {
|
|
66
|
+
name?: string | null;
|
|
67
|
+
} | null;
|
|
68
|
+
path?: string | null;
|
|
69
|
+
}[];
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export type GetContentByIdMethod = (client: GraphQLClient, variables: GetContentByIdVariables) => Promise<GetContentByIdData>;
|
|
73
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ope/types.ts"],"names":[],"mappings":""}
|
package/dist/page.d.ts
ADDED
package/dist/page.js
ADDED
package/dist/page.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gCAAgC,CAAC,MAAW;IAExD,IAAI,CAAC,OAAM,CAAC,MAAM,CAAC,IAAI,UAAU,IAAI,OAAM,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,IAAI;QAC9E,OAAO,KAAK,CAAA;IAEhB,OAAQ,MAA6B,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;AACrE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { type IOptiGraphClient } from "@remkoj/optimizely-graph-client";
|
|
3
|
+
export type PublishApiResponse = {
|
|
4
|
+
status: "success" | "no-publish";
|
|
5
|
+
paths?: string[];
|
|
6
|
+
} | {
|
|
7
|
+
error: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function createPublishApi(client?: IOptiGraphClient): (req: NextRequest) => Promise<NextResponse<PublishApiResponse>>;
|
|
10
|
+
export default createPublishApi;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getServerClient } from '../client';
|
|
3
|
+
import { revalidatePath } from 'next/cache';
|
|
4
|
+
const editPaths = ['/ui/[[...path]]'];
|
|
5
|
+
const publishedPaths = ['/[lang]', '/[lang]/[[...path]]', '/sitemap', '/sitemap.xml'];
|
|
6
|
+
const paths = [...editPaths, ...publishedPaths];
|
|
7
|
+
export function createPublishApi(client) {
|
|
8
|
+
const graphClient = client ?? getServerClient();
|
|
9
|
+
function tryJsonParse(data) {
|
|
10
|
+
if (typeof (data) != 'string')
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(data);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const publishHandler = async (req) => {
|
|
20
|
+
// Validate access
|
|
21
|
+
const xAuthToken = req.headers.get("X-OPTLY-PUBLISH") ??
|
|
22
|
+
req.nextUrl.searchParams.get("token") ??
|
|
23
|
+
undefined;
|
|
24
|
+
const serverToken = graphClient.siteInfo.publishToken;
|
|
25
|
+
if (!serverToken || serverToken == "") {
|
|
26
|
+
console.error("No authentication configured, publishing has been disabled");
|
|
27
|
+
return NextResponse.json({ error: "Not authorized" }, { status: 401 });
|
|
28
|
+
}
|
|
29
|
+
if (serverToken != xAuthToken) {
|
|
30
|
+
console.error("[Publish-API] The provided publishing token is invalid", xAuthToken);
|
|
31
|
+
return NextResponse.json({ error: "Not authorized" }, { status: 401 });
|
|
32
|
+
}
|
|
33
|
+
// Get request data
|
|
34
|
+
const requestBody = tryJsonParse(await req.text());
|
|
35
|
+
// Don't publish if we're in selective mode and there's no data
|
|
36
|
+
if (!requestBody) {
|
|
37
|
+
console.log("Not flushing due to missing request body");
|
|
38
|
+
return NextResponse.json({ status: "no-publish" });
|
|
39
|
+
}
|
|
40
|
+
const action = requestBody.type?.action;
|
|
41
|
+
const subject = requestBody.type?.subject;
|
|
42
|
+
// Only publish on updated documents
|
|
43
|
+
if (subject != "doc" || action != "updated") {
|
|
44
|
+
console.log("Not flushing due to incorrect subject or type", JSON.stringify(requestBody));
|
|
45
|
+
return NextResponse.json({ status: "no-publish" });
|
|
46
|
+
}
|
|
47
|
+
paths.forEach(p => revalidatePath(p, 'page'));
|
|
48
|
+
console.log("Publishing => Revalidated (paths)", paths);
|
|
49
|
+
return NextResponse.json({ status: "success", paths });
|
|
50
|
+
};
|
|
51
|
+
return publishHandler;
|
|
52
|
+
}
|
|
53
|
+
export default createPublishApi;
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/publish/index.ts"],"names":[],"mappings":"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"}
|