@builder.io/sdk-svelte 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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.1.10",
4
+ "version": "0.1.11",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -139,6 +139,7 @@
139
139
  "./index-helpers/blocks-exports": "./index-helpers/blocks-exports.js",
140
140
  "./index-helpers/top-of-file": "./index-helpers/top-of-file.js",
141
141
  "./scripts/init-editing": "./scripts/init-editing.js",
142
+ "./types/api-version": "./types/api-version.js",
142
143
  "./types/builder-block": "./types/builder-block.js",
143
144
  "./types/builder-content": "./types/builder-content.js",
144
145
  "./types/can-track": "./types/can-track.js",
@@ -1,3 +1,7 @@
1
+ ### 0.1.11
2
+
3
+ - No changes.
4
+
1
5
  ### 0.1.10
2
6
 
3
7
  - Fix: Text blocks styles (remove initial top padding)
@@ -1,6 +1,6 @@
1
1
  <script context="module"></script>
2
2
 
3
- <script>import { getContext } from "svelte";
3
+ <script>import { getContext, onMount } from "svelte";
4
4
  import RenderContent from "../../components/render-content/render-content.svelte";
5
5
  import BuilderContext from "../../context/builder.context.js";
6
6
  import { getContent } from "../../functions/get-content/index.js";
@@ -36,24 +36,7 @@ export let attributes;
36
36
  export let symbol;
37
37
  export let dynamic;
38
38
  let builderContext = getContext(BuilderContext.key);
