@builder.io/sdk-svelte 4.1.3 → 4.2.1

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 (30) hide show
  1. package/lib/browser/blocks/form/form/form.svelte +4 -1
  2. package/lib/browser/components/content/components/enable-editor.svelte +25 -5
  3. package/lib/browser/constants/sdk-version.d.ts +1 -1
  4. package/lib/browser/constants/sdk-version.js +1 -1
  5. package/lib/browser/functions/register.d.ts +18 -0
  6. package/lib/browser/functions/register.js +12 -0
  7. package/lib/browser/server-index.d.ts +1 -1
  8. package/lib/browser/server-index.js +1 -1
  9. package/lib/edge/blocks/form/form/form.svelte +4 -1
  10. package/lib/edge/components/content/components/enable-editor.svelte +25 -5
  11. package/lib/edge/constants/sdk-version.d.ts +1 -1
  12. package/lib/edge/constants/sdk-version.js +1 -1
  13. package/lib/edge/functions/register.d.ts +18 -0
  14. package/lib/edge/functions/register.js +12 -0
  15. package/lib/edge/server-index.d.ts +1 -1
  16. package/lib/edge/server-index.js +1 -1
  17. package/lib/node/blocks/form/form/form.svelte +4 -1
  18. package/lib/node/components/content/components/enable-editor.svelte +25 -5
  19. package/lib/node/constants/sdk-version.d.ts +1 -1
  20. package/lib/node/constants/sdk-version.js +1 -1
  21. package/lib/node/functions/register.d.ts +18 -0
  22. package/lib/node/functions/register.js +12 -0
  23. package/lib/node/server-index.d.ts +1 -1
  24. package/lib/node/server-index.js +1 -1
  25. package/package.json +1 -1
  26. package/src/blocks/form/form/form.svelte +7 -1
  27. package/src/components/content/components/enable-editor.svelte +83 -33
  28. package/src/constants/sdk-version.ts +1 -1
  29. package/src/functions/register.ts +29 -0
  30. package/src/server-index.ts +1 -1
