@builder.io/sdk-react 0.1.11 → 0.1.12
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/dist/react/blocks/symbol/symbol.js +40 -35
- package/dist/react/components/render-content/render-content.js +7 -0
- package/dist/react/context/builder.context.js +1 -0
- package/dist/react/functions/get-content/generate-content-url.js +5 -2
- package/dist/react/functions/get-content/generate-content-url.test.js +42 -0
- package/dist/react/types/api-version.js +1 -0
- package/dist/rsc/blocks/symbol/symbol.js +46 -19
- package/dist/rsc/components/render-content/render-content.js +1 -0
- package/dist/rsc/context/builder.context.js +1 -0
- package/dist/rsc/functions/get-content/generate-content-url.js +5 -2
- package/dist/rsc/functions/get-content/generate-content-url.test.js +42 -0
- package/dist/rsc/types/api-version.js +1 -0
- package/package.json +1 -1
- package/packages/react/src/blocks/symbol/symbol.jsx +36 -28
- package/packages/react/src/components/render-content/render-content.jsx +7 -0
- package/packages/react/src/context/builder.context.js +1 -0
- package/packages/react/src/functions/get-content/generate-content-url.js +6 -2
- package/packages/react/src/functions/get-content/generate-content-url.test.js +42 -0
- package/packages/react/src/types/api-version.js +0 -0
- package/packages/rsc/src/blocks/symbol/symbol.jsx +51 -18
- package/packages/rsc/src/components/render-content/render-content.jsx +1 -0
- package/packages/rsc/src/context/builder.context.js +1 -0
- package/packages/rsc/src/functions/get-content/generate-content-url.js +6 -2
- package/packages/rsc/src/functions/get-content/generate-content-url.test.js +42 -0
- package/packages/rsc/src/types/api-version.js +0 -0
|
@@ -5,27 +5,20 @@ import BuilderContext from "../../context/builder.context.js";
|
|
|
5
5
|
import { getContent } from "../../functions/get-content/index.js";
|
|
6
6
|
import { TARGET } from "../../constants/target";
|
|
7
7
|
function Symbol(props) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const [fetchedContent, setFetchedContent] = useState(() => null);
|
|
23
|
-
function contentToUse() {
|
|
24
|
-
return props.symbol?.content || fetchedContent;
|
|
25
|
-
}
|
|
26
|
-
const builderContext = useContext(BuilderContext);
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
const symbolToUse = props.symbol;
|
|
8
|
+
const [className, setClassName] = useState(() => [
|
|
9
|
+
...(TARGET === "vue2" || TARGET === "vue3"
|
|
10
|
+
? Object.keys(props.attributes.class)
|
|
11
|
+
: [props.attributes.class]),
|
|
12
|
+
"builder-symbol",
|
|
13
|
+
props.symbol?.inline ? "builder-inline-symbol" : undefined,
|
|
14
|
+
props.symbol?.dynamic || props.dynamic
|
|
15
|
+
? "builder-dynamic-symbol"
|
|
16
|
+
: undefined,
|
|
17
|
+
]
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.join(" "));
|
|
20
|
+
const [contentToUse, setContentToUse] = useState(() => props.symbol?.content);
|
|
21
|
+
function fetchContent() {
|
|
29
22
|
/**
|
|
30
23
|
* If:
|
|
31
24
|
* - we have a symbol prop
|
|
@@ -35,30 +28,42 @@ function Symbol(props) {
|
|
|
35
28
|
*
|
|
36
29
|
* then we want to re-fetch the symbol content.
|
|
37
30
|
*/
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
!fetchedContent &&
|
|
41
|
-
symbolToUse.model &&
|
|
31
|
+
if (!contentToUse &&
|
|
32
|
+
props.symbol?.model &&
|
|
42
33
|
// This is a hack, we should not need to check for this, but it is needed for Svelte.
|
|
43
34
|
builderContext?.apiKey) {
|
|
44
35
|
getContent({
|
|
45
|
-
model:
|
|
36
|
+
model: props.symbol.model,
|
|
46
37
|
apiKey: builderContext.apiKey,
|
|
38
|
+
apiVersion: builderContext.apiVersion,
|
|
47
39
|
query: {
|
|
48
|
-
id:
|
|
40
|
+
id: props.symbol.entry,
|
|
49
41
|
},
|
|
50
|
-
})
|
|
51
|
-
|
|
42
|
+
})
|
|
43
|
+
.then((response) => {
|
|
44
|
+
if (response) {
|
|
45
|
+
setContentToUse(response);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.catch((err) => {
|
|
49
|
+
console.error("[Builder.io]: Could not fetch symbol content: ", err);
|
|
52
50
|
});
|
|
53
51
|
}
|
|
54
|
-
}
|
|
52
|
+
}
|
|
53
|
+
const builderContext = useContext(BuilderContext);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
fetchContent();
|
|
56
|
+
}, []);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
fetchContent();
|
|
59
|
+
}, [props.symbol]);
|
|
55
60
|
return (React.createElement("div", { ...props.attributes, dataSet: {
|
|
56
|
-
class: className
|
|
57
|
-
}, className: className
|
|
58
|
-
React.createElement(RenderContent, { apiKey: builderContext.apiKey, context: builderContext.context, customComponents: Object.values(builderContext.registeredComponents), data: {
|
|
61
|
+
class: className,
|
|
62
|
+
}, className: className },
|
|
63
|
+
React.createElement(RenderContent, { apiVersion: builderContext.apiVersion, apiKey: builderContext.apiKey, context: builderContext.context, customComponents: Object.values(builderContext.registeredComponents), data: {
|
|
59
64
|
...props.symbol?.data,
|
|
60
65
|
...builderContext.state,
|
|
61
|
-
...
|
|
62
|
-
}, model: props.symbol?.model, content: contentToUse
|
|
66
|
+
...contentToUse?.data?.state,
|
|
67
|
+
}, model: props.symbol?.model, content: contentToUse })));
|
|
63
68
|
}
|
|
64
69
|
export default Symbol;
|
|
@@ -241,6 +241,7 @@ function RenderContent(props) {
|
|
|
241
241
|
getContent({
|
|
242
242
|
model: props.model,
|
|
243
243
|
apiKey: props.apiKey,
|
|
244
|
+
apiVersion: props.apiVersion,
|
|
244
245
|
}).then((content) => {
|
|
245
246
|
if (content) {
|
|
246
247
|
mergeNewContent(content);
|
|
@@ -253,6 +254,11 @@ function RenderContent(props) {
|
|
|
253
254
|
emitStateUpdate();
|
|
254
255
|
}
|
|
255
256
|
}, []);
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
if (props.content) {
|
|
259
|
+
mergeNewContent(props.content);
|
|
260
|
+
}
|
|
261
|
+
}, [props.content]);
|
|
256
262
|
useEffect(() => {
|
|
257
263
|
evaluateJsCode();
|
|
258
264
|
}, [useContent?.data?.jsCode, contentState]);
|
|
@@ -276,6 +282,7 @@ function RenderContent(props) {
|
|
|
276
282
|
setState: setContextState,
|
|
277
283
|
context: props.context || {},
|
|
278
284
|
apiKey: props.apiKey,
|
|
285
|
+
apiVersion: props.apiVersion,
|
|
279
286
|
registeredComponents: allRegisteredComponents,
|
|
280
287
|
} }, useContent ? (React.createElement(React.Fragment, null,
|
|
281
288
|
React.createElement("div", { ref: elementRef, onClick: (event) => onClick(event), "builder-content-id": useContent?.id, "builder-model": props.model },
|
|
@@ -17,11 +17,14 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
import { flatten } from "../../helpers/flatten.js";
|
|
18
18
|
import { getBuilderSearchParamsFromWindow, normalizeSearchParams } from "../get-builder-search-params/index.js";
|
|
19
19
|
const generateContentUrl = (options) => {
|
|
20
|
-
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale } = options;
|
|
20
|
+
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale, apiVersion = "v2" } = options;
|
|
21
21
|
if (!apiKey) {
|
|
22
22
|
throw new Error("Missing API key");
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (!["v2", "v3"].includes(apiVersion)) {
|
|
25
|
+
throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
|
|
26
|
+
}
|
|
27
|
+
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
|
|
25
28
|
const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
|
|
26
29
|
const flattened = flatten(queryOptions);
|
|
27
30
|
for (const key in flattened) {
|
|
@@ -28,4 +28,46 @@ describe("Generate Content URL", () => {
|
|
|
28
28
|
});
|
|
29
29
|
expect(output).toMatchSnapshot();
|
|
30
30
|
});
|
|
31
|
+
test("generate content url with apiVersion as v2", () => {
|
|
32
|
+
const output = generateContentUrl({
|
|
33
|
+
apiKey: testKey,
|
|
34
|
+
model: testModel,
|
|
35
|
+
query: { id: testId },
|
|
36
|
+
options,
|
|
37
|
+
apiVersion: "v2"
|
|
38
|
+
});
|
|
39
|
+
expect(output).toMatchSnapshot();
|
|
40
|
+
});
|
|
41
|
+
test("generate content url with apiVersion as v3", () => {
|
|
42
|
+
const output = generateContentUrl({
|
|
43
|
+
apiKey: testKey,
|
|
44
|
+
model: testModel,
|
|
45
|
+
query: { id: testId },
|
|
46
|
+
options,
|
|
47
|
+
apiVersion: "v3"
|
|
48
|
+
});
|
|
49
|
+
expect(output).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
test("throw error when trying to generate content url with apiVersion as v1", () => {
|
|
52
|
+
expect(() => {
|
|
53
|
+
generateContentUrl({
|
|
54
|
+
apiKey: testKey,
|
|
55
|
+
model: testModel,
|
|
56
|
+
query: { id: testId },
|
|
57
|
+
options,
|
|
58
|
+
apiVersion: "v1"
|
|
59
|
+
});
|
|
60
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'v1'`);
|
|
61
|
+
});
|
|
62
|
+
test("throw error when trying to generate content url with an invalid apiVersion value", () => {
|
|
63
|
+
expect(() => {
|
|
64
|
+
generateContentUrl({
|
|
65
|
+
apiKey: testKey,
|
|
66
|
+
model: testModel,
|
|
67
|
+
query: { id: testId },
|
|
68
|
+
options,
|
|
69
|
+
apiVersion: "INVALID_API_VERSION"
|
|
70
|
+
});
|
|
71
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`);
|
|
72
|
+
});
|
|
31
73
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -6,33 +6,60 @@ import { TARGET } from "../../constants/target";
|
|
|
6
6
|
function Symbol(props) {
|
|
7
7
|
const _context = { ...props["_context"] };
|
|
8
8
|
const state = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
className: [
|
|
10
|
+
...(TARGET === "vue2" || TARGET === "vue3"
|
|
11
|
+
? Object.keys(props.attributes.class)
|
|
12
|
+
: [props.attributes.class]),
|
|
13
|
+
"builder-symbol",
|
|
14
|
+
props.symbol?.inline ? "builder-inline-symbol" : undefined,
|
|
15
|
+
props.symbol?.dynamic || props.dynamic
|
|
16
|
+
? "builder-dynamic-symbol"
|
|
17
|
+
: undefined,
|
|
18
|
+
]
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join(" "),
|
|
21
|
+
contentToUse: props.symbol?.content,
|
|
22
|
+
fetchContent() {
|
|
23
|
+
/**
|
|
24
|
+
* If:
|
|
25
|
+
* - we have a symbol prop
|
|
26
|
+
* - yet it does not have any content
|
|
27
|
+
* - and we have not already stored content from before
|
|
28
|
+
* - and it has a model name
|
|
29
|
+
*
|
|
30
|
+
* then we want to re-fetch the symbol content.
|
|
31
|
+
*/
|
|
32
|
+
if (!state.contentToUse &&
|
|
33
|
+
props.symbol?.model &&
|
|
34
|
+
// This is a hack, we should not need to check for this, but it is needed for Svelte.
|
|
35
|
+
builderContext?.apiKey) {
|
|
36
|
+
getContent({
|
|
37
|
+
model: props.symbol.model,
|
|
38
|
+
apiKey: builderContext.apiKey,
|
|
39
|
+
apiVersion: builderContext.apiVersion,
|
|
40
|
+
query: {
|
|
41
|
+
id: props.symbol.entry,
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
.then((response) => {
|
|
45
|
+
if (response) {
|
|
46
|
+
state.contentToUse = response;
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
.catch((err) => {
|
|
50
|
+
console.error("[Builder.io]: Could not fetch symbol content: ", err);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
26
53
|
},
|
|
27
54
|
};
|
|
28
55
|
const builderContext = _context["BuilderContext"];
|
|
29
56
|
return (React.createElement("div", { ...props.attributes, dataSet: {
|
|
30
57
|
class: state.className,
|
|
31
58
|
}, className: state.className },
|
|
32
|
-
React.createElement(RenderContent, { apiKey: builderContext.apiKey, context: builderContext.context, customComponents: Object.values(builderContext.registeredComponents), data: {
|
|
59
|
+
React.createElement(RenderContent, { apiVersion: builderContext.apiVersion, apiKey: builderContext.apiKey, context: builderContext.context, customComponents: Object.values(builderContext.registeredComponents), data: {
|
|
33
60
|
...props.symbol?.data,
|
|
34
61
|
...builderContext.state,
|
|
35
|
-
...
|
|
62
|
+
...state.contentToUse?.data?.state,
|
|
36
63
|
}, model: props.symbol?.model, content: state.contentToUse, _context: _context })));
|
|
37
64
|
}
|
|
38
65
|
export default Symbol;
|
|
@@ -192,6 +192,7 @@ function RenderContent(props) {
|
|
|
192
192
|
setState: state.setContextState,
|
|
193
193
|
context: props.context || {},
|
|
194
194
|
apiKey: props.apiKey,
|
|
195
|
+
apiVersion: props.apiVersion,
|
|
195
196
|
registeredComponents: state.allRegisteredComponents,
|
|
196
197
|
};
|
|
197
198
|
return (React.createElement(React.Fragment, null, state.useContent ? (React.createElement(React.Fragment, null,
|
|
@@ -17,11 +17,14 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
import { flatten } from "../../helpers/flatten.js";
|
|
18
18
|
import { getBuilderSearchParamsFromWindow, normalizeSearchParams } from "../get-builder-search-params/index.js";
|
|
19
19
|
const generateContentUrl = (options) => {
|
|
20
|
-
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale } = options;
|
|
20
|
+
const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale, apiVersion = "v2" } = options;
|
|
21
21
|
if (!apiKey) {
|
|
22
22
|
throw new Error("Missing API key");
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (!["v2", "v3"].includes(apiVersion)) {
|
|
25
|
+
throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
|
|
26
|
+
}
|
|
27
|
+
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
|
|
25
28
|
const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
|
|
26
29
|
const flattened = flatten(queryOptions);
|
|
27
30
|
for (const key in flattened) {
|
|
@@ -28,4 +28,46 @@ describe("Generate Content URL", () => {
|
|
|
28
28
|
});
|
|
29
29
|
expect(output).toMatchSnapshot();
|
|
30
30
|
});
|
|
31
|
+
test("generate content url with apiVersion as v2", () => {
|
|
32
|
+
const output = generateContentUrl({
|
|
33
|
+
apiKey: testKey,
|
|
34
|
+
model: testModel,
|
|
35
|
+
query: { id: testId },
|
|
36
|
+
options,
|
|
37
|
+
apiVersion: "v2"
|
|
38
|
+
});
|
|
39
|
+
expect(output).toMatchSnapshot();
|
|
40
|
+
});
|
|
41
|
+
test("generate content url with apiVersion as v3", () => {
|
|
42
|
+
const output = generateContentUrl({
|
|
43
|
+
apiKey: testKey,
|
|
44
|
+
model: testModel,
|
|
45
|
+
query: { id: testId },
|
|
46
|
+
options,
|
|
47
|
+
apiVersion: "v3"
|
|
48
|
+
});
|
|
49
|
+
expect(output).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
test("throw error when trying to generate content url with apiVersion as v1", () => {
|
|
52
|
+
expect(() => {
|
|
53
|
+
generateContentUrl({
|
|
54
|
+
apiKey: testKey,
|
|
55
|
+
model: testModel,
|
|
56
|
+
query: { id: testId },
|
|
57
|
+
options,
|
|
58
|
+
apiVersion: "v1"
|
|
59
|
+
});
|
|
60
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'v1'`);
|
|
61
|
+
});
|
|
62
|
+
test("throw error when trying to generate content url with an invalid apiVersion value", () => {
|
|
63
|
+
expect(() => {
|
|
64
|
+
generateContentUrl({
|
|
65
|
+
apiKey: testKey,
|
|
66
|
+
model: testModel,
|
|
67
|
+
query: { id: testId },
|
|
68
|
+
options,
|
|
69
|
+
apiVersion: "INVALID_API_VERSION"
|
|
70
|
+
});
|
|
71
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`);
|
|
72
|
+
});
|
|
31
73
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@ import { getContent } from "../../functions/get-content/index.js";
|
|
|
6
6
|
import { TARGET } from "../../constants/target";
|
|
7
7
|
|
|
8
8
|
function Symbol(props) {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const [className, setClassName] = useState(() =>
|
|
10
|
+
[
|
|
11
11
|
...(TARGET === "vue2" || TARGET === "vue3"
|
|
12
12
|
? Object.keys(props.attributes.class)
|
|
13
13
|
: [props.attributes.class]),
|
|
@@ -18,20 +18,12 @@ function Symbol(props) {
|
|
|
18
18
|
: undefined,
|
|
19
19
|
]
|
|
20
20
|
.filter(Boolean)
|
|
21
|
-
.join(" ")
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const [fetchedContent, setFetchedContent] = useState(() => null);
|
|
25
|
-
|
|
26
|
-
function contentToUse() {
|
|
27
|
-
return props.symbol?.content || fetchedContent;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const builderContext = useContext(BuilderContext);
|
|
21
|
+
.join(" ")
|
|
22
|
+
);
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
const symbolToUse = props.symbol;
|
|
24
|
+
const [contentToUse, setContentToUse] = useState(() => props.symbol?.content);
|
|
34
25
|
|
|
26
|
+
function fetchContent() {
|
|
35
27
|
/**
|
|
36
28
|
* If:
|
|
37
29
|
* - we have a symbol prop
|
|
@@ -42,44 +34,60 @@ function Symbol(props) {
|
|
|
42
34
|
* then we want to re-fetch the symbol content.
|
|
43
35
|
*/
|
|
44
36
|
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
!fetchedContent &&
|
|
48
|
-
symbolToUse.model &&
|
|
37
|
+
!contentToUse &&
|
|
38
|
+
props.symbol?.model &&
|
|
49
39
|
// This is a hack, we should not need to check for this, but it is needed for Svelte.
|
|
50
40
|
builderContext?.apiKey
|
|
51
41
|
) {
|
|
52
42
|
getContent({
|
|
53
|
-
model:
|
|
43
|
+
model: props.symbol.model,
|
|
54
44
|
apiKey: builderContext.apiKey,
|
|
45
|
+
apiVersion: builderContext.apiVersion,
|
|
55
46
|
query: {
|
|
56
|
-
id:
|
|
47
|
+
id: props.symbol.entry,
|
|
57
48
|
},
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
})
|
|
50
|
+
.then((response) => {
|
|
51
|
+
if (response) {
|
|
52
|
+
setContentToUse(response);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.catch((err) => {
|
|
56
|
+
console.error("[Builder.io]: Could not fetch symbol content: ", err);
|
|
57
|
+
});
|
|
61
58
|
}
|
|
62
|
-
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const builderContext = useContext(BuilderContext);
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
fetchContent();
|
|
65
|
+
}, []);
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
fetchContent();
|
|
69
|
+
}, [props.symbol]);
|
|
63
70
|
|
|
64
71
|
return (
|
|
65
72
|
<div
|
|
66
73
|
{...props.attributes}
|
|
67
74
|
dataSet={{
|
|
68
|
-
class: className
|
|
75
|
+
class: className,
|
|
69
76
|
}}
|
|
70
|
-
className={className
|
|
77
|
+
className={className}
|
|
71
78
|
>
|
|
72
79
|
<RenderContent
|
|
80
|
+
apiVersion={builderContext.apiVersion}
|
|
73
81
|
apiKey={builderContext.apiKey}
|
|
74
82
|
context={builderContext.context}
|
|
75
83
|
customComponents={Object.values(builderContext.registeredComponents)}
|
|
76
84
|
data={{
|
|
77
85
|
...props.symbol?.data,
|
|
78
86
|
...builderContext.state,
|
|
79
|
-
...
|
|
87
|
+
...contentToUse?.data?.state,
|
|
80
88
|
}}
|
|
81
89
|
model={props.symbol?.model}
|
|
82
|
-
content={contentToUse
|
|
90
|
+
content={contentToUse}
|
|
83
91
|
/>
|
|
84
92
|
</div>
|
|
85
93
|
);
|
|
@@ -300,6 +300,7 @@ function RenderContent(props) {
|
|
|
300
300
|
getContent({
|
|
301
301
|
model: props.model,
|
|
302
302
|
apiKey: props.apiKey,
|
|
303
|
+
apiVersion: props.apiVersion,
|
|
303
304
|
}).then((content) => {
|
|
304
305
|
if (content) {
|
|
305
306
|
mergeNewContent(content);
|
|
@@ -313,6 +314,11 @@ function RenderContent(props) {
|
|
|
313
314
|
}
|
|
314
315
|
}, []);
|
|
315
316
|
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
if (props.content) {
|
|
319
|
+
mergeNewContent(props.content);
|
|
320
|
+
}
|
|
321
|
+
}, [props.content]);
|
|
316
322
|
useEffect(() => {
|
|
317
323
|
evaluateJsCode();
|
|
318
324
|
}, [useContent?.data?.jsCode, contentState]);
|
|
@@ -343,6 +349,7 @@ function RenderContent(props) {
|
|
|
343
349
|
setState: setContextState,
|
|
344
350
|
context: props.context || {},
|
|
345
351
|
apiKey: props.apiKey,
|
|
352
|
+
apiVersion: props.apiVersion,
|
|
346
353
|
registeredComponents: allRegisteredComponents,
|
|
347
354
|
}}
|
|
348
355
|
>
|
|
@@ -28,12 +28,16 @@ const generateContentUrl = (options) => {
|
|
|
28
28
|
model,
|
|
29
29
|
apiKey,
|
|
30
30
|
includeRefs = true,
|
|
31
|
-
locale
|
|
31
|
+
locale,
|
|
32
|
+
apiVersion = "v2"
|
|
32
33
|
} = options;
|
|
33
34
|
if (!apiKey) {
|
|
34
35
|
throw new Error("Missing API key");
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
if (!["v2", "v3"].includes(apiVersion)) {
|
|
38
|
+
throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
|
|
39
|
+
}
|
|
40
|
+
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
|
|
37
41
|
const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
|
|
38
42
|
const flattened = flatten(queryOptions);
|
|
39
43
|
for (const key in flattened) {
|
|
@@ -28,4 +28,46 @@ describe("Generate Content URL", () => {
|
|
|
28
28
|
});
|
|
29
29
|
expect(output).toMatchSnapshot();
|
|
30
30
|
});
|
|
31
|
+
test("generate content url with apiVersion as v2", () => {
|
|
32
|
+
const output = generateContentUrl({
|
|
33
|
+
apiKey: testKey,
|
|
34
|
+
model: testModel,
|
|
35
|
+
query: { id: testId },
|
|
36
|
+
options,
|
|
37
|
+
apiVersion: "v2"
|
|
38
|
+
});
|
|
39
|
+
expect(output).toMatchSnapshot();
|
|
40
|
+
});
|
|
41
|
+
test("generate content url with apiVersion as v3", () => {
|
|
42
|
+
const output = generateContentUrl({
|
|
43
|
+
apiKey: testKey,
|
|
44
|
+
model: testModel,
|
|
45
|
+
query: { id: testId },
|
|
46
|
+
options,
|
|
47
|
+
apiVersion: "v3"
|
|
48
|
+
});
|
|
49
|
+
expect(output).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
test("throw error when trying to generate content url with apiVersion as v1", () => {
|
|
52
|
+
expect(() => {
|
|
53
|
+
generateContentUrl({
|
|
54
|
+
apiKey: testKey,
|
|
55
|
+
model: testModel,
|
|
56
|
+
query: { id: testId },
|
|
57
|
+
options,
|
|
58
|
+
apiVersion: "v1"
|
|
59
|
+
});
|
|
60
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'v1'`);
|
|
61
|
+
});
|
|
62
|
+
test("throw error when trying to generate content url with an invalid apiVersion value", () => {
|
|
63
|
+
expect(() => {
|
|
64
|
+
generateContentUrl({
|
|
65
|
+
apiKey: testKey,
|
|
66
|
+
model: testModel,
|
|
67
|
+
query: { id: testId },
|
|
68
|
+
options,
|
|
69
|
+
apiVersion: "INVALID_API_VERSION"
|
|
70
|
+
});
|
|
71
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`);
|
|
72
|
+
});
|
|
31
73
|
});
|
|
File without changes
|
|
@@ -8,23 +8,55 @@ function Symbol(props) {
|
|
|
8
8
|
const _context = { ...props["_context"] };
|
|
9
9
|
|
|
10
10
|
const state = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
className: [
|
|
12
|
+
...(TARGET === "vue2" || TARGET === "vue3"
|
|
13
|
+
? Object.keys(props.attributes.class)
|
|
14
|
+
: [props.attributes.class]),
|
|
15
|
+
"builder-symbol",
|
|
16
|
+
props.symbol?.inline ? "builder-inline-symbol" : undefined,
|
|
17
|
+
props.symbol?.dynamic || props.dynamic
|
|
18
|
+
? "builder-dynamic-symbol"
|
|
19
|
+
: undefined,
|
|
20
|
+
]
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join(" "),
|
|
23
|
+
contentToUse: props.symbol?.content,
|
|
24
|
+
fetchContent() {
|
|
25
|
+
/**
|
|
26
|
+
* If:
|
|
27
|
+
* - we have a symbol prop
|
|
28
|
+
* - yet it does not have any content
|
|
29
|
+
* - and we have not already stored content from before
|
|
30
|
+
* - and it has a model name
|
|
31
|
+
*
|
|
32
|
+
* then we want to re-fetch the symbol content.
|
|
33
|
+
*/
|
|
34
|
+
if (
|
|
35
|
+
!state.contentToUse &&
|
|
36
|
+
props.symbol?.model &&
|
|
37
|
+
// This is a hack, we should not need to check for this, but it is needed for Svelte.
|
|
38
|
+
builderContext?.apiKey
|
|
39
|
+
) {
|
|
40
|
+
getContent({
|
|
41
|
+
model: props.symbol.model,
|
|
42
|
+
apiKey: builderContext.apiKey,
|
|
43
|
+
apiVersion: builderContext.apiVersion,
|
|
44
|
+
query: {
|
|
45
|
+
id: props.symbol.entry,
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
.then((response) => {
|
|
49
|
+
if (response) {
|
|
50
|
+
state.contentToUse = response;
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
.catch((err) => {
|
|
54
|
+
console.error(
|
|
55
|
+
"[Builder.io]: Could not fetch symbol content: ",
|
|
56
|
+
err
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
28
60
|
},
|
|
29
61
|
};
|
|
30
62
|
|
|
@@ -39,13 +71,14 @@ function Symbol(props) {
|
|
|
39
71
|
className={state.className}
|
|
40
72
|
>
|
|
41
73
|
<RenderContent
|
|
74
|
+
apiVersion={builderContext.apiVersion}
|
|
42
75
|
apiKey={builderContext.apiKey}
|
|
43
76
|
context={builderContext.context}
|
|
44
77
|
customComponents={Object.values(builderContext.registeredComponents)}
|
|
45
78
|
data={{
|
|
46
79
|
...props.symbol?.data,
|
|
47
80
|
...builderContext.state,
|
|
48
|
-
...
|
|
81
|
+
...state.contentToUse?.data?.state,
|
|
49
82
|
}}
|
|
50
83
|
model={props.symbol?.model}
|
|
51
84
|
content={state.contentToUse}
|
|
@@ -28,12 +28,16 @@ const generateContentUrl = (options) => {
|
|
|
28
28
|
model,
|
|
29
29
|
apiKey,
|
|
30
30
|
includeRefs = true,
|
|
31
|
-
locale
|
|
31
|
+
locale,
|
|
32
|
+
apiVersion = "v2"
|
|
32
33
|
} = options;
|
|
33
34
|
if (!apiKey) {
|
|
34
35
|
throw new Error("Missing API key");
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
if (!["v2", "v3"].includes(apiVersion)) {
|
|
38
|
+
throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
|
|
39
|
+
}
|
|
40
|
+
const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ""}`);
|
|
37
41
|
const queryOptions = __spreadValues(__spreadValues({}, getBuilderSearchParamsFromWindow()), normalizeSearchParams(options.options || {}));
|
|
38
42
|
const flattened = flatten(queryOptions);
|
|
39
43
|
for (const key in flattened) {
|
|
@@ -28,4 +28,46 @@ describe("Generate Content URL", () => {
|
|
|
28
28
|
});
|
|
29
29
|
expect(output).toMatchSnapshot();
|
|
30
30
|
});
|
|
31
|
+
test("generate content url with apiVersion as v2", () => {
|
|
32
|
+
const output = generateContentUrl({
|
|
33
|
+
apiKey: testKey,
|
|
34
|
+
model: testModel,
|
|
35
|
+
query: { id: testId },
|
|
36
|
+
options,
|
|
37
|
+
apiVersion: "v2"
|
|
38
|
+
});
|
|
39
|
+
expect(output).toMatchSnapshot();
|
|
40
|
+
});
|
|
41
|
+
test("generate content url with apiVersion as v3", () => {
|
|
42
|
+
const output = generateContentUrl({
|
|
43
|
+
apiKey: testKey,
|
|
44
|
+
model: testModel,
|
|
45
|
+
query: { id: testId },
|
|
46
|
+
options,
|
|
47
|
+
apiVersion: "v3"
|
|
48
|
+
});
|
|
49
|
+
expect(output).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
test("throw error when trying to generate content url with apiVersion as v1", () => {
|
|
52
|
+
expect(() => {
|
|
53
|
+
generateContentUrl({
|
|
54
|
+
apiKey: testKey,
|
|
55
|
+
model: testModel,
|
|
56
|
+
query: { id: testId },
|
|
57
|
+
options,
|
|
58
|
+
apiVersion: "v1"
|
|
59
|
+
});
|
|
60
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'v1'`);
|
|
61
|
+
});
|
|
62
|
+
test("throw error when trying to generate content url with an invalid apiVersion value", () => {
|
|
63
|
+
expect(() => {
|
|
64
|
+
generateContentUrl({
|
|
65
|
+
apiKey: testKey,
|
|
66
|
+
model: testModel,
|
|
67
|
+
query: { id: testId },
|
|
68
|
+
options,
|
|
69
|
+
apiVersion: "INVALID_API_VERSION"
|
|
70
|
+
});
|
|
71
|
+
}).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`);
|
|
72
|
+
});
|
|
31
73
|
});
|
|
File without changes
|