@remkoj/optimizely-cms-react 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/browser/context.d.ts +6 -0
- package/dist/browser/context.js +15 -0
- package/dist/browser/context.js.map +1 -0
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/factory.d.ts +30 -0
- package/dist/factory.js +65 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/server/components/cms-content-area.d.ts +14 -0
- package/dist/server/components/cms-content-area.js +101 -0
- package/dist/server/components/cms-content-area.js.map +1 -0
- package/dist/server/components/cms-content.d.ts +12 -0
- package/dist/server/components/cms-content.js +106 -0
- package/dist/server/components/cms-content.js.map +1 -0
- package/dist/server/components/get-content-type.d.ts +12 -0
- package/dist/server/components/get-content-type.js +55 -0
- package/dist/server/components/get-content-type.js.map +1 -0
- package/dist/server/components/index.d.ts +2 -0
- package/dist/server/components/index.js +3 -0
- package/dist/server/components/index.js.map +1 -0
- package/dist/server/components/queries.d.ts +19 -0
- package/dist/server/components/queries.js +142 -0
- package/dist/server/components/queries.js.map +1 -0
- package/dist/server/components/types.d.ts +176 -0
- package/dist/server/components/types.js +2 -0
- package/dist/server/components/types.js.map +1 -0
- package/dist/server/components/utils.d.ts +10 -0
- package/dist/server/components/utils.js +28 -0
- package/dist/server/context.d.ts +35 -0
- package/dist/server/context.js +82 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/factory.d.ts +10 -0
- package/dist/server/factory.js +18 -0
- package/dist/server/factory.js.map +1 -0
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.js +6 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/is-debug.d.ts +3 -0
- package/dist/server/is-debug.js +19 -0
- package/dist/server/is-debug.js.map +1 -0
- package/dist/server/type-utils.d.ts +31 -0
- package/dist/server/type-utils.js +2 -0
- package/dist/server/type-utils.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utilities.d.ts +29 -0
- package/dist/utilities.js +98 -0
- package/dist/utilities.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { gql } from 'graphql-request';
|
|
2
|
+
export const CmsContentFragments = {
|
|
3
|
+
IContentDataProps: ["contentType", "id", "locale", "path", "__typename"],
|
|
4
|
+
ContentLink: gql `fragment ContentLink on ContentModelReference {
|
|
5
|
+
id: Id,
|
|
6
|
+
workId: WorkId,
|
|
7
|
+
guidValue: GuidValue
|
|
8
|
+
}`,
|
|
9
|
+
ContentLinkSearch: gql `fragment ContentLinkSearch on ContentModelReferenceSearch {
|
|
10
|
+
id: Id,
|
|
11
|
+
workId: WorkId,
|
|
12
|
+
guidValue: GuidValue
|
|
13
|
+
}`,
|
|
14
|
+
IContentData: gql `fragment IContentData on IContent {
|
|
15
|
+
contentType: ContentType
|
|
16
|
+
id: ContentLink {
|
|
17
|
+
...ContentLink
|
|
18
|
+
}
|
|
19
|
+
locale: Language {
|
|
20
|
+
name: Name
|
|
21
|
+
}
|
|
22
|
+
path:RelativePath
|
|
23
|
+
}`,
|
|
24
|
+
ContentAreaItemData: gql `fragment ContentAreaItemData on ContentAreaItemModelSearch {
|
|
25
|
+
item: ContentLink {
|
|
26
|
+
...ContentLinkSearch
|
|
27
|
+
data: Expanded {
|
|
28
|
+
...BlockData
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
displayOption:DisplayOption
|
|
32
|
+
}`,
|
|
33
|
+
BlockContentAreaItemSearchData: gql `fragment BlockContentAreaItemSearchData on ContentAreaItemModelSearch {
|
|
34
|
+
item: ContentLink {
|
|
35
|
+
...ContentLinkSearch
|
|
36
|
+
data: Expanded {
|
|
37
|
+
...IContentData
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
displayOption:DisplayOption
|
|
41
|
+
}`,
|
|
42
|
+
BlockContentAreaItemData: gql `fragment BlockContentAreaItemData on ContentAreaItemModel {
|
|
43
|
+
item: ContentLink {
|
|
44
|
+
...ContentLink
|
|
45
|
+
data: Expanded {
|
|
46
|
+
...IContentData
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
displayOption:DisplayOption
|
|
50
|
+
}`,
|
|
51
|
+
LinkItemData: gql `fragment LinkItemData on LinkItemNode {
|
|
52
|
+
children: Text
|
|
53
|
+
title: Title
|
|
54
|
+
href: Href
|
|
55
|
+
target: Target
|
|
56
|
+
content: ContentLink {
|
|
57
|
+
href: Url
|
|
58
|
+
data: Expanded {
|
|
59
|
+
path: RelativePath
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}`,
|
|
63
|
+
ImageData: gql `fragment ImageData on ContentModelReference {
|
|
64
|
+
...ContentLink
|
|
65
|
+
url: Url
|
|
66
|
+
data: Expanded {
|
|
67
|
+
...IContentData
|
|
68
|
+
url: Url
|
|
69
|
+
alt: Name
|
|
70
|
+
path: RelativePath
|
|
71
|
+
}
|
|
72
|
+
}`,
|
|
73
|
+
ImageDataSearch: gql `fragment ImageDataSearch on ContentModelReferenceSearch {
|
|
74
|
+
...ContentLinkSearch
|
|
75
|
+
url: Url
|
|
76
|
+
data: Expanded {
|
|
77
|
+
...IContentData
|
|
78
|
+
url: Url
|
|
79
|
+
alt: Name
|
|
80
|
+
path: RelativePath
|
|
81
|
+
}
|
|
82
|
+
}`,
|
|
83
|
+
BlockData: gql `fragment BlockData on IContent {
|
|
84
|
+
...IContentData
|
|
85
|
+
}`,
|
|
86
|
+
PageData: gql `fragment PageData on IContent {
|
|
87
|
+
...IContentData
|
|
88
|
+
}`
|
|
89
|
+
};
|
|
90
|
+
export const ContentAreaFragments = {
|
|
91
|
+
ContentAreaItemBase: gql `fragment ContentAreaItemBase on ContentAreaItemModelSearch {
|
|
92
|
+
contentLink:ContentLink {
|
|
93
|
+
id:Id
|
|
94
|
+
workId:WorkId
|
|
95
|
+
guidValue:GuidValue
|
|
96
|
+
component:Expanded {
|
|
97
|
+
path:RelativePath
|
|
98
|
+
type:ContentType
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
displayOption:DisplayOption
|
|
102
|
+
}`
|
|
103
|
+
};
|
|
104
|
+
export const getContentById = gql `query getContentById($id: Int, $workId: Int, $guidValue: String, $locale: [Locales!], $isCommonDraft: Boolean) {
|
|
105
|
+
Content(
|
|
106
|
+
where: {
|
|
107
|
+
ContentLink: {
|
|
108
|
+
Id: { eq: $id },
|
|
109
|
+
WorkId: { eq: $workId },
|
|
110
|
+
GuidValue: { eq: $guidValue }
|
|
111
|
+
}
|
|
112
|
+
IsCommonDraft: { eq: $isCommonDraft }
|
|
113
|
+
}
|
|
114
|
+
locale: $locale
|
|
115
|
+
) {
|
|
116
|
+
total
|
|
117
|
+
items {
|
|
118
|
+
...IContentData
|
|
119
|
+
...PageData
|
|
120
|
+
...BlockData
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}`;
|
|
124
|
+
export const getContentByPath = gql `query getContentByPath($path: String!, $locale: [Locales], $siteId: String)
|
|
125
|
+
{
|
|
126
|
+
Content(
|
|
127
|
+
where: {
|
|
128
|
+
RelativePath: {
|
|
129
|
+
eq: $path
|
|
130
|
+
}
|
|
131
|
+
SiteId: {
|
|
132
|
+
eq: $siteId
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
locale: $locale
|
|
136
|
+
) {
|
|
137
|
+
items {
|
|
138
|
+
...PageData
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}`;
|
|
142
|
+
//# sourceMappingURL=queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/server/components/queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAErC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAC/B,iBAAiB,EAAE,CAAC,aAAa,EAAC,IAAI,EAAC,QAAQ,EAAC,MAAM,EAAC,YAAY,CAAC;IACpE,WAAW,EAAE,GAAG,CAAA;;;;MAId;IACF,iBAAiB,EAAE,GAAG,CAAA;;;;MAIpB;IACF,YAAY,EAAE,GAAG,CAAA;;;;;;;;;MASf;IACF,mBAAmB,EAAE,GAAG,CAAA;;;;;;;;MAQtB;IACF,8BAA8B,EAAE,GAAG,CAAA;;;;;;;;MAQjC;IACF,wBAAwB,EAAE,GAAG,CAAA;;;;;;;;MAQ3B;IACF,YAAY,EAAE,GAAG,CAAA;;;;;;;;;;;MAWf;IACF,SAAS,EAAE,GAAG,CAAA;;;;;;;;;MASZ;IACF,eAAe,EAAE,GAAG,CAAA;;;;;;;;;MASlB;IACF,SAAS,EAAE,GAAG,CAAA;;MAEZ;IACF,QAAQ,EAAE,GAAG,CAAA;;MAEX;CACL,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,mBAAmB,EAAE,GAAG,CAAA;;;;;;;;;;;IAWtB;CACH,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;EAmB/B,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;EAiBjC,CAAA"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { SuspenseProps, PropsWithChildren } from "react";
|
|
2
|
+
import type { ContentLinkWithLocale, ComponentFactory, ContentType } from "../../types";
|
|
3
|
+
import type { ElementChildrenProps, ElementProps, ElementType, PropTypeIfPropExists, MayBeArray, TypeIfPropExists } from '../type-utils';
|
|
4
|
+
import type { IOptiGraphClient } from "@remkoj/optimizely-graph-client";
|
|
5
|
+
export type CmsContentProps = PropsWithChildren<{
|
|
6
|
+
/**
|
|
7
|
+
* The content type to render
|
|
8
|
+
*/
|
|
9
|
+
contentType?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* The content link to render
|
|
12
|
+
*/
|
|
13
|
+
contentLink: ContentLinkWithLocale;
|
|
14
|
+
/**
|
|
15
|
+
* The initial, pre-loaded data. If set this will be used instead of having the
|
|
16
|
+
* component fetching its' own data. So be sure that this leverages the fragment
|
|
17
|
+
* specified by the component.
|
|
18
|
+
*
|
|
19
|
+
* It will filter out the fiels from the IContentData fragment, to determine if
|
|
20
|
+
* data has been provided.
|
|
21
|
+
*/
|
|
22
|
+
fragmentData?: {
|
|
23
|
+
[fieldname: string]: any;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The native key to use when the element is part of an array
|
|
27
|
+
*/
|
|
28
|
+
key?: string;
|
|
29
|
+
/**
|
|
30
|
+
* If enabled, it will flag all rendering to be inclusive of the Optimizely Edit mode
|
|
31
|
+
* attributes for On Page Editing
|
|
32
|
+
*
|
|
33
|
+
* @deprecated Will be retrieved from the ServerContext
|
|
34
|
+
*/
|
|
35
|
+
inEditMode?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The Optimizely Graph client to use, it will use a new instance if none is provided,
|
|
38
|
+
* the new instance will always use the SingleKey i.e. thus not load edit mode content
|
|
39
|
+
*
|
|
40
|
+
* @deprecated Will be retrieved from the ServerContext
|
|
41
|
+
*/
|
|
42
|
+
client?: IOptiGraphClient;
|
|
43
|
+
/**
|
|
44
|
+
* The component factory to use, it will use the default instance if not provided
|
|
45
|
+
*
|
|
46
|
+
* @deprecated Will be retrieved from the ServerContext
|
|
47
|
+
*/
|
|
48
|
+
factory?: ComponentFactory;
|
|
49
|
+
/**
|
|
50
|
+
* If enabled any warnings intended for an editor will be shown, even if "inEditMode"
|
|
51
|
+
* is false.
|
|
52
|
+
*
|
|
53
|
+
* @deprecated Will be retrieved from the ServerContext
|
|
54
|
+
*/
|
|
55
|
+
outputEditorWarning?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The prefix to apply to the content type, to allow loading of different templates based
|
|
58
|
+
* upon location of usage. If set and the content type already starts with this prefix,
|
|
59
|
+
* it will not be applied.
|
|
60
|
+
*/
|
|
61
|
+
contentTypePrefix?: string;
|
|
62
|
+
}>;
|
|
63
|
+
type RawContentLink = {
|
|
64
|
+
id?: number | null;
|
|
65
|
+
workId?: number | null;
|
|
66
|
+
guidValue?: string | null;
|
|
67
|
+
};
|
|
68
|
+
type RawLocale = {
|
|
69
|
+
name?: string | null;
|
|
70
|
+
};
|
|
71
|
+
export type ContentAreaItemDefinition = {
|
|
72
|
+
__typename?: "ContentAreaItemModelSearch" | "ContentAreaItemModel";
|
|
73
|
+
item?: (RawContentLink & {
|
|
74
|
+
data?: {
|
|
75
|
+
contentType?: (string | null)[] | null;
|
|
76
|
+
id?: RawContentLink | null;
|
|
77
|
+
locale?: RawLocale | null;
|
|
78
|
+
[property: string]: any;
|
|
79
|
+
} | null;
|
|
80
|
+
}) | null;
|
|
81
|
+
displayOption?: string | null;
|
|
82
|
+
tag?: string | null;
|
|
83
|
+
};
|
|
84
|
+
export type CmsContentAreaProps<T extends ElementType, CT extends ElementType> = {
|
|
85
|
+
/**
|
|
86
|
+
* The content area items to be rendered
|
|
87
|
+
*/
|
|
88
|
+
items: (ContentAreaItemDefinition | null | undefined)[] | undefined | null;
|
|
89
|
+
/**
|
|
90
|
+
* The mapper used to apply CSS Classes to items, based upon
|
|
91
|
+
* the display mode (PaaS Only), Content type and position in
|
|
92
|
+
* content area.
|
|
93
|
+
*/
|
|
94
|
+
classMapper?: TypeIfPropExists<T, "className", CmsContentAreaClassMapper>;
|
|
95
|
+
/**
|
|
96
|
+
* The CSS Class to apply to the content area container
|
|
97
|
+
*/
|
|
98
|
+
className?: MayBeArray<PropTypeIfPropExists<T, "className">>;
|
|
99
|
+
/**
|
|
100
|
+
* The fallback component to use as suspense boundary
|
|
101
|
+
*/
|
|
102
|
+
fallback?: SuspenseProps['fallback'];
|
|
103
|
+
/**
|
|
104
|
+
* The fieldname of this content area, provide this to allow in-context
|
|
105
|
+
* editing
|
|
106
|
+
*/
|
|
107
|
+
fieldName?: string;
|
|
108
|
+
/**
|
|
109
|
+
* The HTML element, or React Component to use to render the Content Area Container
|
|
110
|
+
*/
|
|
111
|
+
as?: T;
|
|
112
|
+
itemWrapper?: ({
|
|
113
|
+
/**
|
|
114
|
+
* Override the element type used to wrap the CMS Content Item
|
|
115
|
+
*/
|
|
116
|
+
as?: CT;
|
|
117
|
+
/**
|
|
118
|
+
* The CSS Class to apply to the content area item wrapper
|
|
119
|
+
*/
|
|
120
|
+
className?: MayBeArray<PropTypeIfPropExists<CT, "className">>;
|
|
121
|
+
} & ("children" extends ElementChildrenProps<CT> ? {
|
|
122
|
+
/**
|
|
123
|
+
* The property of the component set for the "as" property of the Content Area Item
|
|
124
|
+
* which should receive the items within the Content Area.
|
|
125
|
+
*
|
|
126
|
+
* Defaults to "children", if not provided
|
|
127
|
+
*/
|
|
128
|
+
itemsProperty?: ElementChildrenProps<CT>;
|
|
129
|
+
} : {
|
|
130
|
+
/**
|
|
131
|
+
* The property of the component set for the "as" property of the Content Area Item
|
|
132
|
+
* which should receive the items within the Content Area.
|
|
133
|
+
*/
|
|
134
|
+
itemsProperty: ElementChildrenProps<CT>;
|
|
135
|
+
}) & Omit<Omit<ElementProps<CT>, "className" | "data-epi-block-id" | "data-displayoption" | "data-tag">, ElementChildrenProps<CT>>);
|
|
136
|
+
/**
|
|
137
|
+
* Ignored if provided
|
|
138
|
+
*
|
|
139
|
+
* @deprecated The ServerContext is used to access the current locale
|
|
140
|
+
*/
|
|
141
|
+
locale?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Ignored if provided
|
|
144
|
+
*
|
|
145
|
+
* @deprecated The ServerContext is used to access the current edit mode status
|
|
146
|
+
*/
|
|
147
|
+
inEditMode?: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Ignored if provided
|
|
150
|
+
*
|
|
151
|
+
* @deprecated The ServerContext is used to access the current Optimizely Graph Client
|
|
152
|
+
*/
|
|
153
|
+
client?: IOptiGraphClient;
|
|
154
|
+
/**
|
|
155
|
+
* Ignored if provided
|
|
156
|
+
*
|
|
157
|
+
* @deprecated The ServerContext is used to access the current Component Factory
|
|
158
|
+
*/
|
|
159
|
+
factory?: ComponentFactory;
|
|
160
|
+
} & Omit<Omit<ElementProps<T>, "className" | "data-epi-edit">, ElementChildrenProps<T>> & ("children" extends ElementChildrenProps<T> ? {
|
|
161
|
+
/**
|
|
162
|
+
* The property of the component set for the "as" property of the Content Area which
|
|
163
|
+
* should receive the items within the Content Area.
|
|
164
|
+
*
|
|
165
|
+
* Defaults to "children", if not provided
|
|
166
|
+
*/
|
|
167
|
+
itemsProperty?: ElementChildrenProps<T>;
|
|
168
|
+
} : {
|
|
169
|
+
/**
|
|
170
|
+
* The property of the component set for the "as" property of the Content Area which
|
|
171
|
+
* should receive the items within the Content Area.
|
|
172
|
+
*/
|
|
173
|
+
itemsProperty: ElementChildrenProps<T>;
|
|
174
|
+
});
|
|
175
|
+
export type CmsContentAreaClassMapper = (displayOption: string, contentType: ContentType | null, index: number) => string;
|
|
176
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/server/components/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ContentType, ContentLinkWithLocale } from "../../types";
|
|
2
|
+
import type { IOptiGraphClient } from "@remkoj/optimizely-graph-client";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the ContentType of an Optimizely CMS Component, identified by its content link
|
|
5
|
+
*
|
|
6
|
+
* @param link The ContentLink of the content item
|
|
7
|
+
* @param gqlClient The GraphQL client to use
|
|
8
|
+
* @returns The ContentType, or undefined if it cannot be resolved
|
|
9
|
+
*/
|
|
10
|
+
export declare function getContentType(link: ContentLinkWithLocale, gqlClient: IOptiGraphClient): Promise<ContentType | undefined>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Utils from "../../utilities";
|
|
2
|
+
import * as Queries from "./queries";
|
|
3
|
+
const DEBUG = false;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the ContentType of an Optimizely CMS Component, identified by its content link
|
|
6
|
+
*
|
|
7
|
+
* @param link The ContentLink of the content item
|
|
8
|
+
* @param gqlClient The GraphQL client to use
|
|
9
|
+
* @returns The ContentType, or undefined if it cannot be resolved
|
|
10
|
+
*/
|
|
11
|
+
export async function getContentType(link, gqlClient) {
|
|
12
|
+
if ((!link.id || link.id < 1) && (!link.guidValue || link.guidValue == ""))
|
|
13
|
+
throw new Error("Cannot dynamically determine the content type of an inline block");
|
|
14
|
+
const gqlQueryVars = Utils.contentLinkToRequestVariables(link);
|
|
15
|
+
const gqlResponse = await gqlClient.request(Queries.getContentTypeQuery, gqlQueryVars);
|
|
16
|
+
if (gqlResponse.Content?.total != 1) {
|
|
17
|
+
if (DEBUG)
|
|
18
|
+
console.error(`getContentType: Expected exactly one type, received ${gqlResponse.Content?.total ?? 0} types for`, gqlQueryVars);
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const items = gqlResponse.Content?.items;
|
|
22
|
+
if (!items || items.length == 0)
|
|
23
|
+
throw new Error("The content item could not be found!");
|
|
24
|
+
const contentType = Utils.normalizeContentType(items[0]?.ContentType);
|
|
25
|
+
if (!contentType)
|
|
26
|
+
throw new Error("The item did not contain type information");
|
|
27
|
+
return contentType;
|
|
28
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import type { ComponentFactory } from '../types';
|
|
3
|
+
import type { IOptiGraphClient } from "@remkoj/optimizely-graph-client";
|
|
4
|
+
export type EditableContentId = {
|
|
5
|
+
id: number | null;
|
|
6
|
+
workId?: number | null;
|
|
7
|
+
guidValue?: string | null;
|
|
8
|
+
} | {
|
|
9
|
+
id?: number | null;
|
|
10
|
+
workId?: number | null;
|
|
11
|
+
guidValue: string | null;
|
|
12
|
+
};
|
|
13
|
+
export interface ServerContext {
|
|
14
|
+
readonly inEditMode: Readonly<boolean>;
|
|
15
|
+
readonly isDevelopment: boolean;
|
|
16
|
+
readonly isDebug: boolean;
|
|
17
|
+
readonly isDebugOrDevelopment: boolean;
|
|
18
|
+
readonly client?: IOptiGraphClient;
|
|
19
|
+
readonly factory: ComponentFactory;
|
|
20
|
+
readonly forceEditorWarnings: boolean;
|
|
21
|
+
readonly locale?: string;
|
|
22
|
+
setInEditMode(newValue: boolean): ServerContext;
|
|
23
|
+
setOptimizelyGraphClient(newValue: IOptiGraphClient): ServerContext;
|
|
24
|
+
setComponentFactory(newValue: ComponentFactory): ServerContext;
|
|
25
|
+
setForceEditorWarnings(newValue: boolean): ServerContext;
|
|
26
|
+
setLocale(newValue: string | undefined): ServerContext;
|
|
27
|
+
setEditableContentId(newId: EditableContentId): ServerContext;
|
|
28
|
+
isEditableContent(id: EditableContentId): boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Retrieve the working instance of the component factory, which is memoized through the React.cache()
|
|
32
|
+
* server side react method. This ensures the context will not be shared across pre-renders / requests.
|
|
33
|
+
*/
|
|
34
|
+
export declare const getServerContext: () => ServerContext;
|
|
35
|
+
export default getServerContext;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { isDevelopment, isDebug } from "./is-debug";
|
|
4
|
+
import { getFactory } from '../factory';
|
|
5
|
+
class DefaultServerContext {
|
|
6
|
+
_inEditMode = false;
|
|
7
|
+
_forceEditorWarnings = false;
|
|
8
|
+
_client = undefined;
|
|
9
|
+
_factory = undefined;
|
|
10
|
+
_locale = undefined;
|
|
11
|
+
_editableContent = undefined;
|
|
12
|
+
get inEditMode() {
|
|
13
|
+
return this._inEditMode;
|
|
14
|
+
}
|
|
15
|
+
get isDebug() {
|
|
16
|
+
return isDebug();
|
|
17
|
+
}
|
|
18
|
+
get isDevelopment() {
|
|
19
|
+
return isDevelopment();
|
|
20
|
+
}
|
|
21
|
+
get isDebugOrDevelopment() {
|
|
22
|
+
return isDevelopment() || isDebug();
|
|
23
|
+
}
|
|
24
|
+
get client() {
|
|
25
|
+
return this._client;
|
|
26
|
+
}
|
|
27
|
+
get factory() {
|
|
28
|
+
return this._factory ?? getFactory();
|
|
29
|
+
}
|
|
30
|
+
get forceEditorWarnings() {
|
|
31
|
+
return this._forceEditorWarnings;
|
|
32
|
+
}
|
|
33
|
+
get locale() {
|
|
34
|
+
return this._locale;
|
|
35
|
+
}
|
|
36
|
+
setInEditMode(newValue) {
|
|
37
|
+
this._inEditMode = newValue;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
setOptimizelyGraphClient(newValue) {
|
|
41
|
+
this._client = newValue;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
setComponentFactory(newValue) {
|
|
45
|
+
this._factory = newValue;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
setForceEditorWarnings(newValue) {
|
|
49
|
+
this._forceEditorWarnings = newValue;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
setLocale(newValue) {
|
|
53
|
+
this._locale = newValue;
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
setEditableContentId(newId) {
|
|
57
|
+
this._editableContent = newId;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
isEditableContent(id) {
|
|
61
|
+
if (!this.inEditMode || !this._editableContent)
|
|
62
|
+
return false; // We can on be editable in edit mode and with an id set
|
|
63
|
+
if (id.id != this._editableContent.id && id.guidValue != this._editableContent.guidValue)
|
|
64
|
+
return false; // Both ID and GUID don't match
|
|
65
|
+
if (this._editableContent.workId && this._editableContent.workId != id.workId)
|
|
66
|
+
return false; // We know the work ID and it doesn't match
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Retrieve the working instance of the component factory, which is memoized through the React.cache()
|
|
72
|
+
* server side react method. This ensures the context will not be shared across pre-renders / requests.
|
|
73
|
+
*/
|
|
74
|
+
//@ts-expect-error React.cache is a canary function, not yet always properly resolved by TypeScript
|
|
75
|
+
export const getServerContext = React.cache(() => {
|
|
76
|
+
const ctx = new DefaultServerContext();
|
|
77
|
+
if (ctx.isDebug)
|
|
78
|
+
console.log('🦺 [ServerContext] Created new context');
|
|
79
|
+
return ctx;
|
|
80
|
+
});
|
|
81
|
+
export default getServerContext;
|
|
82
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import type * as Types from '../types';
|
|
3
|
+
export type { ComponentFactory } from '../types';
|
|
4
|
+
export { DefaultComponentFactory } from '../factory';
|
|
5
|
+
/**
|
|
6
|
+
* Retrieve the working instance of the component factory, which is memoized through the React.cache()
|
|
7
|
+
* server side react method
|
|
8
|
+
*/
|
|
9
|
+
export declare const getFactory: () => Types.ComponentFactory;
|
|
10
|
+
export default getFactory;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DefaultComponentFactory as DefaultFactory } from '../factory';
|
|
4
|
+
import isDebug from './is-debug';
|
|
5
|
+
export { DefaultComponentFactory } from '../factory';
|
|
6
|
+
/**
|
|
7
|
+
* Retrieve the working instance of the component factory, which is memoized through the React.cache()
|
|
8
|
+
* server side react method
|
|
9
|
+
*/
|
|
10
|
+
//@ts-expect-error React.cache is a canary function, not yet always properly resolved by TypeScript
|
|
11
|
+
export const getFactory = React.cache(() => {
|
|
12
|
+
const factory = new DefaultFactory();
|
|
13
|
+
if (isDebug())
|
|
14
|
+
console.log('⚪ [ComponentFactory] Created new DefaultComponentFactory (RSC)');
|
|
15
|
+
return factory;
|
|
16
|
+
});
|
|
17
|
+
export default getFactory;
|
|
18
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/server/factory.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AACpB,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,uBAAuB,IAAI,cAAc,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,OAAO,MAAM,YAAY,CAAA;AAGhC,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAEpD;;;GAGG;AACH,oGAAoG;AACpG,MAAM,CAAC,MAAM,UAAU,GAAkC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE;IACtE,MAAM,OAAO,GAAG,IAAI,cAAc,EAAE,CAAA;IACpC,IAAI,OAAO,EAAE;QACT,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAA;IACjF,OAAO,OAAO,CAAA;AAClB,CAAC,CAAC,CAAA;AAEF,eAAe,UAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AACpB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function isDebug() {
|
|
2
|
+
try {
|
|
3
|
+
const value = process?.env?.OPTIMIZELY_DEBUG ?? process?.env?.DXP_DEBUG;
|
|
4
|
+
return value ? value == '1' || value.toLowerCase() == 'true' : false;
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function isDevelopment() {
|
|
11
|
+
try {
|
|
12
|
+
return process.env.NODE_ENV == 'development';
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export default isDebug;
|
|
19
|
+
//# sourceMappingURL=is-debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-debug.js","sourceRoot":"","sources":["../../src/server/is-debug.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO;IAEnB,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,EAAE,GAAG,EAAE,gBAAgB,IAAI,OAAO,EAAE,GAAG,EAAE,SAAS,CAAA;QACvE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;IACxE,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa;IAEzB,IAAI,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAA;IAChD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED,eAAe,OAAO,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/**
|
|
3
|
+
* Tests if K is a property of T - if so: it is the type of
|
|
4
|
+
* T[K]; if not: it is equal to never
|
|
5
|
+
*/
|
|
6
|
+
export type PropTypeIfPropExists<T extends ElementType, K> = K extends keyof ElementProps<T> ? ElementProps<T>[K] : never;
|
|
7
|
+
/**
|
|
8
|
+
* Tests if K is a property of T - if so: it is equal to U;
|
|
9
|
+
* if not: it is equal to never
|
|
10
|
+
*/
|
|
11
|
+
export type TypeIfPropExists<T extends ElementType, K, U> = K extends keyof ElementProps<T> ? U : never;
|
|
12
|
+
/**
|
|
13
|
+
* Defines the type to be T or an array of T
|
|
14
|
+
*/
|
|
15
|
+
export type MayBeArray<T> = T | T[];
|
|
16
|
+
/**
|
|
17
|
+
* The properties type of an ElementType
|
|
18
|
+
*/
|
|
19
|
+
export type ElementProps<T extends ElementType> = T extends keyof JSX.IntrinsicElements ? React.HTMLProps<JSX.IntrinsicElements[T]> : React.ComponentProps<T>;
|
|
20
|
+
/**
|
|
21
|
+
* The union of property names of an Element that may receive child elements
|
|
22
|
+
*/
|
|
23
|
+
export type ElementChildrenProps<T extends ElementType> = keyof {
|
|
24
|
+
[P in keyof ElementProps<T> as React.ReactElement[] extends ElementProps<T>[P] ? P : never]: ElementProps<T>[P];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Define an element as a React Component, React ExoticComponent or string name
|
|
28
|
+
* representing a HTML Element (e.g. "div", "a", etc...), this value can be used
|
|
29
|
+
* as first argument of React.createElement()
|
|
30
|
+
*/
|
|
31
|
+
export type ElementType = (React.ComponentType<any>) | (React.ExoticComponent<any>) | (keyof JSX.IntrinsicElements);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../src/server/type-utils.ts"],"names":[],"mappings":""}
|