@uniformdev/canvas-next-rsc 19.49.0 → 19.49.4-alpha.67

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 (39) hide show
  1. package/dist/actions/updateContext.d.ts +2 -0
  2. package/dist/actions/updateContext.js +17 -0
  3. package/dist/client/routeClient.js +12 -1
  4. package/dist/components/DefaultNotImplementedComponent.d.ts +1 -1
  5. package/dist/components/GoogleTagManagerAnalytics.d.ts +1 -1
  6. package/dist/components/UniformComponent.d.ts +3 -0
  7. package/dist/components/UniformComposition.d.ts +7 -2
  8. package/dist/components/UniformComposition.js +10 -62
  9. package/dist/components/UniformContext.d.ts +1 -4
  10. package/dist/components/UniformRichTextNode.d.ts +1 -1
  11. package/dist/components/UniformScript.d.ts +1 -1
  12. package/dist/components/UniformText.d.ts +5 -13
  13. package/dist/components/UniformText.js +3 -7
  14. package/dist/components/__tests__/evaluateComposition.spec.js +12 -4
  15. package/dist/components/evaluateComposition.d.ts +3 -3
  16. package/dist/components/evaluateComposition.js +47 -16
  17. package/dist/components/getUniformContext.d.ts +6 -0
  18. package/dist/components/getUniformContext.js +17 -0
  19. package/dist/components/renderComponent.js +7 -8
  20. package/dist/components/retrieveRoute.d.ts +131 -0
  21. package/dist/components/retrieveRoute.js +74 -5
  22. package/dist/config/helpers.d.ts +2 -0
  23. package/dist/config/helpers.js +15 -1
  24. package/dist/config/models.d.ts +4 -0
  25. package/dist/config.js +14 -25
  26. package/dist/handler/helpers.js +2 -1
  27. package/dist/handler/messages/handleProjectMapNodeDelete.js +2 -1
  28. package/dist/handler/messages/handleProjectMapNodeInsert.js +2 -1
  29. package/dist/handler/messages/handleProjectMapNodeUpdate.js +2 -1
  30. package/dist/handler/messages/handleRedirectDelete.js +2 -1
  31. package/dist/handler/messages/handleRedirectInsert.js +2 -1
  32. package/dist/handler/messages/handleRedirectUpdate.js +2 -1
  33. package/dist/index.d.ts +5 -2
  34. package/dist/index.js +6 -1
  35. package/dist/utils/comp.js +30 -12
  36. package/dist/utils/draft.js +5 -8
  37. package/package.json +18 -16
  38. package/dist/config/uniform.server.config.d.ts +0 -3
  39. package/dist/config/uniform.server.config.js +0 -3
@@ -0,0 +1,2 @@
1
+ import { ContextState } from '@uniformdev/context';
2
+ export declare const updateContextAction: (options: Partial<ContextState>) => Promise<void>;
@@ -0,0 +1,17 @@
1
+ 'use server';
2
+ import { UNIFORM_DEFAULT_COOKIE_NAME } from '@uniformdev/context';
3
+ import { cookies } from 'next/headers';
4
+ import { getUniformContext } from '../components/getUniformContext';
5
+ import { serializeCookie } from '../score';
6
+ export const updateContextAction = async (options) => {
7
+ var _a;
8
+ const context = await getUniformContext({
9
+ cookieValue: (_a = cookies().get(UNIFORM_DEFAULT_COOKIE_NAME)) === null || _a === void 0 ? void 0 : _a.value,
10
+ });
11
+ if (!context.storage.data.consent) {
12
+ return;
13
+ }
14
+ await context.update(options);
15
+ const scoreCookie = serializeCookie(context.storage.data);
16
+ cookies().set(UNIFORM_DEFAULT_COOKIE_NAME, scoreCookie);
17
+ };
@@ -1,4 +1,4 @@
1
- import { RouteClient } from '@uniformdev/canvas';
1
+ import { CANVAS_EDITOR_STATE, RouteClient } from '@uniformdev/canvas';
2
2
  import { isDevelopmentEnvironment } from '../utils/draft';
3
3
  import { buildPathTag } from '../utils/tag';
4
4
  export const getRouteClient = (options) => {
@@ -18,10 +18,13 @@ export const getRouteClient = (options) => {
18
18
  requestedUrl = new URL(req.url);
19
19
  }
20
20
  const tags = [];
21
+ let state;
21
22
  if (requestedUrl) {
22
23
  // this is here so this code breaks if parameters change here
23
24
  const pathKey = 'path';
25
+ const stateKey = 'state';
24
26
  const path = requestedUrl.searchParams.get(pathKey);
27
+ state = parseInt(requestedUrl.searchParams.get(stateKey) || '', 10);
25
28
  if (path) {
26
29
  // at this point, we do not know if this path is dynamic or not
27
30
  // so apply each segment as a tag so we can clear any segment, ie:
@@ -43,6 +46,10 @@ export const getRouteClient = (options) => {
43
46
  noCache = true;
44
47
  revalidate = undefined;
45
48
  }
49
+ const extraHeaders = {};
50
+ if (state === CANVAS_EDITOR_STATE) {
51
+ extraHeaders['x-bypass-cache'] = 'true';
52
+ }
46
53
  return fetch(req, {
47
54
  ...init,
48
55
  cache: noCache ? 'no-cache' : 'force-cache',
@@ -50,6 +57,10 @@ export const getRouteClient = (options) => {
50
57
  revalidate,
51
58
  tags: tags.length ? tags : undefined,
52
59
  },
60
+ headers: {
61
+ ...((init === null || init === void 0 ? void 0 : init.headers) || {}),
62
+ ...extraHeaders,
63
+ },
53
64
  });
54
65
  },
55
66
  });
@@ -1,2 +1,2 @@
1
1
  import { ComponentProps } from './UniformComponent';
2
- export declare function DefaultNotImplementedComponent(props: ComponentProps): JSX.Element | null;
2
+ export declare function DefaultNotImplementedComponent(props: ComponentProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,3 +1,3 @@
1
1
  export declare const GoogleTagManagerAnalytics: (props?: {
2
2
  measurementId?: string;
3
- }) => JSX.Element;
3
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -7,6 +7,9 @@ export type CompositionContext = Omit<RouteGetResponseComposition, 'compositionA
7
7
  searchParams: {
8
8
  [key: string]: string | undefined;
9
9
  } | undefined;
10
+ cookieValue: string | undefined;
11
+ isDraftMode: boolean;
12
+ isContextualEditing: boolean;
10
13
  };