39
- $: className = () => {
40
- return [
41
- ...(TARGET === "vue2" || TARGET === "vue3"
42
- ? Object.keys(attributes.class)
43
- : [attributes.class]),
44
- "builder-symbol",
45
- symbol?.inline ? "builder-inline-symbol" : undefined,
46
- symbol?.dynamic || dynamic ? "builder-dynamic-symbol" : undefined,
47
- ]
48
- .filter(Boolean)
49
- .join(" ");
50
- };
51
- $: contentToUse = () => {
52
- return symbol?.content || fetchedContent;
53
- };
54
- let fetchedContent = null;
55
- function onUpdateFn_0() {
56
- const symbolToUse = symbol;
39
+ function fetchContent() {
57
40
  /**
58
41
  * If:
59
42
  * - we have a symbol prop
@@ -63,44 +46,67 @@ function onUpdateFn_0() {
63
46
  *
64
47
  * then we want to re-fetch the symbol content.
65
48
  */
66
- if (symbolToUse &&
67
- !symbolToUse.content &&
68
- !fetchedContent &&
69
- symbolToUse.model &&
49
+ if (!contentToUse &&
50
+ symbol?.model &&
70
51
  // This is a hack, we should not need to check for this, but it is needed for Svelte.
71
52
  builderContext?.apiKey) {
72
53
  getContent({
73
- model: symbolToUse.model,
54
+ model: symbol.model,
74
55
  apiKey: builderContext.apiKey,
56
+ apiVersion: builderContext.apiVersion,
75
57
  query: {
76
- id: symbolToUse.entry,
58
+ id: symbol.entry,
77
59
  },
78
- }).then((response) => {
79
- fetchedContent = response;
60
+ })
61
+ .then((response) => {
62
+ if (response) {
63
+ contentToUse = response;
64
+ }
65
+ })
66
+ .catch((err) => {
67
+ console.error("[Builder.io]: Could not fetch symbol content: ", err);
80
68
  });
81
69
  }
82
70
  }
83
- $: onUpdateFn_0(...[symbol, fetchedContent]);
71
+ let className = [
72
+ ...(TARGET === "vue2" || TARGET === "vue3"
73
+ ? Object.keys(attributes.class)
74
+ : [attributes.class]),
75
+ "builder-symbol",
76
+ symbol?.inline ? "builder-inline-symbol" : undefined,
77
+ symbol?.dynamic || dynamic ? "builder-dynamic-symbol" : undefined,
78
+ ]
79
+ .filter(Boolean)
80
+ .join(" ");
81
+ let contentToUse = symbol?.content;
82
+ onMount(() => {
83
+ fetchContent();
84
+ });
85
+ function onUpdateFn_0() {
86
+ fetchContent();
87
+ }
88
+ $: onUpdateFn_0(...[symbol]);
84
89
  </script>
85
90
 
86
91
  <div
87
92
  {...filterAttrs(attributes, isNonEvent)}
88
93
  dataSet={{
89
- class: className(),
94
+ class: className,
90
95
  }}
91
- class={className()}
96
+ class={className}
92
97
  use:setAttrs={filterAttrs(attributes, isEvent)}
93
98
  >
94
99
  <RenderContent
100
+ apiVersion={builderContext.apiVersion}
95
101
  apiKey={builderContext.apiKey}
96
102
  context={builderContext.context}
97
103
  customComponents={Object.values(builderContext.registeredComponents)}
98
104
  data={{
99
105
  ...symbol?.data,
100
106
  ...builderContext.state,
101
- ...symbol?.content?.data?.state,
107
+ ...contentToUse?.data?.state,
102
108
  }}
103
109
  model={symbol?.model}
104
- content={contentToUse()}
110
+ content={contentToUse}
105
111
  />
106
112
  </div>
@@ -27,6 +27,7 @@ export let model;
27
27
  export let context;
28
28
  export let apiKey;
29
29
  export let includeRefs;
30
+ export let apiVersion;
30
31
  function mergeNewContent(newContent) {
31
32
  useContent = {
32
33
  ...useContent,
@@ -251,6 +252,7 @@ onMount(() => {
251
252
  getContent({
252
253
  model: model,
253
254
  apiKey: apiKey,
255
+ apiVersion: apiVersion,
254
256
  }).then((content) => {
255
257
  if (content) {
256
258
  mergeNewContent(content);
@@ -264,17 +266,23 @@ onMount(() => {
264
266
  }
265
267
  });
266
268
  function onUpdateFn_0() {
267
- evaluateJsCode();
269
+ if (content) {
270
+ mergeNewContent(content);
271
+ }
268
272
  }
269
- $: onUpdateFn_0(...[useContent?.data?.jsCode, contentState]);
273
+ $: onUpdateFn_0(...[content]);
270
274
  function onUpdateFn_1() {
271
- runHttpRequests();
275
+ evaluateJsCode();
272
276
  }
273
- $: onUpdateFn_1(...[useContent?.data?.httpRequests]);
277
+ $: onUpdateFn_1(...[useContent?.data?.jsCode, contentState]);
274
278
  function onUpdateFn_2() {
279
+ runHttpRequests();
280
+ }
281
+ $: onUpdateFn_2(...[useContent?.data?.httpRequests]);
282
+ function onUpdateFn_3() {
275
283
  emitStateUpdate();
276
284
  }
277
- $: onUpdateFn_2(...[contentState]);
285
+ $: onUpdateFn_3(...[contentState]);
278
286
  setContext(builderContext.key, {
279
287
  get content() {
280
288
  return useContent;
@@ -291,6 +299,9 @@ setContext(builderContext.key, {
291
299
  get apiKey() {
292
300
  return apiKey;
293
301
  },
302
+ get apiVersion() {
303
+ return apiVersion;
304
+ },
294
305
  get registeredComponents() {
295
306
  return allRegisteredComponents;
296
307
  },
@@ -11,6 +11,7 @@ declare const __propDef: {
11
11
  context: RenderContentProps["context"];
12
12
  apiKey: RenderContentProps["apiKey"];
13
13
  includeRefs: RenderContentProps["includeRefs"];
14
+ apiVersion: RenderContentProps["apiVersion"];
14
15
  };
15
16
  events: {
16
17
  [evt: string]: CustomEvent<any>;
@@ -1,6 +1,7 @@
1
1
  import type { BuilderRenderContext, RegisteredComponent, BuilderRenderState } from '../../context/types';
2
2
  import type { BuilderContent } from '../../types/builder-content';
3
3
  import type { Nullable } from '../../types/typescript';
4
+ import type { ApiVersion } from '../../types/api-version';
4
5
  export type RenderContentProps = {
5
6
  content?: Nullable<BuilderContent>;
6
7
  model?: string;
@@ -9,6 +10,7 @@ export type RenderContentProps = {
9
10
  };
10
11
  context?: BuilderRenderContext;
11
12
  apiKey: string;
13
+ apiVersion?: ApiVersion;
12
14
  customComponents?: RegisteredComponent[];
13
15
  canTrack?: boolean;
14
16
  locale?: string;
@@ -5,6 +5,7 @@ declare const _default: {
5
5
  state: {};
6
6
  setState(): void;
7
7
  apiKey: null;
8
+ apiVersion: undefined;
8
9
  registeredComponents: {};
9
10
  inheritedStyles: {};
10
11
  };
@@ -6,6 +6,7 @@ export default {
6
6
  state: {},
7
7
  setState() { },
8
8
  apiKey: null,
9
+ apiVersion: undefined,
9
10
  registeredComponents: {},
10
11
  inheritedStyles: {},
11
12
  },
@@ -1,6 +1,7 @@
1
1
  import type { BuilderContent } from '../types/builder-content.js';
2
2
  import type { ComponentInfo } from '../types/components.js';
3
3
  import type { Dictionary, Nullable } from '../types/typescript.js';
4
+ import type { ApiVersion } from '../types/api-version.js';
4
5
  export type RegisteredComponent = ComponentInfo & {
5
6
  component: any;
6
7
  };
@@ -13,6 +14,7 @@ export interface BuilderContextInterface {
13
14
  state: BuilderRenderState;
14
15
  setState?: (state: BuilderRenderState) => void;
15
16
  apiKey: string | null;
17
+ apiVersion?: ApiVersion;
16
18
  registeredComponents: RegisteredComponents;
17
19
  inheritedStyles: Record<string, unknown>;
18
20
  }
@@ -1,11 +1,14 @@
1
1
  import { flatten } from '../../helpers/flatten.js';
2
2
  import { getBuilderSearchParamsFromWindow, normalizeSearchParams, } from '../get-builder-search-params/index.js';
3
3
  export const generateContentUrl = (options) => {
4
- const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale, } = options;
4
+ const { limit = 30, userAttributes, query, noTraverse = false, model, apiKey, includeRefs = true, locale, apiVersion = 'v2', } = options;
5
5
  if (!apiKey) {
6
6
  throw new Error('Missing API key');
7
7
  }
8
- const url = new URL(`https://cdn.builder.io/api/v2/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ''}`);
8
+ if (!['v2', 'v3'].includes(apiVersion)) {
9
+ throw new Error(`Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`);
10
+ }
11
+ const url = new URL(`https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${locale ? `&locale=${locale}` : ''}`);
9
12
  const queryOptions = {
10
13
  ...getBuilderSearchParamsFromWindow(),
11
14
  ...normalizeSearchParams(options.options || {}),
@@ -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
  });
@@ -36,4 +36,10 @@ export interface GetContentOptions {
36
36
  * If provided, the API will auto-resolve localized objects to the value of this `locale` key.
37
37
  */
38
38
  locale?: string;
39
+ /**
40
+ * If provided, sets the Builder API version used to fetch content.
41
+ *
42
+ * Defaults to `v2`.
43
+ */
44
+ apiVersion?: 'v2' | 'v3';
39
45
  }
@@ -0,0 +1 @@
1
+ export type ApiVersion = 'v2' | 'v3';
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.1.11",
4
+ "version": "0.1.12",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -1,8 +1,6 @@
1
1
  <script context="module" lang="ts">
2
2
  import type { BuilderContent } from "../../types/builder-content.js";
3
3
 
4
- import type { Nullable } from "../../types/typescript.js";
5
-
6
4
  import type { BuilderBlock } from "../../types/builder-block.js";
7
5
 
8
6
  export interface SymbolInfo {
@@ -25,7 +23,7 @@
25
23
  </script>
26
24
 
27
25
  <script lang="ts">
28
- import { getContext } from "svelte";
26
+ import { getContext, onMount } from "svelte";
29
27
 
30
28
  import RenderContent from "../../components/render-content/render-content.svelte";
31
29
  import BuilderContext from "../../context/builder.context.js";
@@ -67,27 +65,7 @@
67
65
 
68
66
  let builderContext = getContext(BuilderContext.key);
69
67
 
70
- $: className = () => {
71
- return [
72
- ...(TARGET === "vue2" || TARGET === "vue3"
73
- ? Object.keys(attributes.class)
74
- : [attributes.class]),
75
- "builder-symbol",
76
- symbol?.inline ? "builder-inline-symbol" : undefined,
77
- symbol?.dynamic || dynamic ? "builder-dynamic-symbol" : undefined,
78
- ]
79
- .filter(Boolean)
80
- .join(" ");
81
- };
82
- $: contentToUse = () => {
83
- return symbol?.content || fetchedContent;
84
- };
85
-
86
- let fetchedContent = null;
87
-
88
- function onUpdateFn_0() {
89
- const symbolToUse = symbol;
90
-
68
+ function fetchContent() {
91
69
  /**
92
70
  * If:
93
71
  * - we have a symbol prop
@@ -98,45 +76,71 @@
98
76
  * then we want to re-fetch the symbol content.
99
77
  */
100
78
  if (
101
- symbolToUse &&
102
- !symbolToUse.content &&
103
- !fetchedContent &&
104
- symbolToUse.model &&
79
+ !contentToUse &&
80
+ symbol?.model &&
105
81
  // This is a hack, we should not need to check for this, but it is needed for Svelte.
106
82
  builderContext?.apiKey
107
83
  ) {
108
84
  getContent({
109
- model: symbolToUse.model,
85
+ model: symbol.model,
110
86
  apiKey: builderContext.apiKey,
87
+ apiVersion: builderContext.apiVersion,
111
88
  query: {
112
- id: symbolToUse.entry,
89
+ id: symbol.entry,
113
90
  },
114
- }).then((response) => {
115
- fetchedContent = response;
116
- });
91
+ })
92
+ .then((response) => {
93
+ if (response) {
94
+ contentToUse = response;
95
+ }
96
+ })
97
+ .catch((err) => {
98
+ console.error("[Builder.io]: Could not fetch symbol content: ", err);
99
+ });
117
100
  }
118
101
  }
119
- $: onUpdateFn_0(...[symbol, fetchedContent]);
102
+
103
+ let className = [
104
+ ...(TARGET === "vue2" || TARGET === "vue3"
105
+ ? Object.keys(attributes.class)
106
+ : [attributes.class]),
107
+ "builder-symbol",
108
+ symbol?.inline ? "builder-inline-symbol" : undefined,
109
+ symbol?.dynamic || dynamic ? "builder-dynamic-symbol" : undefined,
110
+ ]
111
+ .filter(Boolean)
112
+ .join(" ");
113
+ let contentToUse = symbol?.content;
114
+
115
+ onMount(() => {
116
+ fetchContent();
117
+ });
118
+
119
+ function onUpdateFn_0() {
120
+ fetchContent();
121
+ }
122
+ $: onUpdateFn_0(...[symbol]);
120
123
  </script>
121
124
 
122
125
  <div
123
126
  {...filterAttrs(attributes, isNonEvent)}
124
127
  dataSet={{
125
- class: className(),
128
+ class: className,
126
129
  }}
127
- class={className()}
130
+ class={className}
128
131
  use:setAttrs={filterAttrs(attributes, isEvent)}
129
132
  >
130
133
  <RenderContent
134
+ apiVersion={builderContext.apiVersion}
131
135
  apiKey={builderContext.apiKey}
132
136
  context={builderContext.context}
133
137
  customComponents={Object.values(builderContext.registeredComponents)}
134
138
  data={{
135
139
  ...symbol?.data,
136
140
  ...builderContext.state,
137
- ...symbol?.content?.data?.state,
141
+ ...contentToUse?.data?.state,
138
142
  }}
139
143
  model={symbol?.model}
140
- content={contentToUse()}
144
+ content={contentToUse}
141
145
  />
142
146
  </div>
@@ -57,6 +57,7 @@
57
57
  export let context: RenderContentProps["context"];
58
58
  export let apiKey: RenderContentProps["apiKey"];
59
59
  export let includeRefs: RenderContentProps["includeRefs"];
60
+ export let apiVersion: RenderContentProps["apiVersion"];
60
61
 
61
62
  function mergeNewContent(newContent) {
62
63
  useContent = {
@@ -305,6 +306,7 @@
305
306
  getContent({
306
307
  model: model,
307
308
  apiKey: apiKey,
309
+ apiVersion: apiVersion,
308
310
  }).then((content) => {
309
311
  if (content) {
310
312
  mergeNewContent(content);
@@ -319,17 +321,23 @@
319
321
  });
320
322
 
321
323
  function onUpdateFn_0() {
322
- evaluateJsCode();
324
+ if (content) {
325
+ mergeNewContent(content);
326
+ }
323
327
  }
324
- $: onUpdateFn_0(...[useContent?.data?.jsCode, contentState]);
328
+ $: onUpdateFn_0(...[content]);
325
329
  function onUpdateFn_1() {
326
- runHttpRequests();
330
+ evaluateJsCode();
327
331
  }
328
- $: onUpdateFn_1(...[useContent?.data?.httpRequests]);
332
+ $: onUpdateFn_1(...[useContent?.data?.jsCode, contentState]);
329
333
  function onUpdateFn_2() {
334
+ runHttpRequests();
335
+ }
336
+ $: onUpdateFn_2(...[useContent?.data?.httpRequests]);
337
+ function onUpdateFn_3() {
330
338
  emitStateUpdate();
331
339
  }
332
- $: onUpdateFn_2(...[contentState]);
340
+ $: onUpdateFn_3(...[contentState]);
333
341
 
334
342
  setContext(builderContext.key, {
335
343
  get content() {
@@ -347,6 +355,9 @@
347
355
  get apiKey() {
348
356
  return apiKey;
349
357
  },
358
+ get apiVersion() {
359
+ return apiVersion;
360
+ },
350
361
  get registeredComponents() {
351
362
  return allRegisteredComponents;
352
363
  },
@@ -5,6 +5,7 @@ import type {
5
5
  } from '../../context/types';
6
6
  import type { BuilderContent } from '../../types/builder-content';
7
7
  import type { Nullable } from '../../types/typescript';
8
+ import type { ApiVersion } from '../../types/api-version';
8
9
 
9
10
  export type RenderContentProps = {
10
11
  content?: Nullable<BuilderContent>;
@@ -12,6 +13,7 @@ export type RenderContentProps = {
12
13
  data?: { [key: string]: any };
13
14
  context?: BuilderRenderContext;
14
15
  apiKey: string;
16
+ apiVersion?: ApiVersion;
15
17
  customComponents?: RegisteredComponent[];
16
18
  canTrack?: boolean;
17
19
  locale?: string;
@@ -7,6 +7,7 @@ export default {
7
7
  state: {},
8
8
  setState() {},
9
9
  apiKey: null,
10
+ apiVersion: undefined,
10
11
  registeredComponents: {},
11
12
  inheritedStyles: {},
12
13
  },
@@ -1,6 +1,7 @@
1
1
  import type { BuilderContent } from '../types/builder-content.js';
2
2
  import type { ComponentInfo } from '../types/components.js';
3
3
  import type { Dictionary, Nullable } from '../types/typescript.js';
4
+ import type { ApiVersion } from '../types/api-version.js';
4
5
 
5
6
  export type RegisteredComponent = ComponentInfo & {
6
7
  component: any;
@@ -18,6 +19,7 @@ export interface BuilderContextInterface {
18
19
  state: BuilderRenderState;
19
20
  setState?: (state: BuilderRenderState) => void;
20
21
  apiKey: string | null;
22
+ apiVersion?: ApiVersion;
21
23
  registeredComponents: RegisteredComponents;
22
24
  // Used to recursively store all CSS coming from a parent that would apply to a Text block
23
25
  inheritedStyles: Record<string, unknown>;
@@ -1,4 +1,5 @@
1
1
  import { generateContentUrl } from './generate-content-url';
2
+ import type { GetContentOptions } from './types';
2
3
 
3
4
  const testKey = 'YJIGb4i01jvw0SRdL5Bt';
4
5
  const testModel = 'page';
@@ -23,6 +24,7 @@ describe('Generate Content URL', () => {
23
24
  });
24
25
  expect(output).toMatchSnapshot();
25
26
  });
27
+
26
28
  test('Handles overrides correctly', () => {
27
29
  const output = generateContentUrl({
28
30
  apiKey: testKey,
@@ -32,4 +34,52 @@ describe('Generate Content URL', () => {
32
34
  });
33
35
  expect(output).toMatchSnapshot();
34
36
  });
37
+
38
+ test('generate content url with apiVersion as v2', () => {
39
+ const output = generateContentUrl({
40
+ apiKey: testKey,
41
+ model: testModel,
42
+ query: { id: testId },
43
+ options,
44
+ apiVersion: 'v2',
45
+ });
46
+ expect(output).toMatchSnapshot();
47
+ });
48
+
49
+ test('generate content url with apiVersion as v3', () => {
50
+ const output = generateContentUrl({
51
+ apiKey: testKey,
52
+ model: testModel,
53
+ query: { id: testId },
54
+ options,
55
+ apiVersion: 'v3',
56
+ });
57
+ expect(output).toMatchSnapshot();
58
+ });
59
+
60
+ test('throw error when trying to generate content url with apiVersion as v1', () => {
61
+ expect(() => {
62
+ generateContentUrl({
63
+ apiKey: testKey,
64
+ model: testModel,
65
+ query: { id: testId },
66
+ options,
67
+ apiVersion: 'v1' as GetContentOptions['apiVersion'],
68
+ });
69
+ }).toThrow(`Invalid apiVersion: expected 'v2' or 'v3', received 'v1'`);
70
+ });
71
+
72
+ test('throw error when trying to generate content url with an invalid apiVersion value', () => {
73
+ expect(() => {
74
+ generateContentUrl({
75
+ apiKey: testKey,
76
+ model: testModel,
77
+ query: { id: testId },
78
+ options,
79
+ apiVersion: 'INVALID_API_VERSION' as GetContentOptions['apiVersion'],
80
+ });
81
+ }).toThrow(
82
+ `Invalid apiVersion: expected 'v2' or 'v3', received 'INVALID_API_VERSION'`
83
+ );
84
+ });
35
85
  });
@@ -15,14 +15,21 @@ export const generateContentUrl = (options: GetContentOptions): URL => {
15
15
  apiKey,
16
16
  includeRefs = true,
17
17
  locale,
18
+ apiVersion = 'v2',
18
19
  } = options;
19
20
 
20
21
  if (!apiKey) {
21
22
  throw new Error('Missing API key');
22
23
  }
23
24
 
25
+ if (!['v2', 'v3'].includes(apiVersion)) {
26
+ throw new Error(
27
+ `Invalid apiVersion: expected 'v2' or 'v3', received '${apiVersion}'`
28
+ );
29
+ }
30
+
24
31
  const url = new URL(
25
- `https://cdn.builder.io/api/v2/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${
32
+ `https://cdn.builder.io/api/${apiVersion}/content/${model}?apiKey=${apiKey}&limit=${limit}&noTraverse=${noTraverse}&includeRefs=${includeRefs}${
26
33
  locale ? `&locale=${locale}` : ''
27
34
  }`
28
35
  );
@@ -43,4 +43,11 @@ export interface GetContentOptions {
43
43
  * If provided, the API will auto-resolve localized objects to the value of this `locale` key.
44
44
  */
45
45
  locale?: string;
46
+
47
+ /**
48
+ * If provided, sets the Builder API version used to fetch content.
49
+ *
50
+ * Defaults to `v2`.
51
+ */
52
+ apiVersion?: 'v2' | 'v3';
46
53
  }
@@ -0,0 +1 @@
1
+ export type ApiVersion = 'v2' | 'v3';