@@ -62,13 +62,16 @@ function onSubmit(event) {
62
62
  // TODO: maybe support null
63
63
  const formPairs = Array.from(el.querySelectorAll("input,select,textarea"))
64
64
  .filter((el) => !!el.name)
65
+ .filter((el) => !!el.name &&
66
+ (el.type !== "radio" ||
67
+ el.checked))
65
68
  .map((el) => {
66
69
  let value;
67
70
  const key = el.name;
68
71
  if (el instanceof HTMLInputElement) {
69
72
  if (el.type === "radio") {
70
73
  if (el.checked) {
71
- value = el.name;
74
+ value = el.value;
72
75
  return {
73
76
  key,
74
77
  value,
@@ -126,15 +126,20 @@ function onClick(event) {
126
126
  }
127
127
  function runHttpRequests() {
128
128
  const requests = $builderContextSignal.content?.data?.httpRequests ?? {};
129
- Object.entries(requests).forEach(([key, url]) => {
130
- if (!url)
129
+ Object.entries(requests).forEach(([key, httpRequest]) => {
130
+ if (!httpRequest)
131
131
  return;
132
+ const isCoreRequest = typeof httpRequest === "object" &&
133
+ httpRequest["@type"] === "@builder.io/core:Request";
132
134
  // request already in progress
133
135
  if (httpReqsPending[key])
134
136
  return;
135
137
  // request already completed, and not in edit mode
136
138
  if (httpReqsData[key] && !isEditing())
137
139
  return;
140
+ const url = isCoreRequest
141
+ ? httpRequest.request.url
142
+ : httpRequest;
138
143
  httpReqsPending[key] = true;
139
144
  const evaluatedUrl = url.replace(/{{([^}]+)}}/g, (_match, group) => String(evaluate({
140
145
  code: group,
@@ -143,8 +148,23 @@ function runHttpRequests() {
143
148
  rootState: $builderContextSignal.rootState,
144
149
  rootSetState: $builderContextSignal.rootSetState,
145
150
  })));
146
- logFetch(evaluatedUrl);
147
- fetch(evaluatedUrl)
151
+ const fetchRequestObj = isCoreRequest
152
+ ? {
153
+ url: evaluatedUrl,
154
+ method: httpRequest.request.method,
155
+ headers: httpRequest.request.headers,
156
+ body: httpRequest.request.body,
157
+ }
158
+ : {
159
+ url: evaluatedUrl,
160
+ method: "GET",
161
+ };
162
+ logFetch(JSON.stringify(fetchRequestObj));
163
+ fetch(fetchRequestObj.url, {
164
+ method: fetchRequestObj.method,
165
+ headers: fetchRequestObj.headers,
166
+ body: fetchRequestObj.body,
167
+ })
148
168
  .then((response) => response.json())
149
169
  .then((json) => {
150
170
  mergeNewRootState({
@@ -153,7 +173,7 @@ function runHttpRequests() {
153
173
  httpReqsData[key] = true;
154
174
  })
155
175
  .catch((err) => {
156
- console.error("error fetching dynamic data", url, err);
176
+ console.error("error fetching dynamic data", JSON.stringify(httpRequest), err);
157
177
  })
158
178
  .finally(() => {
159
179
  httpReqsPending[key] = false;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "4.1.3";
1
+ export declare const SDK_VERSION = "4.2.1";
@@ -1 +1 @@
1
- export const SDK_VERSION = "4.1.3";
1
+ export const SDK_VERSION = "4.2.1";
@@ -1,5 +1,22 @@
1
1
  import type { BuilderBlock } from '../types/builder-block';
2
2
  import type { DeepPartial } from '../types/deep-partial';
3
+ import type { Input } from '../types/input';
4
+ export interface Action {
5
+ name: string;
6
+ inputs?: readonly Input[];
7
+ returnType?: Input;
8
+ action: (options: Record<string, any>) => string;
9
+ /**
10
+ * Is an action for expression (e.g. calculating a binding like a formula
11
+ * to fill a value based on locale) or a function (e.g. something to trigger
12
+ * on an event like add to cart) or either (e.g. a custom code block)
13
+ */
14
+ kind: 'expression' | 'function' | 'any';
15
+ /**
16
+ * Globally unique ID for an action, e.g. "@builder.io:setState"
17
+ */
18
+ id: string;
19
+ }
3
20
  export interface InsertMenuItem {
4
21
  name: string;
5
22
  icon?: string;
@@ -14,3 +31,4 @@ export interface InsertMenuConfig {
14
31
  }
15
32
  export declare function register(type: 'insertMenu', info: InsertMenuConfig): void;
16
33
  export declare function register(type: string, info: any): void;
34
+ export declare function registerAction(action: Action): void;
@@ -29,3 +29,15 @@ export function register(type, info) {
29
29
  }
30
30
  }
31
31
  }
32
+ export function registerAction(action) {
33
+ if (isBrowser()) {
34
+ const actionClone = JSON.parse(JSON.stringify(action));
35
+ if (action.action) {
36
+ actionClone.action = action.action.toString();
37
+ }
38
+ window.parent?.postMessage({
39
+ type: 'builder.registerAction',
40
+ data: actionClone
41
+ }, '*');
42
+ }
43
+ }
@@ -25,7 +25,7 @@ export type { ComponentInfo } from './types/components';
25
25
  export { isEditing } from './functions/is-editing';
26
26
  export { isPreviewing } from './functions/is-previewing';
27
27
  export { createRegisterComponentMessage } from './functions/register-component';
28
- export { register } from './functions/register';
28
+ export { register, registerAction } from './functions/register';
29
29
  export type { InsertMenuConfig, InsertMenuItem } from './functions/register';
30
30
  export { setEditorSettings } from './functions/set-editor-settings';
31
31
  export type { Settings } from './functions/set-editor-settings';
@@ -5,7 +5,7 @@ export * from './index-helpers/top-of-file';
5
5
  export { isEditing } from './functions/is-editing';
6
6
  export { isPreviewing } from './functions/is-previewing';
7
7
  export { createRegisterComponentMessage } from './functions/register-component';
8
- export { register } from './functions/register';
8
+ export { register, registerAction } from './functions/register';
9
9
  export { setEditorSettings } from './functions/set-editor-settings';
10
10
  export { getBuilderSearchParams } from './functions/get-builder-search-params/index';
11
11
  export { track } from './functions/track/index';
@@ -62,13 +62,16 @@ function onSubmit(event) {
62
62
  // TODO: maybe support null
63
63
  const formPairs = Array.from(el.querySelectorAll("input,select,textarea"))
64
64
  .filter((el) => !!el.name)
65
+ .filter((el) => !!el.name &&
66
+ (el.type !== "radio" ||
67
+ el.checked))
65
68
  .map((el) => {
66
69
  let value;
67
70
  const key = el.name;
68
71
  if (el instanceof HTMLInputElement) {
69
72
  if (el.type === "radio") {
70
73
  if (el.checked) {
71
- value = el.name;
74
+ value = el.value;
72
75
  return {
73
76
  key,
74
77
  value,
@@ -126,15 +126,20 @@ function onClick(event) {
126
126
  }
127
127
  function runHttpRequests() {
128
128
  const requests = $builderContextSignal.content?.data?.httpRequests ?? {};
129
- Object.entries(requests).forEach(([key, url]) => {
130
- if (!url)
129
+ Object.entries(requests).forEach(([key, httpRequest]) => {
130
+ if (!httpRequest)
131
131
  return;
132
+ const isCoreRequest = typeof httpRequest === "object" &&
133
+ httpRequest["@type"] === "@builder.io/core:Request";
132
134
  // request already in progress
133
135
  if (httpReqsPending[key])
134
136
  return;
135
137
  // request already completed, and not in edit mode
136
138
  if (httpReqsData[key] && !isEditing())
137
139
  return;
140
+ const url = isCoreRequest
141
+ ? httpRequest.request.url
142
+ : httpRequest;
138
143
  httpReqsPending[key] = true;
139
144
  const evaluatedUrl = url.replace(/{{([^}]+)}}/g, (_match, group) => String(evaluate({
140
145
  code: group,
@@ -143,8 +148,23 @@ function runHttpRequests() {
143
148
  rootState: $builderContextSignal.rootState,
144
149
  rootSetState: $builderContextSignal.rootSetState,
145
150
  })));
146
- logFetch(evaluatedUrl);
147
- fetch(evaluatedUrl)
151
+ const fetchRequestObj = isCoreRequest
152
+ ? {
153
+ url: evaluatedUrl,
154
+ method: httpRequest.request.method,
155
+ headers: httpRequest.request.headers,
156
+ body: httpRequest.request.body,
157
+ }
158
+ : {
159
+ url: evaluatedUrl,
160
+ method: "GET",
161
+ };
162
+ logFetch(JSON.stringify(fetchRequestObj));
163
+ fetch(fetchRequestObj.url, {
164
+ method: fetchRequestObj.method,
165
+ headers: fetchRequestObj.headers,
166
+ body: fetchRequestObj.body,
167
+ })
148
168
  .then((response) => response.json())
149
169
  .then((json) => {
150
170
  mergeNewRootState({
@@ -153,7 +173,7 @@ function runHttpRequests() {
153
173
  httpReqsData[key] = true;
154
174
  })
155
175
  .catch((err) => {
156
- console.error("error fetching dynamic data", url, err);
176
+ console.error("error fetching dynamic data", JSON.stringify(httpRequest), err);
157
177
  })
158
178
  .finally(() => {
159
179
  httpReqsPending[key] = false;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "4.1.3";
1
+ export declare const SDK_VERSION = "4.2.1";
@@ -1 +1 @@
1
- export const SDK_VERSION = "4.1.3";
1
+ export const SDK_VERSION = "4.2.1";
@@ -1,5 +1,22 @@
1
1
  import type { BuilderBlock } from '../types/builder-block';
2
2
  import type { DeepPartial } from '../types/deep-partial';
3
+ import type { Input } from '../types/input';
4
+ export interface Action {
5
+ name: string;
6
+ inputs?: readonly Input[];
7
+ returnType?: Input;
8
+ action: (options: Record<string, any>) => string;
9
+ /**
10
+ * Is an action for expression (e.g. calculating a binding like a formula
11
+ * to fill a value based on locale) or a function (e.g. something to trigger
12
+ * on an event like add to cart) or either (e.g. a custom code block)
13
+ */
14
+ kind: 'expression' | 'function' | 'any';
15
+ /**
16
+ * Globally unique ID for an action, e.g. "@builder.io:setState"
17
+ */
18
+ id: string;
19
+ }
3
20
  export interface InsertMenuItem {
4
21
  name: string;
5
22
  icon?: string;
@@ -14,3 +31,4 @@ export interface InsertMenuConfig {
14
31
  }
15
32
  export declare function register(type: 'insertMenu', info: InsertMenuConfig): void;
16
33
  export declare function register(type: string, info: any): void;
34
+ export declare function registerAction(action: Action): void;
@@ -29,3 +29,15 @@ export function register(type, info) {
29
29
  }
30
30
  }
31
31
  }
32
+ export function registerAction(action) {
33
+ if (isBrowser()) {
34
+ const actionClone = JSON.parse(JSON.stringify(action));
35
+ if (action.action) {
36
+ actionClone.action = action.action.toString();
37
+ }
38
+ window.parent?.postMessage({
39
+ type: 'builder.registerAction',
40
+ data: actionClone
41
+ }, '*');
42
+ }
43
+ }
@@ -25,7 +25,7 @@ export type { ComponentInfo } from './types/components';
25
25
  export { isEditing } from './functions/is-editing';
26
26
  export { isPreviewing } from './functions/is-previewing';
27
27
  export { createRegisterComponentMessage } from './functions/register-component';
28
- export { register } from './functions/register';
28
+ export { register, registerAction } from './functions/register';
29
29
  export type { InsertMenuConfig, InsertMenuItem } from './functions/register';
30
30
  export { setEditorSettings } from './functions/set-editor-settings';
31
31
  export type { Settings } from './functions/set-editor-settings';
@@ -5,7 +5,7 @@ export * from './index-helpers/top-of-file';
5
5
  export { isEditing } from './functions/is-editing';
6
6
  export { isPreviewing } from './functions/is-previewing';
7
7
  export { createRegisterComponentMessage } from './functions/register-component';
8
- export { register } from './functions/register';
8
+ export { register, registerAction } from './functions/register';
9
9
  export { setEditorSettings } from './functions/set-editor-settings';
10
10
  export { getBuilderSearchParams } from './functions/get-builder-search-params/index';
11
11
  export { track } from './functions/track/index';
@@ -62,13 +62,16 @@ function onSubmit(event) {
62
62
  // TODO: maybe support null
63
63
  const formPairs = Array.from(el.querySelectorAll("input,select,textarea"))
64
64
  .filter((el) => !!el.name)
65
+ .filter((el) => !!el.name &&
66
+ (el.type !== "radio" ||
67
+ el.checked))
65
68
  .map((el) => {
66
69
  let value;
67
70
  const key = el.name;
68
71
  if (el instanceof HTMLInputElement) {
69
72
  if (el.type === "radio") {
70
73
  if (el.checked) {
71
- value = el.name;
74
+ value = el.value;
72
75
  return {
73
76
  key,
74
77
  value,
@@ -126,15 +126,20 @@ function onClick(event) {
126
126
  }
127
127
  function runHttpRequests() {
128
128
  const requests = $builderContextSignal.content?.data?.httpRequests ?? {};
129
- Object.entries(requests).forEach(([key, url]) => {
130
- if (!url)
129
+ Object.entries(requests).forEach(([key, httpRequest]) => {
130
+ if (!httpRequest)
131
131
  return;
132
+ const isCoreRequest = typeof httpRequest === "object" &&
133
+ httpRequest["@type"] === "@builder.io/core:Request";
132
134
  // request already in progress
133
135
  if (httpReqsPending[key])
134
136
  return;
135
137
  // request already completed, and not in edit mode
136
138
  if (httpReqsData[key] && !isEditing())
137
139
  return;
140
+ const url = isCoreRequest
141
+ ? httpRequest.request.url
142
+ : httpRequest;
138
143
  httpReqsPending[key] = true;
139
144
  const evaluatedUrl = url.replace(/{{([^}]+)}}/g, (_match, group) => String(evaluate({
140
145
  code: group,
@@ -143,8 +148,23 @@ function runHttpRequests() {
143
148
  rootState: $builderContextSignal.rootState,
144
149
  rootSetState: $builderContextSignal.rootSetState,
145
150
  })));
146
- logFetch(evaluatedUrl);
147
- fetch(evaluatedUrl)
151
+ const fetchRequestObj = isCoreRequest
152
+ ? {
153
+ url: evaluatedUrl,
154
+ method: httpRequest.request.method,
155
+ headers: httpRequest.request.headers,
156
+ body: httpRequest.request.body,
157
+ }
158
+ : {
159
+ url: evaluatedUrl,
160
+ method: "GET",
161
+ };
162
+ logFetch(JSON.stringify(fetchRequestObj));
163
+ fetch(fetchRequestObj.url, {
164
+ method: fetchRequestObj.method,
165
+ headers: fetchRequestObj.headers,
166
+ body: fetchRequestObj.body,
167
+ })
148
168
  .then((response) => response.json())
149
169
  .then((json) => {
150
170
  mergeNewRootState({
@@ -153,7 +173,7 @@ function runHttpRequests() {
153
173
  httpReqsData[key] = true;
154
174
  })
155
175
  .catch((err) => {
156
- console.error("error fetching dynamic data", url, err);
176
+ console.error("error fetching dynamic data", JSON.stringify(httpRequest), err);
157
177
  })
158
178
  .finally(() => {
159
179
  httpReqsPending[key] = false;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "4.1.3";
1
+ export declare const SDK_VERSION = "4.2.1";
@@ -1 +1 @@
1
- export const SDK_VERSION = "4.1.3";
1
+ export const SDK_VERSION = "4.2.1";
@@ -1,5 +1,22 @@
1
1
  import type { BuilderBlock } from '../types/builder-block';
2
2
  import type { DeepPartial } from '../types/deep-partial';
3
+ import type { Input } from '../types/input';
4
+ export interface Action {
5
+ name: string;
6
+ inputs?: readonly Input[];
7
+ returnType?: Input;
8
+ action: (options: Record<string, any>) => string;
9
+ /**
10
+ * Is an action for expression (e.g. calculating a binding like a formula
11
+ * to fill a value based on locale) or a function (e.g. something to trigger
12
+ * on an event like add to cart) or either (e.g. a custom code block)
13
+ */
14
+ kind: 'expression' | 'function' | 'any';
15
+ /**
16
+ * Globally unique ID for an action, e.g. "@builder.io:setState"
17
+ */
18
+ id: string;
19
+ }
3
20
  export interface InsertMenuItem {
4
21
  name: string;
5
22
  icon?: string;
@@ -14,3 +31,4 @@ export interface InsertMenuConfig {
14
31
  }
15
32
  export declare function register(type: 'insertMenu', info: InsertMenuConfig): void;
16
33
  export declare function register(type: string, info: any): void;
34
+ export declare function registerAction(action: Action): void;
@@ -29,3 +29,15 @@ export function register(type, info) {
29
29
  }
30
30
  }
31
31
  }
32
+ export function registerAction(action) {
33
+ if (isBrowser()) {
34
+ const actionClone = JSON.parse(JSON.stringify(action));
35
+ if (action.action) {
36
+ actionClone.action = action.action.toString();
37
+ }
38
+ window.parent?.postMessage({
39
+ type: 'builder.registerAction',
40
+ data: actionClone
41
+ }, '*');
42
+ }
43
+ }
@@ -25,7 +25,7 @@ export type { ComponentInfo } from './types/components';
25
25
  export { isEditing } from './functions/is-editing';
26
26
  export { isPreviewing } from './functions/is-previewing';
27
27
  export { createRegisterComponentMessage } from './functions/register-component';
28
- export { register } from './functions/register';
28
+ export { register, registerAction } from './functions/register';
29
29
  export type { InsertMenuConfig, InsertMenuItem } from './functions/register';
30
30
  export { setEditorSettings } from './functions/set-editor-settings';
31
31
  export type { Settings } from './functions/set-editor-settings';
@@ -5,7 +5,7 @@ export * from './index-helpers/top-of-file';
5
5
  export { isEditing } from './functions/is-editing';
6
6
  export { isPreviewing } from './functions/is-previewing';
7
7
  export { createRegisterComponentMessage } from './functions/register-component';
8
- export { register } from './functions/register';
8
+ export { register, registerAction } from './functions/register';
9
9
  export { setEditorSettings } from './functions/set-editor-settings';
10
10
  export { getBuilderSearchParams } from './functions/get-builder-search-params/index';
11
11
  export { track } from './functions/track/index';
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": "4.1.3",
4
+ "version": "4.2.1",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "lib",
@@ -108,13 +108,19 @@
108
108
  value: File | boolean | number | string | FileList;
109
109
  }[] = Array.from(el.querySelectorAll("input,select,textarea"))
110
110
  .filter((el) => !!(el as HTMLInputElement).name)
111
+ .filter(
112
+ (el) =>
113
+ !!(el as HTMLInputElement).name &&
114
+ ((el as HTMLInputElement).type !== "radio" ||
115
+ (el as HTMLInputElement).checked)
116
+ )
111
117
  .map((el) => {
112
118
  let value: any;
113
119
  const key = (el as HTMLImageElement).name;
114
120
  if (el instanceof HTMLInputElement) {
115
121
  if (el.type === "radio") {
116
122
  if (el.checked) {
117
- value = el.name;
123
+ value = el.value;
118
124
  return {
119
125
  key,
120
126
  value,
@@ -12,6 +12,27 @@
12
12
  setBuilderContextSignal?: (signal: any) => any;
13
13
  children?: any;
14
14
  };
15
+
16
+ interface BuilderRequest {
17
+ "@type": "@builder.io/core:Request";
18
+ request: {
19
+ url: string;
20
+ query?: {
21
+ [key: string]: string;
22
+ };
23
+ headers?: {
24
+ [key: string]: string;
25
+ };
26
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
27
+ body?: any;
28
+ };
29
+ options?: {
30
+ [key: string]: any;
31
+ };
32
+ bindings?: {
33
+ [key: string]: string;
34
+ };
35
+ }
15
36
  </script>
16
37
 
17
38
  <script lang="ts">
@@ -155,44 +176,73 @@
155
176
  }
156
177
  function runHttpRequests() {
157
178
  const requests: {
158
- [key: string]: string;
179
+ [key: string]: string | any;
159
180
  } = $builderContextSignal.content?.data?.httpRequests ?? {};
160
- Object.entries(requests).forEach(([key, url]) => {
161
- if (!url) return;
181
+ Object.entries(requests).forEach(
182
+ ([key, httpRequest]: [string, BuilderRequest | string]) => {
183
+ if (!httpRequest) return;
184
+ const isCoreRequest =
185
+ typeof httpRequest === "object" &&
186
+ httpRequest["@type"] === "@builder.io/core:Request";
162
187
 
163
- // request already in progress
164
- if (httpReqsPending[key]) return;
188
+ // request already in progress
189
+ if (httpReqsPending[key]) return;
165
190
 
166
- // request already completed, and not in edit mode
167
- if (httpReqsData[key] && !isEditing()) return;
168
- httpReqsPending[key] = true;
169
- const evaluatedUrl = url.replace(/{{([^}]+)}}/g, (_match, group) =>
170
- String(
171
- evaluate({
172
- code: group,
173
- context: context || {},
174
- localState: undefined,
175
- rootState: $builderContextSignal.rootState,
176
- rootSetState: $builderContextSignal.rootSetState,
191
+ // request already completed, and not in edit mode
192
+ if (httpReqsData[key] && !isEditing()) return;
193
+ const url = isCoreRequest
194
+ ? httpRequest.request.url
195
+ : (httpRequest as string);
196
+ httpReqsPending[key] = true;
197
+ const evaluatedUrl = url.replace(
198
+ /{{([^}]+)}}/g,
199
+ (_match: string, group: string) =>
200
+ String(
201
+ evaluate({
202
+ code: group,
203
+ context: context || {},
204
+ localState: undefined,
205
+ rootState: $builderContextSignal.rootState,
206
+ rootSetState: $builderContextSignal.rootSetState,
207
+ })
208
+ )
209
+ );
210
+ const fetchRequestObj = isCoreRequest
211
+ ? {
212
+ url: evaluatedUrl,
213
+ method: httpRequest.request.method,
214
+ headers: httpRequest.request.headers,
215
+ body: httpRequest.request.body,
216
+ }
217
+ : {
218
+ url: evaluatedUrl,
219
+ method: "GET",
220
+ };
221
+ logFetch(JSON.stringify(fetchRequestObj));
222
+ fetch(fetchRequestObj.url, {
223
+ method: fetchRequestObj.method,
224
+ headers: fetchRequestObj.headers,
225
+ body: fetchRequestObj.body,
226
+ })
227
+ .then((response) => response.json())
228
+ .then((json) => {
229
+ mergeNewRootState({
230
+ [key]: json,
231
+ });
232
+ httpReqsData[key] = true;
177
233
  })
178
- )
179
- );
180
- logFetch(evaluatedUrl);
181
- fetch(evaluatedUrl)
182
- .then((response) => response.json())
183
- .then((json) => {
184
- mergeNewRootState({
185
- [key]: json,
234
+ .catch((err) => {
235
+ console.error(
236
+ "error fetching dynamic data",
237
+ JSON.stringify(httpRequest),
238
+ err
239
+ );
240
+ })
241
+ .finally(() => {
242
+ httpReqsPending[key] = false;
186
243
  });
187
- httpReqsData[key] = true;
188
- })
189
- .catch((err) => {
190
- console.error("error fetching dynamic data", url, err);
191
- })
192
- .finally(() => {
193
- httpReqsPending[key] = false;
194
- });
195
- });
244
+ }
245
+ );
196
246
  }
197
247
  function emitStateUpdate() {
198
248
  if (isEditing()) {
@@ -1 +1 @@
1
- export const SDK_VERSION = "4.1.3"
1
+ export const SDK_VERSION = "4.2.1"
@@ -1,7 +1,24 @@
1
1
  import type { BuilderBlock } from '../types/builder-block';
2
2
  import type { DeepPartial } from '../types/deep-partial';
3
+ import type { Input } from '../types/input';
3
4
  import { isBrowser } from './is-browser';
4
5
  import { serializeIncludingFunctions } from './register-component';
6
+ export interface Action {
7
+ name: string;
8
+ inputs?: readonly Input[];
9
+ returnType?: Input;
10
+ action: (options: Record<string, any>) => string;
11
+ /**
12
+ * Is an action for expression (e.g. calculating a binding like a formula
13
+ * to fill a value based on locale) or a function (e.g. something to trigger
14
+ * on an event like add to cart) or either (e.g. a custom code block)
15
+ */
16
+ kind: 'expression' | 'function' | 'any';
17
+ /**
18
+ * Globally unique ID for an action, e.g. "@builder.io:setState"
19
+ */
20
+ id: string;
21
+ }
5
22
  export interface InsertMenuItem {
6
23
  name: string;
7
24
  icon?: string;
@@ -45,4 +62,16 @@ export function register(type: string, info: any) {
45
62
  console.debug('Could not postmessage', err);
46
63
  }
47
64
  }
65
+ }
66
+ export function registerAction(action: Action) {
67
+ if (isBrowser()) {
68
+ const actionClone = JSON.parse(JSON.stringify(action));
69
+ if (action.action) {
70
+ actionClone.action = action.action.toString();
71
+ }
72
+ window.parent?.postMessage({
73
+ type: 'builder.registerAction',
74
+ data: actionClone
75
+ }, '*');
76
+ }
48
77
  }
@@ -28,7 +28,7 @@ export type { ComponentInfo } from './types/components';
28
28
  export { isEditing } from './functions/is-editing';
29
29
  export { isPreviewing } from './functions/is-previewing';
30
30
  export { createRegisterComponentMessage } from './functions/register-component';
31
- export { register } from './functions/register';
31
+ export { register, registerAction } from './functions/register';
32
32
  export type { InsertMenuConfig, InsertMenuItem } from './functions/register';
33
33
  export { setEditorSettings } from './functions/set-editor-settings';
34
34
  export type { Settings } from './functions/set-editor-settings';