11
14
  export type ComponentProps<TProps = unknown> = TProps & {
12
15
  component: ComponentInstance;
@@ -1,3 +1,4 @@
1
+ import { ContextState } from '@uniformdev/context';
1
2
  import { ReactNode } from 'react';
2
3
  export type SuspenseOptions = {
3
4
  mode: 'off';
@@ -25,11 +26,15 @@ export type UniformCompositionProps = {
25
26
  mode: 'off';
26
27
  } | {
27
28
  mode: 'fallback';
28
- fallback: React.ReactNode;
29
+ fallback: ReactNode;
29
30
  };
31
+ /**
32
+ * Update state that should be added to the call to update before composition evaluation
33
+ */
34
+ update?: Partial<ContextState>;
30
35
  /**
31
36
  * The children of the UniformComposition component.
32
37
  */
33
38
  children?: ReactNode;
34
39
  };
35
- export declare const UniformComposition: ({ suspense, ...props }: UniformCompositionProps) => JSX.Element;
40
+ export declare const UniformComposition: ({ suspense, ...props }: UniformCompositionProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,13 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { CANVAS_DRAFT_STATE, CANVAS_EDITOR_STATE, CANVAS_PUBLISHED_STATE } from '@uniformdev/canvas';
3
- import { cookies, headers } from 'next/headers';
4
- import { notFound, redirect } from 'next/navigation';
5
2
  import { Suspense } from 'react';
6
- import { getManifestFromApi } from '../client/manifestClient';
7
- import { isDevelopmentEnvironment, isDraftModeEnabled, isIncontextEditingEnabled, isOnVercelPreviewEnvironment, } from '../utils/draft';
8
- import { evaluateComposition } from './evaluateComposition';
9
- import { resolvePath } from './resolvePath';
10
- import { resolveRedirectHref, retrieveRoute } from './retrieveRoute';
3
+ import { isDraftModeEnabled, isIncontextEditingEnabled } from '../utils/draft';
4
+ import { resolveComposition } from './retrieveRoute';
11
5
  import { UniformComponent } from './UniformComponent';
12
6
  import { UniformProvider } from './UniformContext';
13
7
  import { UniformScript } from './UniformScript';
@@ -20,67 +14,21 @@ const ConditionalWrapper = ({ children, options }) => {
20
14
  }
21
15
  return _jsx(Suspense, { fallback: options.fallback, children: children });
22
16
  };
23
- const UniformCompositionInner = async ({ params, searchParams, children }) => {
24
- // prefetch manifest immediately
25
- void getManifestFromApi({
26
- searchParams,
27
- });
28
- const draftMode = isDraftModeEnabled({ searchParams });
29
- const previewEnvironment = isOnVercelPreviewEnvironment();
30
- const isDevelopment = isDevelopmentEnvironment();
31
- const isCanvasEditing = isIncontextEditingEnabled({
32
- searchParams,
33
- });
34
- // resolve the path from provided params
35
- const path = resolvePath({
17
+ const UniformCompositionInner = async ({ params, searchParams, update, children, }) => {
18
+ const { composition: evaluatedComposition, cookieValue, path, searchParams: evaluatedSearchParams, seenComponents, isCanvasEditing, ...rest } = await resolveComposition({
36
19
  params,
37
- });
38
- let state;
39
- if (isCanvasEditing) {
40
- state = CANVAS_EDITOR_STATE;
41
- }
42
- else {
43
- state = draftMode || previewEnvironment || isDevelopment ? CANVAS_DRAFT_STATE : CANVAS_PUBLISHED_STATE;
44
- }
45
- // resolve the route from the path
46
- const resolveResult = await retrieveRoute({
47
- path,
48
- state,
49
20
  searchParams,
50
- });
51
- // if the route is a redirect, redirect
52
- if (resolveResult.type === 'redirect') {
53
- const href = resolveRedirectHref(resolveResult, path);
54
- redirect(href);
55
- }
56
- // if the route is not found, return 404
57
- if (resolveResult.type === 'notFound') {
58
- notFound();
59
- }
60
- const { compositionApiResponse, ...rest } = resolveResult;
61
- // retrieve the manifest
62
- const manifest = await getManifestFromApi({
63
- searchParams,
64
- });
65
- // evaluate the composition
66
- const { cookieValue, composition: evaluatedComposition, seenComponents, } = await evaluateComposition({
67
- root: compositionApiResponse.composition,
68
- params,
69
- searchParams: searchParams !== null && searchParams !== void 0 ? searchParams : {},
70
- dynamicInputs: rest.dynamicInputs,
71
- manifest,
72
- headers: headers(),
73
- cookies: cookies()
74
- .getAll()
75
- .reduce((acc, cookie) => {
76
- acc[cookie.name] = cookie.value;
77
- return acc;
78
- }, {}),
21
+ update,
79
22
  });
80
23
  const context = {
81
24
  composition: evaluatedComposition,
82
25
  path,
83
26
  searchParams,
27
+ cookieValue,
28
+ isDraftMode: isDraftModeEnabled({ searchParams }),
29
+ isContextualEditing: isIncontextEditingEnabled({
30
+ searchParams,
31
+ }),
84
32
  ...rest,
85
33
  };
86
34
  return (_jsxs(UniformProvider, { cookieValue: cookieValue, seenComponents: seenComponents, children: [_jsx(UniformScript, { enabled: isCanvasEditing }), _jsx(UniformComponent, { data: evaluatedComposition, context: context }), Boolean(children) && children] }));
@@ -5,7 +5,4 @@ export type UniformContextProps = {
5
5
  seenComponents: SeenUniformComponent[] | undefined;
6
6
  };
7
7
  export declare const UniformContext: import("react").Context<UniformContextProps>;
8
- export declare const UniformProvider: ({ children, cookieValue, seenComponents, }: PropsWithChildren<{
9
- cookieValue: string | undefined;
10
- seenComponents: SeenUniformComponent[] | undefined;
11
- }>) => JSX.Element;
8
+ export declare const UniformProvider: ({ children, cookieValue, seenComponents, }: PropsWithChildren<UniformContextProps>) => import("react/jsx-runtime").JSX.Element;
@@ -7,4 +7,4 @@ export type UniformRichTextNodeProps = {
7
7
  /**
8
8
  * Render a single RichText node
9
9
  */
10
- export declare function UniformRichTextNode({ node, ...props }: UniformRichTextNodeProps): JSX.Element | null;
10
+ export declare function UniformRichTextNode({ node, ...props }: UniformRichTextNodeProps): import("react/jsx-runtime").JSX.Element | null;
@@ -1,3 +1,3 @@
1
1
  export declare const UniformScript: ({ enabled }: {
2
2
  enabled: boolean;
3
- }) => JSX.Element;
3
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -1,14 +1,6 @@
1
- /// <reference types="react" />
2
- import { ComponentInstance } from '@uniformdev/canvas';
1
+ import { type PureUniformTextProps } from '@uniformdev/canvas-react/core';
2
+ import { CompositionContext } from './UniformComponent';
3
3
  export type UniformTextProps = {
4
- /**
5
- * The name of the HTML tag to render.
6
- * @default "span"
7
- */
8
- as?: React.ElementType;
9
- /** The ID of the parameter. */
10
- parameterId: string;
11
- /** The component instance. */
12
- component: ComponentInstance;
13
- } & Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'>;
14
- export declare const UniformText: ({ as: Tag, parameterId, component, ...rest }: UniformTextProps) => JSX.Element | null;
4
+ context: CompositionContext;
5
+ } & Omit<PureUniformTextProps, 'skipCustomRendering' | 'isContextualEditing'>;
6
+ export declare const UniformText: ({ context, ...rest }: UniformTextProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,9 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export const UniformText = ({ as: Tag = 'span', parameterId, component, ...rest }) => {
3
- var _a;
4
- const parameter = (_a = component === null || component === void 0 ? void 0 : component.parameters) === null || _a === void 0 ? void 0 : _a[parameterId];
5
- if (!parameter) {
6
- return null;
7
- }
8
- return _jsx(Tag, { ...rest, children: parameter.value });
2
+ import { PureUniformText } from '@uniformdev/canvas-react/core';
3
+ export const UniformText = ({ context, ...rest }) => {
4
+ return (_jsx(PureUniformText, { ...rest, isContextualEditing: context.isContextualEditing, skipCustomRendering: context.isContextualEditing }));
9
5
  };
@@ -1,7 +1,17 @@
1
1
  import { CANVAS_LOCALE_TAG_PARAM, CANVAS_LOCALIZATION_SLOT, CANVAS_LOCALIZATION_TYPE, } from '@uniformdev/canvas';
2
+ import { Context } from '@uniformdev/context';
2
3
  import { evaluateComposition } from '../evaluateComposition';
4
+ jest.mock('../getUniformContext', () => ({
5
+ getUniformContext: () => {
6
+ return new Context({
7
+ manifest: {
8
+ project: {},
9
+ },
10
+ });
11
+ },
12
+ }));
3
13
  describe('evaluateComposition', () => {
4
- it('should localize a compoisition when dynmaic inputs include locale token', async () => {
14
+ it('should localize a composition when dynmaic inputs include locale token', async () => {
5
15
  var _a, _b;
6
16
  const root = {
7
17
  _id: 'root',
@@ -61,9 +71,7 @@ describe('evaluateComposition', () => {
61
71
  localeDynamicInputs: ['lang'],
62
72
  },
63
73
  },
64
- manifest: {
65
- project: {},
66
- },
74
+ update: undefined,
67
75
  });
68
76
  const localizedHero = (_a = root.slots) === null || _a === void 0 ? void 0 : _a['content'][0];
69
77
  expect(localizedHero).toBeDefined();
@@ -1,8 +1,8 @@
1
1
  import { RootComponentInstance, RouteGetResponseComposition } from '@uniformdev/canvas';
2
- import { ManifestV2 } from '@uniformdev/context';
2
+ import { ContextState } from '@uniformdev/context';
3
3
  import { UniformServerConfig } from '../config';
4
4
  import { SeenUniformComponent } from '../models';
5
- export declare const evaluateComposition: ({ root, params, searchParams, dynamicInputs, manifest, headers, cookies, config, }: {
5
+ export declare const evaluateComposition: ({ root, params, searchParams, dynamicInputs, headers, cookies, update, config, }: {
6
6
  root: RootComponentInstance;
7
7
  params: {
8
8
  slug: string | string[];
@@ -11,9 +11,9 @@ export declare const evaluateComposition: ({ root, params, searchParams, dynamic
11
11
  [key: string]: string | undefined;
12
12
  };
13
13
  dynamicInputs: RouteGetResponseComposition['dynamicInputs'];
14
- manifest: ManifestV2;
15
14
  headers: Headers;
16
15
  cookies: Record<string, string>;
16
+ update: Partial<ContextState> | undefined;
17
17
  config?: UniformServerConfig | undefined;
18
18
  }) => Promise<{
19
19
  composition: RootComponentInstance;
@@ -1,23 +1,20 @@
1
- import { CANVAS_PERSONALIZATION_PARAM, CANVAS_PERSONALIZE_TYPE, CANVAS_TEST_TYPE, localize, mapSlotToPersonalizedVariations, mapSlotToTestVariations, walkComponentTree, } from '@uniformdev/canvas';
2
- import { Context, CookieTransitionDataStore, UNIFORM_DEFAULT_COOKIE_NAME, } from '@uniformdev/context';
3
- import serverConfig from '../config/uniform.server.config';
1
+ import { CANVAS_PERSONALIZATION_PARAM, CANVAS_PERSONALIZE_TYPE, CANVAS_TEST_TYPE, localize, mapSlotToPersonalizedVariations, mapSlotToTestVariations, walkNodeTree, } from '@uniformdev/canvas';
2
+ import { UNIFORM_DEFAULT_COOKIE_NAME } from '@uniformdev/context';
3
+ import { getServerConfig } from '../config/helpers';
4
4
  import { serializeCookie } from '../score';
5
+ import { isIncontextEditingEnabled } from '../utils/draft';
5
6
  import { getBaseUrl } from '../utils/url';
6
7
  import { getEnrichmentTags } from './getEnrichmentTags';
8
+ import { getUniformContext } from './getUniformContext';
7
9
  import { resolvePath } from './resolvePath';
8
- export const evaluateComposition = async ({ root, params, searchParams, dynamicInputs, manifest, headers, cookies, config = serverConfig, }) => {
9
- // retrieve the score from the cookie, if any
10
- const score = cookies[UNIFORM_DEFAULT_COOKIE_NAME];
10
+ export const evaluateComposition = async ({ root, params, searchParams, dynamicInputs, headers, cookies, update, config = getServerConfig(), }) => {
11
11
  // resolve the path from route params
12
12
  const path = resolvePath({
13
13
  params,
14
14
  });
15
- // create a context
16
- const context = new Context({
17
- manifest,
18
- transitionStore: new CookieTransitionDataStore({
19
- serverCookieValue: score,
20
- }),
15
+ const context = await getUniformContext({
16
+ searchParams,
17
+ cookieValue: cookies[UNIFORM_DEFAULT_COOKIE_NAME] || undefined,
21
18
  });
22
19
  // generate the current URL for the request
23
20
  const url = new URL(`${getBaseUrl()}${path}`);
@@ -27,15 +24,21 @@ export const evaluateComposition = async ({ root, params, searchParams, dynamicI
27
24
  }
28
25
  }
29
26
  const missingQuirkValue = 'unknown';
27
+ const { cookies: updateCookies, quirks: updateQuirks, ...restOfUpdate } = update || {};
30
28
  // update context to update scores
31
29
  await context.update({
32
- cookies,
30
+ cookies: {
31
+ ...cookies,
32
+ ...(updateCookies || {}),
33
+ },
33
34
  url,
34
35
  quirks: {
35
36
  'vc-country': headers.get('x-vercel-ip-country') || missingQuirkValue,
36
37
  'vc-region': headers.get('x-vercel-ip-country-region') || missingQuirkValue,
37
38
  'vc-city': headers.get('x-vercel-ip-city') || missingQuirkValue,
39
+ ...(updateQuirks || {}),
38
40
  },
41
+ ...restOfUpdate,
39
42
  });
40
43
  const composition = root;
41
44
  const resolvedLocaleKey = Object.keys(dynamicInputs || {}).find((key) => {
@@ -53,8 +56,13 @@ export const evaluateComposition = async ({ root, params, searchParams, dynamicI
53
56
  }
54
57
  const enrichmentTags = [];
55
58
  const seenComponents = [];
56
- walkComponentTree(composition, (component, _ancestors, actions) => {
59
+ walkNodeTree(composition, ({ type, node: component, actions }) => {
57
60
  var _a, _b, _c, _d, _e, _f;
61
+ if (type !== 'component') {
62
+ // we ignore blocks for now
63
+ actions.stopProcessingDescendants();
64
+ return;
65
+ }
58
66
  let replacementComponents;
59
67
  // evaluate personalization components
60
68
  if (component.type === CANVAS_PERSONALIZE_TYPE) {
@@ -116,12 +124,12 @@ export const evaluateComposition = async ({ root, params, searchParams, dynamicI
116
124
  if (typeof replacementComponents !== 'undefined') {
117
125
  // if no variants were selected, just remove the current component. no matches.
118
126
  if (replacementComponents.length === 0) {
119
- actions.removeComponent();
127
+ actions.remove();
120
128
  }
121
129
  else {
122
130
  const [first, ...rest] = replacementComponents;
123
131
  // replace the first component
124
- actions.replaceComponent(first);
132
+ actions.replace(first);
125
133
  // if there are other components, insert them after the first
126
134
  if (rest.length) {
127
135
  actions.insertAfter(rest);
@@ -137,6 +145,29 @@ export const evaluateComposition = async ({ root, params, searchParams, dynamicI
137
145
  }
138
146
  }
139
147
  });
148
+ // when we post compositions to CANVAS_EDITOR_STATE, we have to remove all
149
+ // contextual editing objects that have been attached to parameters in order
150
+ // to pass API validation. walk the composition and add them back in, assume
151
+ // everything is editable.
152
+ if (isIncontextEditingEnabled({ searchParams })) {
153
+ walkNodeTree(composition, ({ node: component, actions, type }) => {
154
+ if (type !== 'component') {
155
+ actions.stopProcessingDescendants();
156
+ return;
157
+ }
158
+ if (component.parameters) {
159
+ const params = Object.keys(component.parameters);
160
+ params.forEach((key) => {
161
+ const param = component.parameters[key];
162
+ if (param.type === 'text' && typeof param._contextualEditing === 'undefined') {
163
+ param._contextualEditing = {
164
+ isEditable: true,
165
+ };
166
+ }
167
+ });
168
+ }
169
+ });
170
+ }
140
171
  // if we've seen any enrichment tags, update the context with them
141
172
  if (enrichmentTags.length) {
142
173
  await context.update({
@@ -0,0 +1,6 @@
1
+ import { Context } from '@uniformdev/context';
2
+ import { UniformCompositionProps } from './UniformComposition';
3
+ export declare const getUniformContext: ({ searchParams, cookieValue, }: {
4
+ searchParams?: UniformCompositionProps['searchParams'];
5
+ cookieValue: string | undefined;
6
+ }) => Promise<Context>;
@@ -0,0 +1,17 @@
1
+ import { Context, CookieTransitionDataStore } from '@uniformdev/context';
2
+ import { getManifestFromApi } from '../client/manifestClient';
3
+ import { getServerConfig } from '../config/helpers';
4
+ export const getUniformContext = async ({ searchParams, cookieValue, }) => {
5
+ const manifest = await getManifestFromApi({
6
+ searchParams,
7
+ });
8
+ const config = getServerConfig();
9
+ const context = new Context({
10
+ manifest,
11
+ defaultConsent: config.defaultConsent,
12
+ transitionStore: new CookieTransitionDataStore({
13
+ serverCookieValue: cookieValue,
14
+ }),
15
+ });
16
+ return context;
17
+ };
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { CANVAS_LOCALE_TAG_PARAM, CANVAS_PERSONALIZE_SLOT, CANVAS_PERSONALIZE_TYPE, CANVAS_TEST_SLOT, CANVAS_TEST_TYPE, IN_CONTEXT_EDITOR_COMPONENT_START_ROLE, PLACEHOLDER_ID, } from '@uniformdev/canvas';
2
+ import { CANVAS_LOCALE_TAG_PARAM, CANVAS_PERSONALIZE_SLOT, CANVAS_PERSONALIZE_TYPE, CANVAS_TEST_SLOT, CANVAS_TEST_TYPE, IN_CONTEXT_EDITOR_COMPONENT_START_ROLE, isComponentPlaceholderId, } from '@uniformdev/canvas';
3
3
  import { componentStoreResolver } from '../register/componentStoreResolver';
4
+ import { isIncontextEditingEnabled } from '../utils/draft';
4
5
  import { convertComponentToProps } from './convertComponentToProps';
5
6
  import { UniformComponent } from './UniformComponent';
6
7
  export function renderComponent({ component, context, resolveSystem, key = 0, indexInSlot, slotName, parentComponent, slotChildrenCount, emptyPlaceholder, }) {
7
- var _a, _b, _c, _d, _e;
8
+ var _a, _b, _c, _d;
8
9
  const RenderComponent = componentStoreResolver(component);
9
10
  // custom handling for tests and personalizes
10
11
  if (component.type === CANVAS_TEST_TYPE) {
@@ -42,12 +43,10 @@ export function renderComponent({ component, context, resolveSystem, key = 0, in
42
43
  component,
43
44
  context,
44
45
  });
45
- const shouldRenderContextualEditingTags = Boolean(component._id);
46
- const isPlaceholder = component._id === PLACEHOLDER_ID;
47
- const isReadOnly = ((_a = component === null || component === void 0 ? void 0 : component._contextualEditing) === null || _a === void 0 ? void 0 : _a.isEditable)
48
- ? undefined
49
- : 'true';
50
- return (_jsx(UniformComponent, { data: component, context: context, children: _jsxs(_Fragment, { children: [!shouldRenderContextualEditingTags ? null : (_jsx("script", { "data-role": IN_CONTEXT_EDITOR_COMPONENT_START_ROLE, "data-parent-id": parentComponent === null || parentComponent === void 0 ? void 0 : parentComponent._id, "data-parent-type": parentComponent === null || parentComponent === void 0 ? void 0 : parentComponent.type, "data-component-id": component._id, "data-slot-name": slotName !== null && slotName !== void 0 ? slotName : '', "data-component-index": indexInSlot !== null && indexInSlot !== void 0 ? indexInSlot : '', "data-total-components": slotChildrenCount !== null && slotChildrenCount !== void 0 ? slotChildrenCount : '', "data-component-name": component.type, "data-is-placeholder": isPlaceholder ? 'true' : undefined, "data-is-localized": ((_b = component.parameters) === null || _b === void 0 ? void 0 : _b[CANVAS_LOCALE_TAG_PARAM]) ? 'true' : undefined, "data-component-title": (_e = (_d = (_c = component.parameters) === null || _c === void 0 ? void 0 : _c.title) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : '', "data-is-readonly": isReadOnly }, key)), isPlaceholder && emptyPlaceholder !== undefined ? (emptyPlaceholder) : (_jsx(RenderComponent, { ...props })), !shouldRenderContextualEditingTags ? null : _jsx("script", { "data-role": "component-end" })] }) }, key));
46
+ const shouldRenderContextualEditingTags = Boolean(component._id) && isIncontextEditingEnabled(context);
47
+ const isPlaceholder = isComponentPlaceholderId(component._id);
48
+ const isReadOnly = false;
49
+ return (_jsx(UniformComponent, { data: component, context: context, children: _jsxs(_Fragment, { children: [!shouldRenderContextualEditingTags ? null : (_jsx("script", { "data-role": IN_CONTEXT_EDITOR_COMPONENT_START_ROLE, "data-parent-id": parentComponent === null || parentComponent === void 0 ? void 0 : parentComponent._id, "data-parent-type": parentComponent === null || parentComponent === void 0 ? void 0 : parentComponent.type, "data-component-id": component._id, "data-slot-name": slotName !== null && slotName !== void 0 ? slotName : '', "data-component-index": indexInSlot !== null && indexInSlot !== void 0 ? indexInSlot : '', "data-total-components": slotChildrenCount !== null && slotChildrenCount !== void 0 ? slotChildrenCount : '', "data-component-name": component.type, "data-is-placeholder": isPlaceholder ? 'true' : undefined, "data-is-localized": ((_a = component.parameters) === null || _a === void 0 ? void 0 : _a[CANVAS_LOCALE_TAG_PARAM]) ? 'true' : undefined, "data-component-title": (_d = (_c = (_b = component.parameters) === null || _b === void 0 ? void 0 : _b.title) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : '', "data-is-readonly": isReadOnly }, key)), isPlaceholder && emptyPlaceholder !== undefined ? (emptyPlaceholder) : (_jsx(RenderComponent, { ...props })), !shouldRenderContextualEditingTags ? null : _jsx("script", { "data-role": "component-end" })] }) }, key));
51
50
  }
52
51
  return null;
53
52
  }
@@ -1,4 +1,5 @@
1
1
  import { ResolvedRouteGetResponse, RouteGetResponseRedirect } from '@uniformdev/canvas';
2
+ import { UniformCompositionProps } from './UniformComposition';
2
3
  export type ResolveRouteOptions = {
3
4
  path: string;
4
5
  state?: number;
@@ -6,5 +7,135 @@ export type ResolveRouteOptions = {
6
7
  [key: string]: string | undefined;
7
8
  } | undefined;
8
9
  };
10
+ export declare const resolveComposition: ({ searchParams, params, update, }: Pick<UniformCompositionProps, 'searchParams' | 'params' | 'update'>) => Promise<{
11
+ type: "composition";
12
+ matchedRoute: string;
13
+ dynamicInputs?: {
14
+ [key: string]: string;
15
+ } | undefined;
16
+ composition: {
17
+ type: string;
18
+ parameters?: {
19
+ [key: string]: {
20
+ value: unknown;
21
+ type: string;
22
+ connectedData?: {
23
+ pointer: string;
24
+ syntax: "jptr";
25
+ } | undefined;
26
+ };
27
+ } | undefined;
28
+ variant?: string | undefined;
29
+ projectMapNodes?: {
30
+ id: string;
31
+ path: string;
32
+ projectMapId: string;
33
+ }[] | undefined;
34
+ slots?: {
35
+ [key: string]: {
36
+ type: string;
37
+ parameters?: {
38
+ [key: string]: {
39
+ value: unknown;
40
+ type: string;
41
+ connectedData?: {
42
+ pointer: string;
43
+ syntax: "jptr";
44
+ } | undefined;
45
+ };
46
+ } | undefined;
47
+ variant?: string | undefined;
48
+ slots?: {
49
+ [key: string]: any[];
50
+ } | undefined;
51
+ _id?: string | undefined;
52
+ _pattern?: string | undefined;
53
+ _dataResources?: {
54
+ [key: string]: {
55
+ type: string;
56
+ isPatternParameter?: boolean | undefined;
57
+ ignorePatternParameterDefault?: boolean | undefined;
58
+ variables?: {
59
+ [key: string]: string;
60
+ } | undefined;
61
+ };
62
+ } | undefined;
63
+ _patternDataResources?: {
64
+ [key: string]: {
65
+ type: string;
66
+ isPatternParameter?: boolean | undefined;
67
+ ignorePatternParameterDefault?: boolean | undefined;
68
+ variables?: {
69
+ [key: string]: string;
70
+ } | undefined;
71
+ };
72
+ } | undefined;
73
+ _patternError?: "NOTFOUND" | "CYCLIC" | undefined;
74
+ _overrides?: {
75
+ [key: string]: {
76
+ parameters?: {
77
+ [key: string]: {
78
+ value: unknown;
79
+ type: string;
80
+ connectedData?: {
81
+ pointer: string;
82
+ syntax: "jptr";
83
+ } | undefined;
84
+ };
85
+ } | undefined;
86
+ variant?: string | undefined;
87
+ };
88
+ } | undefined;
89
+ _overridability?: {
90
+ parameters?: {
91
+ [key: string]: "yes" | "no";
92
+ } | undefined;
93
+ variants?: boolean | undefined;
94
+ } | undefined;
95
+ }[];
96
+ } | undefined;
97
+ _id: string;
98
+ _slug?: string | null | undefined;
99
+ _name: string;
100
+ _dataResources?: {
101
+ [key: string]: {
102
+ type: string;
103
+ isPatternParameter?: boolean | undefined;
104
+ ignorePatternParameterDefault?: boolean | undefined;
105
+ variables?: {
106
+ [key: string]: string;
107
+ } | undefined;
108
+ };
109
+ } | undefined;
110
+ _overrides?: {
111
+ [key: string]: {
112
+ parameters?: {
113
+ [key: string]: {
114
+ value: unknown;
115
+ type: string;
116
+ connectedData?: {
117
+ pointer: string;
118
+ syntax: "jptr";
119
+ } | undefined;
120
+ };
121
+ } | undefined;
122
+ variant?: string | undefined;
123
+ };
124
+ } | undefined;
125
+ _overridability?: {
126
+ parameters?: {
127
+ [key: string]: "yes" | "no";
128
+ } | undefined;
129
+ variants?: boolean | undefined;
130
+ } | undefined;
131
+ };
132
+ cookieValue: string | undefined;
133
+ path: string;
134
+ searchParams: {
135
+ [key: string]: string | undefined;
136
+ } | undefined;
137
+ isCanvasEditing: boolean;
138
+ seenComponents: import("../models").SeenUniformComponent[];
139
+ }>;
9
140
  export declare const retrieveRoute: (data: ResolveRouteOptions) => Promise<ResolvedRouteGetResponse>;
10
141
  export declare const resolveRedirectHref: (resolveResult: RouteGetResponseRedirect, path: string) => string;
@@ -1,12 +1,79 @@
1
- import { CANVAS_DRAFT_STATE, CANVAS_EDITOR_STATE, } from '@uniformdev/canvas';
1
+ import { CANVAS_DRAFT_STATE, CANVAS_EDITOR_STATE, CANVAS_PUBLISHED_STATE, } from '@uniformdev/canvas';
2
2
  import { RedirectClient } from '@uniformdev/redirect';
3
3
  import { get } from '@vercel/edge-config';
4
+ import { cookies, headers } from 'next/headers';
5
+ import { notFound, redirect } from 'next/navigation';
6
+ import { getManifestFromApi } from '../client/manifestClient';
4
7
  import { getRouteClient } from '../client/routeClient';
5
- import { getRouteRevalidateInterval } from '../config/helpers';
6
- import config from '../config/uniform.server.config';
7
- import { isOnVercelPreviewEnvironment } from '../utils/draft';
8
+ import { getRouteRevalidateInterval, getServerConfig } from '../config/helpers';
9
+ import { isDevelopmentEnvironment, isDraftModeEnabled, isIncontextEditingEnabled, isOnVercelPreviewEnvironment, } from '../utils/draft';
8
10
  import { buildPathTag } from '../utils/tag';
9
11
  import { getBaseUrl } from '../utils/url';
12
+ import { evaluateComposition } from './evaluateComposition';
13
+ import { resolvePath } from './resolvePath';
14
+ export const resolveComposition = async ({ searchParams, params, update, }) => {
15
+ // prefetch manifest immediately
16
+ void getManifestFromApi({
17
+ searchParams,
18
+ });
19
+ const draftMode = isDraftModeEnabled({ searchParams });
20
+ const previewEnvironment = isOnVercelPreviewEnvironment();
21
+ const isDevelopment = isDevelopmentEnvironment();
22
+ const isCanvasEditing = isIncontextEditingEnabled({
23
+ searchParams,
24
+ });
25
+ // resolve the path from provided params
26
+ const path = resolvePath({
27
+ params,
28
+ });
29
+ let state;
30
+ if (isCanvasEditing) {
31
+ state = CANVAS_EDITOR_STATE;
32
+ }
33
+ else {
34
+ state = draftMode || previewEnvironment || isDevelopment ? CANVAS_DRAFT_STATE : CANVAS_PUBLISHED_STATE;
35
+ }
36
+ // resolve the route from the path
37
+ const resolveResult = await retrieveRoute({
38
+ path,
39
+ state,
40
+ searchParams,
41
+ });
42
+ // if the route is a redirect, redirect
43
+ if (resolveResult.type === 'redirect') {
44
+ const href = resolveRedirectHref(resolveResult, path);
45
+ redirect(href);
46
+ }
47
+ // if the route is not found, return 404
48
+ if (resolveResult.type === 'notFound') {
49
+ notFound();
50
+ }
51
+ const { compositionApiResponse, ...rest } = resolveResult;
52
+ // evaluate the composition
53
+ const { cookieValue, composition: evaluatedComposition, seenComponents, } = await evaluateComposition({
54
+ root: compositionApiResponse.composition,
55
+ params,
56
+ searchParams: searchParams !== null && searchParams !== void 0 ? searchParams : {},
57
+ dynamicInputs: rest.dynamicInputs,
58
+ headers: headers(),
59
+ cookies: cookies()
60
+ .getAll()
61
+ .reduce((acc, cookie) => {
62
+ acc[cookie.name] = cookie.value;
63
+ return acc;
64
+ }, {}),
65
+ update,
66
+ });
67
+ return {
68
+ composition: evaluatedComposition,
69
+ cookieValue,
70
+ path,
71
+ searchParams,
72
+ isCanvasEditing,
73
+ seenComponents,
74
+ ...rest,
75
+ };
76
+ };
10
77
  export const retrieveRoute = async (data) => {
11
78
  void resolveRouteByEdgeConfig(data);
12
79
  void resolveRouteByRouteApi(data);
@@ -43,6 +110,7 @@ export const resolveRedirectHref = (resolveResult, path) => {
43
110
  };
44
111
  const resolveRouteByEdgeConfig = async (data) => {
45
112
  var _a;
113
+ const config = getServerConfig();
46
114
  if (!((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeRedirects) || !process.env.EDGE_CONFIG) {
47
115
  return undefined;
48
116
  }
@@ -62,6 +130,7 @@ const resolveRouteByEdgeConfig = async (data) => {
62
130
  return edgeConfig;
63
131
  };
64
132
  const resolveRouteByRouteApi = async (data) => {
133
+ var _a;
65
134
  const routeClient = getRouteClient({
66
135
  revalidate: getRouteRevalidateInterval({
67
136
  searchParams: data.searchParams,
@@ -71,7 +140,7 @@ const resolveRouteByRouteApi = async (data) => {
71
140
  path: data.path,
72
141
  state: data.state,
73
142
  withComponentIDs: data.state === CANVAS_DRAFT_STATE || data.state === CANVAS_EDITOR_STATE,
74
- withContentSourceMap: isOnVercelPreviewEnvironment(),
143
+ withContentSourceMap: isOnVercelPreviewEnvironment() && ((_a = getServerConfig().experimental) === null || _a === void 0 ? void 0 : _a.vercelVisualEditing),
75
144
  });
76
145
  return routeResult;
77
146
  };
@@ -1,3 +1,4 @@
1
+ import { UniformServerConfig } from './models';
1
2
  export declare const getCanvasRevalidateInterval: (options: {
2
3
  searchParams: {
3
4
  [key: string]: string | undefined;
@@ -13,3 +14,4 @@ export declare const getRouteRevalidateInterval: (options: {
13
14
  [key: string]: string | undefined;
14
15
  } | undefined;
15
16
  }) => number | undefined;
17
+ export declare const getServerConfig: () => UniformServerConfig;
@@ -1,20 +1,34 @@
1
1
  import { isDraftModeEnabled, isOnVercelPreviewEnvironment } from '../utils/draft';
2
- import config from './uniform.server.config';
3
2
  export const getCanvasRevalidateInterval = (options) => {
4
3
  if (isDraftModeEnabled({ searchParams: options.searchParams }) || isOnVercelPreviewEnvironment()) {
5
4
  return -1;
6
5
  }
6
+ const config = getServerConfig();
7
7
  return 'canvasRevalidateInterval' in config ? config.canvasRevalidateInterval : undefined;
8
8
  };
9
9
  export const getManifestRevalidateInterval = (options) => {
10
10
  if (isDraftModeEnabled({ searchParams: options.searchParams }) || isOnVercelPreviewEnvironment()) {
11
11
  return -1;
12
12
  }
13
+ const config = getServerConfig();
13
14
  return 'manifestRevalidateInterval' in config ? config.manifestRevalidateInterval : undefined;
14
15
  };
15
16
  export const getRouteRevalidateInterval = (options) => {
16
17
  if (isDraftModeEnabled({ searchParams: options.searchParams }) || isOnVercelPreviewEnvironment()) {
17
18
  return -1;
18
19
  }
20
+ const config = getServerConfig();
19
21
  return 'routeRevalidateInterval' in config ? config.routeRevalidateInterval : undefined;
20
22
  };
23
+ export const getServerConfig = () => {
24
+ let serverConfig;
25
+ try {
26
+ serverConfig = require('uniform.server.config.js');
27
+ }
28
+ catch (e) {
29
+ serverConfig = {
30
+ defaultConsent: false,
31
+ };
32
+ }
33
+ return serverConfig;
34
+ };
@@ -43,5 +43,9 @@ export type UniformServerConfig = {
43
43
  * Dynamic tokens names that should be used for localization.
44
44
  */
45
45
  localeDynamicInputs?: string[];
46
+ /**
47
+ * Enables visual editing mode.
48
+ */
49
+ vercelVisualEditing?: boolean;
46
50
  };
47
51
  };
package/dist/config.js CHANGED
@@ -1,14 +1,11 @@
1
- const { existsSync, lstatSync, readFileSync, writeFileSync, readlinkSync } = require('fs');
2
- const { join, dirname, isAbsolute } = require('path');
3
- const getPackagePath = () => join(process.cwd(), 'node_modules', '@uniformdev/canvas-next-rsc');
4
- const getSymlinkAbsolutePath = (symlink) => join(dirname(getPackagePath()), symlink);
5
- const getConfigPath = (type) => {
6
- const configFilePath = join(process.cwd(), `uniform.${type}.config.js`);
1
+ const { existsSync } = require('fs');
2
+ const { join } = require('path');
3
+ const getConfigPath = () => {
4
+ const configFilePath = join(process.cwd(), `uniform.server.config.js`);
7
5
  if (!existsSync(configFilePath)) {
8
6
  return undefined;
9
7
  }
10
- const content = readFileSync(configFilePath, 'utf8');
11
- return content;
8
+ return configFilePath;
12
9
  };
13
10
  module.exports.withUniformConfig = (nextConfig) => ({
14
11
  ...nextConfig,
@@ -17,23 +14,15 @@ module.exports.withUniformConfig = (nextConfig) => ({
17
14
  nextConfig.webpack(config, context);
18
15
  }
19
16
  if (context.isServer) {
20
- const uniformConfig = getConfigPath('server');
21
- if (uniformConfig) {
22
- const packagePath = getPackagePath();
23
- const stat = lstatSync(packagePath);
24
- const jsFilePath = 'dist/config/uniform.server.config.js';
25
- if (stat === null || stat === void 0 ? void 0 : stat.isSymbolicLink()) {
26
- const symlink = readlinkSync(packagePath);
27
- if (symlink) {
28
- const absolute = join(!isAbsolute(symlink) ? getSymlinkAbsolutePath(symlink) : symlink, jsFilePath);
29
- // eslint-disable-next-line no-console
30
- console.log(`Writing Uniform config to ${absolute}`);
31
- writeFileSync(absolute, uniformConfig, 'utf8');
32
- }
33
- }
34
- else {
35
- writeFileSync(join(packagePath, jsFilePath), uniformConfig, 'utf8');
36
- }
17
+ const uniformConfigPath = getConfigPath();
18
+ if (uniformConfigPath) {
19
+ /* eslint-disable-next-line no-console */
20
+ console.log('Using Uniform config from', uniformConfigPath);
21
+ config.module.rules.push({
22
+ test: /uniform\.server\.config\.js$/,
23
+ include: uniformConfigPath,
24
+ use: context.defaultLoaders.babel,
25
+ });
37
26
  }
38
27
  }
39
28
  return config;
@@ -2,7 +2,7 @@ import { parseConnectionString } from '@vercel/edge-config';
2
2
  import { Webhook } from 'svix';
3
3
  import { getProjectMapClient } from '../client/projectMapClient';
4
4
  import { getRouteClient } from '../client/routeClient';
5
- import config from '../config/uniform.server.config';
5
+ import { getServerConfig } from '../config/helpers';
6
6
  import { buildCompositionTag, buildPathTag } from '../utils/tag';
7
7
  export const isSvixMessage = async (request) => {
8
8
  const requiredHeaders = ['svix-id', 'svix-timestamp', 'svix-signature'];
@@ -100,6 +100,7 @@ export const processEdgeConfigChange = async ({ source_url }) => {
100
100
  console.warn('UNIFORM_VERCEL_EDGE_CONFIG_TOKEN is not set, skipping edge redirect upsert');
101
101
  return;
102
102
  }
103
+ const config = getServerConfig();
103
104
  const routeClient = getRouteClient({
104
105
  revalidate: -1,
105
106
  });
@@ -1,5 +1,5 @@
1
1
  import { ProjectMapNodeDeleteDefinition } from '@uniformdev/webhooks';
2
- import config from '../../config/uniform.server.config';
2
+ import { getServerConfig } from '../../config/helpers';
3
3
  import { buildProjectMapNodePaths, processEdgeConfigChange } from '../helpers';
4
4
  export const handleProjectMapNodeDelete = async (body) => {
5
5
  var _a;
@@ -9,6 +9,7 @@ export const handleProjectMapNodeDelete = async (body) => {
9
9
  }
10
10
  const tags = [];
11
11
  tags.push(...buildProjectMapNodePaths(parsed.data.path));
12
+ const config = getServerConfig();
12
13
  if ((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeCompositions) {
13
14
  await processEdgeConfigChange({
14
15
  source_url: parsed.data.path,
@@ -1,5 +1,5 @@
1
1
  import { ProjectMapNodeInsertDefinition } from '@uniformdev/webhooks';
2
- import config from '../../config/uniform.server.config';
2
+ import { getServerConfig } from '../../config/helpers';
3
3
  import { buildProjectMapNodePaths, processEdgeConfigChange } from '../helpers';
4
4
  export const handleProjectMapNodeInsert = async (body) => {
5
5
  var _a;
@@ -9,6 +9,7 @@ export const handleProjectMapNodeInsert = async (body) => {
9
9
  }
10
10
  const tags = [];
11
11
  tags.push(...buildProjectMapNodePaths(parsed.data.path));
12
+ const config = getServerConfig();
12
13
  if ((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeCompositions) {
13
14
  await processEdgeConfigChange({
14
15
  source_url: parsed.data.path,
@@ -1,5 +1,5 @@
1
1
  import { ProjectMapNodeUpdateDefinition } from '@uniformdev/webhooks';
2
- import config from '../../config/uniform.server.config';
2
+ import { getServerConfig } from '../../config/helpers';
3
3
  import { buildProjectMapNodePaths, processEdgeConfigChange } from '../helpers';
4
4
  export const handleProjectMapNodeUpdate = async (body) => {
5
5
  var _a;
@@ -10,6 +10,7 @@ export const handleProjectMapNodeUpdate = async (body) => {
10
10
  const tags = [];
11
11
  tags.push(...buildProjectMapNodePaths(parsed.data.path));
12
12
  tags.push(...buildProjectMapNodePaths(parsed.data.previous_path));
13
+ const config = getServerConfig();
13
14
  if ((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeCompositions) {
14
15
  await processEdgeConfigChange({
15
16
  source_url: parsed.data.path,
@@ -1,5 +1,5 @@
1
1
  import { RedirectDeleteDefinition } from '@uniformdev/webhooks';
2
- import config from '../../config/uniform.server.config';
2
+ import { getServerConfig } from '../../config/helpers';
3
3
  import { processEdgeConfigChange, processRedirectChange } from '../helpers';
4
4
  export const handleRedirectDelete = async (body) => {
5
5
  var _a;
@@ -7,6 +7,7 @@ export const handleRedirectDelete = async (body) => {
7
7
  if (!parsed.success) {
8
8
  return undefined;
9
9
  }
10
+ const config = getServerConfig();
10
11
  if ((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeRedirects) {
11
12
  await processEdgeConfigChange(parsed.data);
12
13
  }
@@ -1,5 +1,5 @@
1
1
  import { RedirectInsertDefinition } from '@uniformdev/webhooks';
2
- import config from '../../config/uniform.server.config';
2
+ import { getServerConfig } from '../../config/helpers';
3
3
  import { processEdgeConfigChange, processRedirectChange } from '../helpers';
4
4
  export const handleRedirectInsert = async (body) => {
5
5
  var _a;
@@ -7,6 +7,7 @@ export const handleRedirectInsert = async (body) => {
7
7
  if (!parsed.success) {
8
8
  return undefined;
9
9
  }
10
+ const config = getServerConfig();
10
11
  if ((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeRedirects) {
11
12
  await processEdgeConfigChange(parsed.data);
12
13
  }
@@ -1,5 +1,5 @@
1
1
  import { RedirectUpdateDefinition } from '@uniformdev/webhooks';
2
- import config from '../../config/uniform.server.config';
2
+ import { getServerConfig } from '../../config/helpers';
3
3
  import { processEdgeConfigChange, processRedirectChange } from '../helpers';
4
4
  export const handleRedirectUpdate = async (body) => {
5
5
  var _a;
@@ -7,6 +7,7 @@ export const handleRedirectUpdate = async (body) => {
7
7
  if (!parsed.success) {
8
8
  return undefined;
9
9
  }
10
+ const config = getServerConfig();
10
11
  if ((_a = config.experimental) === null || _a === void 0 ? void 0 : _a.edgeRedirects) {
11
12
  await processEdgeConfigChange(parsed.data);
12
13
  }
package/dist/index.d.ts CHANGED
@@ -9,12 +9,15 @@ export { useToggleConsent } from './hooks/useToggleConsent';
9
9
  export { useUniformContext } from './hooks/useUniformContext';
10
10
  export { componentStore } from './register/componentStore';
11
11
  export { registerUniformComponent } from './register/registerUniformComponent';
12
+ export { getUniformContext } from './components/getUniformContext';
12
13
  export { getCanvasClient } from './client/canvasClient';
13
14
  export { getManifestClient } from './client/manifestClient';
14
15
  export { getProjectMapClient } from './client/projectMapClient';
15
16
  export { getRouteClient } from './client/routeClient';
16
- export declare const UniformComposition: (props: Omit<BaseUniformCompositionProps, 'suspense' | 'children'>) => JSX.Element;
17
- export declare const UniformCompositionCustom: (props: BaseUniformCompositionProps) => JSX.Element;
17
+ export { resolveComposition } from './components/retrieveRoute';
18
+ export { updateContextAction } from './actions/updateContext';
19
+ export declare const UniformComposition: (props: Omit<BaseUniformCompositionProps, 'suspense' | 'children' | 'update'>) => import("react/jsx-runtime").JSX.Element;
20
+ export declare const UniformCompositionCustom: (props: BaseUniformCompositionProps) => import("react/jsx-runtime").JSX.Element;
18
21
  export { UniformRichText } from './components/UniformRichText';
19
22
  export { isDraftModeEnabled, isIncontextEditingEnabled, isOnVercelPreviewEnvironment } from './utils/draft';
20
23
  export { CANVAS_DRAFT_STATE, CANVAS_PUBLISHED_STATE, IN_CONTEXT_EDITOR_QUERY_STRING_PARAM, } from '@uniformdev/canvas';
package/dist/index.js CHANGED
@@ -12,12 +12,17 @@ export { useUniformContext } from './hooks/useUniformContext';
12
12
  // Component Registry
13
13
  export { componentStore } from './register/componentStore';
14
14
  export { registerUniformComponent } from './register/registerUniformComponent';
15
+ // Context
16
+ export { getUniformContext } from './components/getUniformContext';
15
17
  // Clients
16
18
  export { getCanvasClient } from './client/canvasClient';
17
19
  export { getManifestClient } from './client/manifestClient';
18
20
  export { getProjectMapClient } from './client/projectMapClient';
19
21
  export { getRouteClient } from './client/routeClient';
20
- export const UniformComposition = (props) => (_jsx(BaseUniformComposition, { ...props }));
22
+ export { resolveComposition } from './components/retrieveRoute';
23
+ // actions
24
+ export { updateContextAction } from './actions/updateContext';
25
+ export const UniformComposition = (props) => _jsx(BaseUniformComposition, { ...props });
21
26
  export const UniformCompositionCustom = (props) => (_jsx(BaseUniformComposition, { ...props }));
22
27
  export { UniformRichText } from './components/UniformRichText';
23
28
  export { isDraftModeEnabled, isIncontextEditingEnabled, isOnVercelPreviewEnvironment } from './utils/draft';
@@ -1,14 +1,25 @@
1
- import { walkComponentTree } from '@uniformdev/canvas';
1
+ import { walkNodeTree } from '@uniformdev/canvas';
2
2
  export const getAllComponents = (composition) => {
3
3
  const ids = {};
4
- walkComponentTree(composition, (component, ancestors) => {
5
- if (component._id) {
6
- const [self, parent] = ancestors;
7
- ids[component._id] = {
8
- parentId: parent === null || parent === void 0 ? void 0 : parent.component._id,
9
- slot: self === null || self === void 0 ? void 0 : self.parentSlot,
10
- slotIndex: self === null || self === void 0 ? void 0 : self.parentSlotIndex,
11
- component,
4
+ walkNodeTree(composition, ({ type, actions, node, ancestorsAndSelf }) => {
5
+ if (type !== 'component') {
6
+ // don't want blocks here
7
+ actions.stopProcessingDescendants();
8
+ return;
9
+ }
10
+ if (node._id) {
11
+ const [self, parent] = ancestorsAndSelf;
12
+ if (self.type === 'block') {
13
+ // just to make TS happy, we already know this is true due to the preceding type-prop check
14
+ return;
15
+ }
16
+ const slotIndex = self.type === 'root' ? undefined : self.parentSlotIndex;
17
+ const slot = self.type === 'root' ? undefined : self.parentSlot;
18
+ ids[node._id] = {
19
+ parentId: parent === null || parent === void 0 ? void 0 : parent.node._id,
20
+ slot,
21
+ slotIndex,
22
+ component: node,
12
23
  };
13
24
  }
14
25
  });
@@ -16,9 +27,16 @@ export const getAllComponents = (composition) => {
16
27
  };
17
28
  export const getComponent = (composition, id) => {
18
29
  let result;
19
- walkComponentTree(composition, (component) => {
20
- if (component._id === id) {
21
- result = component;
30
+ walkNodeTree(composition, ({ type, node, actions }) => {
31
+ // note: does not work on blocks because it didn't before - so leaving that for back compat
32
+ // no technical reason I know of why we can't let it find blocks by ID
33
+ if (type !== 'component') {
34
+ actions.stopProcessingDescendants();
35
+ return;
36
+ }
37
+ if (node._id === id) {
38
+ result = node;
39
+ actions.stopProcessingDescendants();
22
40
  }
23
41
  });
24
42
  return result;
@@ -6,16 +6,13 @@ export const isDraftModeEnabled = ({ searchParams, }) => {
6
6
  if (isDevelopmentEnvironment()) {
7
7
  return isIncontextEditingEnabled({ searchParams });
8
8
  }
9
- return draftMode().isEnabled;
9
+ return draftMode().isEnabled || isIncontextEditingEnabled({ searchParams });
10
10
  };
11
11
  export const isIncontextEditingEnabled = ({ searchParams, }) => {
12
- // workaround for this https://github.com/vercel/next.js/issues/49927, as draftMode() is not working in dev mode
13
- // so we just need to check if the query string contains the IN_CONTEXT_EDITOR_QUERY_STRING_PARAM blindly
14
- if (isDevelopmentEnvironment() || draftMode().isEnabled) {
15
- const containsKey = typeof (searchParams === null || searchParams === void 0 ? void 0 : searchParams[IN_CONTEXT_EDITOR_QUERY_STRING_PARAM]) !== 'undefined';
16
- return containsKey;
17
- }
18
- return false;
12
+ // todo (adaml): draft mode can't be trusted in edge mode, consider in context editing if query string
13
+ // is present: https://github.com/vercel/next.js/issues/52080
14
+ const containsKey = typeof (searchParams === null || searchParams === void 0 ? void 0 : searchParams[IN_CONTEXT_EDITOR_QUERY_STRING_PARAM]) !== 'undefined';
15
+ return containsKey;
19
16
  };
20
17
  export const isOnVercelPreviewEnvironment = () => {
21
18
  return process.env.VERCEL_ENV === 'preview';
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@uniformdev/canvas-next-rsc",
3
- "version": "19.49.0",
3
+ "version": "19.49.4-alpha.67+9773e3b65",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "scripts": {
6
- "dev": "pnpm build --watch",
6
+ "dev": "tsc --watch",
7
7
  "build": "tsc && node scripts/remove-export.js",
8
8
  "lint": "eslint \"**/*.{ts,tsx}\" --fix",
9
9
  "test": "jest --maxWorkers=1 --passWithNoTests"
@@ -48,33 +48,35 @@
48
48
  "@types/gtag.js": "^0.0.13",
49
49
  "@types/js-cookie": "^3.0.3",
50
50
  "@types/node": "^18.0.0",
51
- "@types/react": "^18.2.3",
51
+ "@types/react": "^18.2.20",
52
52
  "eslint": "^8.11.0",
53
- "next": "13.4.12",
53
+ "next": "^13.4.12",
54
54
  "react": "18.2.0",
55
- "react-dom": "18.2.0",
56
- "typescript": "^5.0.4"
55
+ "react-dom": "18.2.0"
57
56
  },
58
57
  "dependencies": {
59
- "@uniformdev/canvas": "19.49.0",
60
- "@uniformdev/canvas-react": "19.49.0",
61
- "@uniformdev/context": "19.49.0",
62
- "@uniformdev/project-map": "19.49.0",
63
- "@uniformdev/redirect": "19.49.0",
64
- "@uniformdev/richtext": "19.49.0",
65
- "@uniformdev/webhooks": "19.49.0",
58
+ "@uniformdev/canvas": "19.49.4-alpha.67+9773e3b65",
59
+ "@uniformdev/canvas-react": "19.49.4-alpha.67+9773e3b65",
60
+ "@uniformdev/context": "19.49.4-alpha.67+9773e3b65",
61
+ "@uniformdev/project-map": "19.49.4-alpha.67+9773e3b65",
62
+ "@uniformdev/redirect": "19.49.4-alpha.67+9773e3b65",
63
+ "@uniformdev/richtext": "19.49.4-alpha.67+9773e3b65",
64
+ "@uniformdev/webhooks": "19.49.4-alpha.67+9773e3b65",
66
65
  "@vercel/edge-config": "^0.2.0",
67
66
  "dequal": "^2.0.3",
68
67
  "js-cookie": "^3.0.5",
69
68
  "svix": "^1.5.0"
70
69
  },
70
+ "engines": {
71
+ "node": ">=16.14.0"
72
+ },
71
73
  "peerDependencies": {
72
74
  "next": ">=13.4.7",
73
- "react": ">=16.13.1 || 17 || 18",
74
- "react-dom": ">=16.13.1"
75
+ "react": ">=18.2",
76
+ "react-dom": ">=18.2"
75
77
  },
76
78
  "publishConfig": {
77
79
  "access": "public"
78
80
  },
79
- "gitHead": "7aaac583f8003f3e510e6a68a76828a32cbf451d"
81
+ "gitHead": "9773e3b65168255768f5cbecf2536988fa0e03af"
80
82
  }
@@ -1,3 +0,0 @@
1
- import { UniformServerConfig } from './models';
2
- declare const config: UniformServerConfig;
3
- export default config;
@@ -1,3 +0,0 @@
1
- // NOTE: this file will be replaced at build time with (project root)/uniform.client.config.js (if it exists)
2
- const config = {};
3
- export default config;