@bacano/sdk 1.2.2 → 1.2.4
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/CONTENT_TYPE_MANAGEMENT.md +42 -2
- package/FLOWS.md +114 -0
- package/README.md +89 -18
- package/STOREFRONT_FORMS.md +50 -0
- package/STOREFRONT_PAYMENTS.md +231 -0
- package/client.d.ts +9 -1
- package/content-management-types.d.ts +44 -1
- package/content-management.cjs +26 -0
- package/content-management.js +26 -0
- package/flows.d.ts +109 -0
- package/form-conditions.d.ts +6 -0
- package/index.cjs +142 -3
- package/index.d.ts +3 -0
- package/index.js +142 -3
- package/modules/checkout.d.ts +1 -1
- package/modules/content.d.ts +1 -0
- package/package.json +1 -1
- package/react/flow-form.d.ts +9 -0
- package/react/form-scale-control.d.ts +9 -0
- package/react/forms.cjs +260 -65
- package/react/forms.d.ts +1 -0
- package/react/forms.js +254 -59
- package/react.cjs +106 -2
- package/react.js +106 -2
- package/skills/bacano-web/SKILL.md +2 -0
- package/skills/bacano-web/references/storefront.md +2 -0
- package/transport/documents.d.ts +2 -1
- package/types.d.ts +14 -1
|
@@ -2,7 +2,7 @@ import type { FormManagementClient } from "./form-management-types";
|
|
|
2
2
|
export type ContentManagementTypeKind = "entry" | "component";
|
|
3
3
|
export type ContentManagementTypeStatus = "draft" | "active" | "archived";
|
|
4
4
|
export type ContentManagementTypeUsage = "website_content" | "product_additional" | "product_specification";
|
|
5
|
-
export type ContentManagementScope = "content_types:manage" | "content_entries:manage" | "content_media:upload" | "content_entries:publish" | "forms:manage" | "forms:publish";
|
|
5
|
+
export type ContentManagementScope = "content_types:manage" | "content_entries:manage" | "content_media:upload" | "content_entries:publish" | "forms:manage" | "forms:publish" | "product_content:manage";
|
|
6
6
|
export type ContentManagementFieldType = "boolean" | "component" | "date" | "link" | "measure" | "media" | "number" | "reference" | "repeater" | "rich_text" | "rich_text_full" | "select" | "slug" | "text" | "textarea";
|
|
7
7
|
export interface ContentManagementChildFieldInput {
|
|
8
8
|
id?: string | null;
|
|
@@ -68,8 +68,46 @@ export interface ContentManagementContext {
|
|
|
68
68
|
/** @deprecated Use scopes to inspect the complete grant. */
|
|
69
69
|
scope: ContentManagementScope;
|
|
70
70
|
scopes: ContentManagementScope[];
|
|
71
|
+
productIds: string[];
|
|
71
72
|
expiresAt: string;
|
|
72
73
|
}
|
|
74
|
+
export interface ContentManagementProductBlock {
|
|
75
|
+
id: string;
|
|
76
|
+
productId: string;
|
|
77
|
+
contentType: {
|
|
78
|
+
id: string;
|
|
79
|
+
key: string;
|
|
80
|
+
name: string;
|
|
81
|
+
};
|
|
82
|
+
locale: string;
|
|
83
|
+
content: Record<string, unknown>;
|
|
84
|
+
sortOrder: number;
|
|
85
|
+
createdAt: string;
|
|
86
|
+
updatedAt: string;
|
|
87
|
+
}
|
|
88
|
+
export interface ContentManagementProductBlockListInput {
|
|
89
|
+
contentType?: string;
|
|
90
|
+
locale?: string;
|
|
91
|
+
}
|
|
92
|
+
export interface ContentManagementProductBlockCreateInput {
|
|
93
|
+
contentType: string;
|
|
94
|
+
locale?: string;
|
|
95
|
+
content: Record<string, unknown>;
|
|
96
|
+
sortOrder: number;
|
|
97
|
+
}
|
|
98
|
+
export interface ContentManagementProductBlockUpdateInput {
|
|
99
|
+
content: Record<string, unknown>;
|
|
100
|
+
sortOrder: number;
|
|
101
|
+
expectedUpdatedAt: string;
|
|
102
|
+
}
|
|
103
|
+
export interface ContentManagementProductBlockReorderInput {
|
|
104
|
+
locale: string;
|
|
105
|
+
/** Complete ordered list for this product and locale. */
|
|
106
|
+
items: Array<{
|
|
107
|
+
id: string;
|
|
108
|
+
expectedUpdatedAt: string;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
73
111
|
export type ContentManagementEntryStatus = "draft" | "published" | "archived";
|
|
74
112
|
export interface ContentManagementEntryInput {
|
|
75
113
|
contentType: string;
|
|
@@ -262,6 +300,11 @@ export interface ContentManagementClientConfig {
|
|
|
262
300
|
}
|
|
263
301
|
export interface ContentManagementClient extends FormManagementClient {
|
|
264
302
|
getContext(): Promise<ContentManagementContext>;
|
|
303
|
+
listProductBlocks(productId: string, input?: ContentManagementProductBlockListInput): Promise<ContentManagementProductBlock[]>;
|
|
304
|
+
createProductBlock(productId: string, input: ContentManagementProductBlockCreateInput): Promise<ContentManagementProductBlock>;
|
|
305
|
+
updateProductBlock(productId: string, blockId: string, input: ContentManagementProductBlockUpdateInput): Promise<ContentManagementProductBlock>;
|
|
306
|
+
reorderProductBlocks(productId: string, input: ContentManagementProductBlockReorderInput): Promise<ContentManagementProductBlock[]>;
|
|
307
|
+
retireProductBlock(productId: string, blockId: string, expectedUpdatedAt: string): Promise<ContentManagementProductBlock>;
|
|
265
308
|
getReferences(): Promise<ContentManagementReferences>;
|
|
266
309
|
listTypes(): Promise<ContentManagementType[]>;
|
|
267
310
|
getType(identifier: string): Promise<ContentManagementType>;
|
package/content-management.cjs
CHANGED
|
@@ -112,6 +112,13 @@ function mediaListPath(input = {}) {
|
|
|
112
112
|
const query = search.toString();
|
|
113
113
|
return query ? `/media?${query}` : "/media";
|
|
114
114
|
}
|
|
115
|
+
function productBlocksPath(productId, input = {}) {
|
|
116
|
+
const path = `/products/${encodeIdentifier(productId)}/blocks`;
|
|
117
|
+
const search = new URLSearchParams();
|
|
118
|
+
if (input.contentType) search.set("contentType", input.contentType);
|
|
119
|
+
if (input.locale) search.set("locale", input.locale);
|
|
120
|
+
return search.size ? `${path}?${search}` : path;
|
|
121
|
+
}
|
|
115
122
|
function uploadBody(file) {
|
|
116
123
|
if ("arrayBuffer" in file) return file;
|
|
117
124
|
if (file instanceof ArrayBuffer) return file;
|
|
@@ -183,6 +190,25 @@ function createContentManagementClient(config) {
|
|
|
183
190
|
return {
|
|
184
191
|
...createFormManagementMethods(request),
|
|
185
192
|
getContext: () => request("/context"),
|
|
193
|
+
listProductBlocks: (productId, input) => request(
|
|
194
|
+
productBlocksPath(productId, input)
|
|
195
|
+
),
|
|
196
|
+
createProductBlock: (productId, input) => request(productBlocksPath(productId), {
|
|
197
|
+
method: "POST",
|
|
198
|
+
body: JSON.stringify(input)
|
|
199
|
+
}),
|
|
200
|
+
updateProductBlock: (productId, blockId, input) => request(
|
|
201
|
+
`${productBlocksPath(productId)}/${encodeIdentifier(blockId)}`,
|
|
202
|
+
{ method: "PUT", body: JSON.stringify(input) }
|
|
203
|
+
),
|
|
204
|
+
reorderProductBlocks: (productId, input) => request(
|
|
205
|
+
`${productBlocksPath(productId)}/order`,
|
|
206
|
+
{ method: "PUT", body: JSON.stringify(input) }
|
|
207
|
+
),
|
|
208
|
+
retireProductBlock: (productId, blockId, expectedUpdatedAt) => request(
|
|
209
|
+
`${productBlocksPath(productId)}/${encodeIdentifier(blockId)}`,
|
|
210
|
+
{ method: "DELETE", body: JSON.stringify({ expectedUpdatedAt }) }
|
|
211
|
+
),
|
|
186
212
|
getReferences: () => request("/references"),
|
|
187
213
|
listTypes: () => request("/types"),
|
|
188
214
|
getType: (identifier) => request(`/types/${encodeIdentifier(identifier)}`),
|
package/content-management.js
CHANGED
|
@@ -85,6 +85,13 @@ function mediaListPath(input = {}) {
|
|
|
85
85
|
const query = search.toString();
|
|
86
86
|
return query ? `/media?${query}` : "/media";
|
|
87
87
|
}
|
|
88
|
+
function productBlocksPath(productId, input = {}) {
|
|
89
|
+
const path = `/products/${encodeIdentifier(productId)}/blocks`;
|
|
90
|
+
const search = new URLSearchParams();
|
|
91
|
+
if (input.contentType) search.set("contentType", input.contentType);
|
|
92
|
+
if (input.locale) search.set("locale", input.locale);
|
|
93
|
+
return search.size ? `${path}?${search}` : path;
|
|
94
|
+
}
|
|
88
95
|
function uploadBody(file) {
|
|
89
96
|
if ("arrayBuffer" in file) return file;
|
|
90
97
|
if (file instanceof ArrayBuffer) return file;
|
|
@@ -156,6 +163,25 @@ function createContentManagementClient(config) {
|
|
|
156
163
|
return {
|
|
157
164
|
...createFormManagementMethods(request),
|
|
158
165
|
getContext: () => request("/context"),
|
|
166
|
+
listProductBlocks: (productId, input) => request(
|
|
167
|
+
productBlocksPath(productId, input)
|
|
168
|
+
),
|
|
169
|
+
createProductBlock: (productId, input) => request(productBlocksPath(productId), {
|
|
170
|
+
method: "POST",
|
|
171
|
+
body: JSON.stringify(input)
|
|
172
|
+
}),
|
|
173
|
+
updateProductBlock: (productId, blockId, input) => request(
|
|
174
|
+
`${productBlocksPath(productId)}/${encodeIdentifier(blockId)}`,
|
|
175
|
+
{ method: "PUT", body: JSON.stringify(input) }
|
|
176
|
+
),
|
|
177
|
+
reorderProductBlocks: (productId, input) => request(
|
|
178
|
+
`${productBlocksPath(productId)}/order`,
|
|
179
|
+
{ method: "PUT", body: JSON.stringify(input) }
|
|
180
|
+
),
|
|
181
|
+
retireProductBlock: (productId, blockId, expectedUpdatedAt) => request(
|
|
182
|
+
`${productBlocksPath(productId)}/${encodeIdentifier(blockId)}`,
|
|
183
|
+
{ method: "DELETE", body: JSON.stringify({ expectedUpdatedAt }) }
|
|
184
|
+
),
|
|
159
185
|
getReferences: () => request("/references"),
|
|
160
186
|
listTypes: () => request("/types"),
|
|
161
187
|
getType: (identifier) => request(`/types/${encodeIdentifier(identifier)}`),
|
package/flows.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { AccessTokenProvider, WebsiteFormDefinition, WebsiteFormResponseValue } from "./types";
|
|
2
|
+
export interface FlowCaseSummary {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
reference: string;
|
|
6
|
+
status: "open" | "completed" | "rejected";
|
|
7
|
+
flowName: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ParticipantFlowStep {
|
|
10
|
+
id: string;
|
|
11
|
+
kind: "content" | "form" | "task" | "review";
|
|
12
|
+
title: string;
|
|
13
|
+
required: boolean;
|
|
14
|
+
completed: boolean;
|
|
15
|
+
available: boolean;
|
|
16
|
+
canComplete: boolean;
|
|
17
|
+
internal: boolean;
|
|
18
|
+
canReadResponse: boolean;
|
|
19
|
+
completion?: "reference" | "continue" | "confirmation";
|
|
20
|
+
confirmationText?: string;
|
|
21
|
+
instructions?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ParticipantJourney extends FlowCaseSummary {
|
|
24
|
+
revision: number;
|
|
25
|
+
flowRevision: number;
|
|
26
|
+
stageId: string;
|
|
27
|
+
dueDate: string | null;
|
|
28
|
+
stages: Array<{
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
current: boolean;
|
|
32
|
+
/** Presentation only; availability and completion remain server-authoritative. */
|
|
33
|
+
presentation?: "step_by_step" | "single_view";
|
|
34
|
+
steps: ParticipantFlowStep[];
|
|
35
|
+
}>;
|
|
36
|
+
messages: Array<{
|
|
37
|
+
createdAt: string;
|
|
38
|
+
message: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
export interface FlowPublishedForm {
|
|
42
|
+
name: string;
|
|
43
|
+
version: number;
|
|
44
|
+
definitionHash: string;
|
|
45
|
+
definition: WebsiteFormDefinition;
|
|
46
|
+
/** Own previous answers, scoped and filtered by the backend for a correction. */
|
|
47
|
+
initialValues?: Record<string, WebsiteFormResponseValue>;
|
|
48
|
+
correction?: {
|
|
49
|
+
attempt: number;
|
|
50
|
+
formChanged: boolean;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export interface FlowContentResource {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
content: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
export interface FlowResponse {
|
|
59
|
+
snapshot: Array<{
|
|
60
|
+
key: string;
|
|
61
|
+
label: string;
|
|
62
|
+
displayValue: unknown;
|
|
63
|
+
}>;
|
|
64
|
+
attempt: number;
|
|
65
|
+
submittedAt: string;
|
|
66
|
+
}
|
|
67
|
+
export interface FlowParticipantCommand {
|
|
68
|
+
stepId: string;
|
|
69
|
+
revision: number;
|
|
70
|
+
flowRevision: number;
|
|
71
|
+
idempotencyKey: string;
|
|
72
|
+
operation: "complete_content" | "complete_task" | "submit_form";
|
|
73
|
+
confirmed?: boolean;
|
|
74
|
+
submission?: {
|
|
75
|
+
formVersion: number;
|
|
76
|
+
definitionHash: string;
|
|
77
|
+
values: Record<string, WebsiteFormResponseValue>;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export interface FlowsClientConfig {
|
|
81
|
+
apiUrl: string;
|
|
82
|
+
getAccessToken?: AccessTokenProvider;
|
|
83
|
+
websiteSlug?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface FlowDemoSession {
|
|
86
|
+
token: string;
|
|
87
|
+
name: string;
|
|
88
|
+
expiresAt: string;
|
|
89
|
+
}
|
|
90
|
+
/** Gateway only. Tokens are supplied per request; this client stores no credentials. */
|
|
91
|
+
export declare function createFlowsClient(config: FlowsClientConfig): {
|
|
92
|
+
/** Only the explicitly enabled local demo gateway accepts these credentials. */
|
|
93
|
+
localDemoLogin: (email: string, password: string) => Promise<FlowDemoSession>;
|
|
94
|
+
logout: () => Promise<{
|
|
95
|
+
success: boolean;
|
|
96
|
+
}>;
|
|
97
|
+
listCases: () => Promise<FlowCaseSummary[]>;
|
|
98
|
+
getJourney: (caseId: string) => Promise<ParticipantJourney>;
|
|
99
|
+
getContent: (caseId: string, stepId: string) => Promise<FlowContentResource[]>;
|
|
100
|
+
getForm: (caseId: string, stepId: string) => Promise<FlowPublishedForm>;
|
|
101
|
+
getResponse: (caseId: string, stepId: string) => Promise<FlowResponse>;
|
|
102
|
+
getFile: (caseId: string, stepId: string, fileId: string) => Promise<Blob>;
|
|
103
|
+
act: (caseId: string, command: FlowParticipantCommand) => Promise<{
|
|
104
|
+
caseId: string;
|
|
105
|
+
revision: number;
|
|
106
|
+
responseId: string | null;
|
|
107
|
+
}>;
|
|
108
|
+
};
|
|
109
|
+
export type FlowsClient = ReturnType<typeof createFlowsClient>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WebsiteFormDefinition, WebsiteFormField } from "./types";
|
|
2
|
+
export declare function formRootFields(definition: WebsiteFormDefinition): WebsiteFormField[];
|
|
3
|
+
/** Unselected branches do not participate in validation or submissions. */
|
|
4
|
+
export declare function visibleFormFields(fields: WebsiteFormField[], values: Record<string, unknown>): WebsiteFormField[];
|
|
5
|
+
export declare function allFormFields(fields: WebsiteFormField[]): WebsiteFormField[];
|
|
6
|
+
export declare function activeFormValues<T>(definition: WebsiteFormDefinition, values: Record<string, T>): Record<string, T>;
|
package/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
RateLimitError: () => RateLimitError,
|
|
31
31
|
WEBSITE_MARKETING_CONTACT_PLACEMENTS: () => WEBSITE_MARKETING_CONTACT_PLACEMENTS,
|
|
32
32
|
WebsiteError: () => WebsiteError,
|
|
33
|
+
activeFormValues: () => activeFormValues,
|
|
33
34
|
buildStorageContentMediaUrls: () => buildStorageContentMediaUrls,
|
|
34
35
|
buildStorageFileUrl: () => buildStorageFileUrl,
|
|
35
36
|
buildStorageMediaUrls: () => buildStorageMediaUrls,
|
|
@@ -37,7 +38,9 @@ __export(index_exports, {
|
|
|
37
38
|
buildStorageTransformedFileUrl: () => buildStorageTransformedFileUrl,
|
|
38
39
|
captureWebsiteMarketingAttribution: () => captureWebsiteMarketingAttribution,
|
|
39
40
|
createBacanoClient: () => createBacanoClient,
|
|
41
|
+
createFlowsClient: () => createFlowsClient,
|
|
40
42
|
createWebsiteMarketingRuntime: () => createWebsiteMarketingRuntime,
|
|
43
|
+
formRootFields: () => formRootFields,
|
|
41
44
|
formatMediaSrcSet: () => formatMediaSrcSet,
|
|
42
45
|
getAllowedMarketingParameters: () => getAllowedMarketingParameters,
|
|
43
46
|
getContentEntryLocatorAttributes: () => getContentEntryLocatorAttributes,
|
|
@@ -51,7 +54,8 @@ __export(index_exports, {
|
|
|
51
54
|
getWebsiteMarketingAttribution: () => getWebsiteMarketingAttribution,
|
|
52
55
|
getWebsitePublicConfig: () => getWebsitePublicConfig,
|
|
53
56
|
resolveProductPricing: () => resolveProductPricing,
|
|
54
|
-
sanitizeMarketingUrl: () => sanitizeMarketingUrl
|
|
57
|
+
sanitizeMarketingUrl: () => sanitizeMarketingUrl,
|
|
58
|
+
visibleFormFields: () => visibleFormFields
|
|
55
59
|
});
|
|
56
60
|
module.exports = __toCommonJS(index_exports);
|
|
57
61
|
|
|
@@ -110,6 +114,52 @@ var GraphQLRequestError = class extends WebsiteError {
|
|
|
110
114
|
}
|
|
111
115
|
};
|
|
112
116
|
|
|
117
|
+
// libs/sdk/src/flows.ts
|
|
118
|
+
function createFlowsClient(config) {
|
|
119
|
+
const base = config.apiUrl.replace(/\/+$/, "") + "/api/v1/website/flows";
|
|
120
|
+
async function request(path, body, binary = false) {
|
|
121
|
+
const token = await config.getAccessToken?.();
|
|
122
|
+
const response = await fetch(base + path, {
|
|
123
|
+
method: body === void 0 ? "GET" : "POST",
|
|
124
|
+
cache: "no-store",
|
|
125
|
+
headers: {
|
|
126
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
127
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
128
|
+
...config.websiteSlug ? { "x-bacano-website-slug": config.websiteSlug } : {}
|
|
129
|
+
},
|
|
130
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
const result = await response.json().catch(() => ({ error: "FLOW_REQUEST_FAILED" }));
|
|
134
|
+
throw new WebsiteError(
|
|
135
|
+
result.error ?? "FLOW_REQUEST_FAILED",
|
|
136
|
+
result.error ?? "FLOW_REQUEST_FAILED"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
return binary ? await response.blob() : await response.json();
|
|
140
|
+
}
|
|
141
|
+
const stepPath = (caseId, stepId) => `/cases/${encodeURIComponent(caseId)}/steps/${encodeURIComponent(stepId)}`;
|
|
142
|
+
return {
|
|
143
|
+
/** Only the explicitly enabled local demo gateway accepts these credentials. */
|
|
144
|
+
localDemoLogin: (email, password) => request("/local-session", { email, password }),
|
|
145
|
+
logout: () => request("/logout", {}),
|
|
146
|
+
listCases: () => request("/cases"),
|
|
147
|
+
getJourney: (caseId) => request(`/cases/${encodeURIComponent(caseId)}`),
|
|
148
|
+
getContent: (caseId, stepId) => request(stepPath(caseId, stepId) + "/content"),
|
|
149
|
+
getForm: (caseId, stepId) => request(stepPath(caseId, stepId) + "/form"),
|
|
150
|
+
getResponse: (caseId, stepId) => request(stepPath(caseId, stepId) + "/response"),
|
|
151
|
+
getFile: (caseId, stepId, fileId) => request(
|
|
152
|
+
stepPath(caseId, stepId) + `/files/${encodeURIComponent(fileId)}`,
|
|
153
|
+
void 0,
|
|
154
|
+
true
|
|
155
|
+
),
|
|
156
|
+
act: (caseId, command) => request(
|
|
157
|
+
`/cases/${encodeURIComponent(caseId)}/actions`,
|
|
158
|
+
command
|
|
159
|
+
)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
113
163
|
// libs/sdk/src/media.ts
|
|
114
164
|
var DEFAULT_RESPONSIVE_WIDTHS = [240, 384, 640, 960, 1400];
|
|
115
165
|
var CONTENT_HERO_WIDTHS = [640, 960, 1400, 1920, 2560];
|
|
@@ -1364,6 +1414,35 @@ var WEBSITE_GET_PRODUCT_CONTENT = (
|
|
|
1364
1414
|
}
|
|
1365
1415
|
`
|
|
1366
1416
|
);
|
|
1417
|
+
var WEBSITE_GET_PRODUCT_CONTENT_BATCH = (
|
|
1418
|
+
/* GraphQL */
|
|
1419
|
+
`
|
|
1420
|
+
mutation WebsiteGetProductContentBatch(
|
|
1421
|
+
$websiteId: uuid!
|
|
1422
|
+
$productIds: [uuid!]!
|
|
1423
|
+
$locale: String
|
|
1424
|
+
) {
|
|
1425
|
+
result: websiteGetProductContentBatch(
|
|
1426
|
+
website_id: $websiteId
|
|
1427
|
+
product_ids: $productIds
|
|
1428
|
+
locale: $locale
|
|
1429
|
+
) {
|
|
1430
|
+
success
|
|
1431
|
+
errors
|
|
1432
|
+
blocks {
|
|
1433
|
+
id
|
|
1434
|
+
product_id
|
|
1435
|
+
locale
|
|
1436
|
+
content_json
|
|
1437
|
+
resolved_fields
|
|
1438
|
+
sort_order
|
|
1439
|
+
updated_at
|
|
1440
|
+
content_type { id key name kind }
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
`
|
|
1445
|
+
);
|
|
1367
1446
|
var CHECK_AVAILABILITY = (
|
|
1368
1447
|
/* GraphQL */
|
|
1369
1448
|
`
|
|
@@ -2240,7 +2319,7 @@ var RECONCILE_PAYMENT_SESSION = (
|
|
|
2240
2319
|
$orderId: uuid!
|
|
2241
2320
|
$publicOrderToken: String!
|
|
2242
2321
|
$paymentSessionId: uuid!
|
|
2243
|
-
$gatewayTransactionId: String
|
|
2322
|
+
$gatewayTransactionId: String
|
|
2244
2323
|
) {
|
|
2245
2324
|
websiteReconcilePaymentSession(
|
|
2246
2325
|
order_id: $orderId
|
|
@@ -5732,6 +5811,33 @@ function createContentModule(graphqlUrl, getHeaders, getContext, storageUrl) {
|
|
|
5732
5811
|
return (data.result.blocks ?? []).map(
|
|
5733
5812
|
(block) => mapProductContentBlock(block, storageUrl)
|
|
5734
5813
|
);
|
|
5814
|
+
},
|
|
5815
|
+
async getForProducts(productIds, opts) {
|
|
5816
|
+
const uniqueIds = [...new Set(productIds.map((id) => id.toLowerCase()))];
|
|
5817
|
+
const blocksByProduct = Object.fromEntries(uniqueIds.map((id) => [id, []]));
|
|
5818
|
+
if (uniqueIds.length === 0) return blocksByProduct;
|
|
5819
|
+
const ctx = getContext();
|
|
5820
|
+
for (let start = 0; start < uniqueIds.length; start += 50) {
|
|
5821
|
+
const batch = uniqueIds.slice(start, start + 50);
|
|
5822
|
+
const data = await executeGraphQL(
|
|
5823
|
+
graphqlUrl,
|
|
5824
|
+
WEBSITE_GET_PRODUCT_CONTENT_BATCH,
|
|
5825
|
+
{
|
|
5826
|
+
websiteId: ctx.websiteId,
|
|
5827
|
+
productIds: batch,
|
|
5828
|
+
locale: opts?.locale ?? DEFAULT_LOCALE
|
|
5829
|
+
},
|
|
5830
|
+
getHeaders
|
|
5831
|
+
);
|
|
5832
|
+
if (!data.result?.success) continue;
|
|
5833
|
+
for (const block of data.result.blocks ?? []) {
|
|
5834
|
+
const id = block.product_id.toLowerCase();
|
|
5835
|
+
if (Object.prototype.hasOwnProperty.call(blocksByProduct, id)) {
|
|
5836
|
+
blocksByProduct[id].push(mapProductContentBlock(block, storageUrl));
|
|
5837
|
+
}
|
|
5838
|
+
}
|
|
5839
|
+
}
|
|
5840
|
+
return blocksByProduct;
|
|
5735
5841
|
}
|
|
5736
5842
|
};
|
|
5737
5843
|
}
|
|
@@ -7064,6 +7170,7 @@ function createBacanoClient(config) {
|
|
|
7064
7170
|
await initialization;
|
|
7065
7171
|
},
|
|
7066
7172
|
getContext,
|
|
7173
|
+
flows: createFlowsClient(config),
|
|
7067
7174
|
auth: {
|
|
7068
7175
|
async getAccessToken() {
|
|
7069
7176
|
return config.getAccessToken ? await config.getAccessToken() : null;
|
|
@@ -7096,7 +7203,8 @@ function createBacanoClient(config) {
|
|
|
7096
7203
|
getByKey: contentModule.getByKey.bind(contentModule),
|
|
7097
7204
|
getByCategory: contentModule.getByCategory.bind(contentModule),
|
|
7098
7205
|
getByTag: contentModule.getByTag.bind(contentModule),
|
|
7099
|
-
getForProduct: contentModule.getForProduct.bind(contentModule)
|
|
7206
|
+
getForProduct: contentModule.getForProduct.bind(contentModule),
|
|
7207
|
+
getForProducts: contentModule.getForProducts.bind(contentModule)
|
|
7100
7208
|
},
|
|
7101
7209
|
forms: {
|
|
7102
7210
|
getDefinition: formsModule.getDefinition.bind(formsModule),
|
|
@@ -7163,3 +7271,34 @@ function getContentEntryLocatorAttributes(entry) {
|
|
|
7163
7271
|
"data-bacano-entry-name": entry.name.trim() || key
|
|
7164
7272
|
};
|
|
7165
7273
|
}
|
|
7274
|
+
|
|
7275
|
+
// libs/sdk/src/form-conditions.ts
|
|
7276
|
+
function formRootFields(definition) {
|
|
7277
|
+
return [
|
|
7278
|
+
...definition.fields,
|
|
7279
|
+
...definition.sections.flatMap((section) => section.fields),
|
|
7280
|
+
...definition.steps.flatMap((step) => [
|
|
7281
|
+
...step.fields,
|
|
7282
|
+
...step.sections.flatMap((section) => section.fields)
|
|
7283
|
+
])
|
|
7284
|
+
];
|
|
7285
|
+
}
|
|
7286
|
+
function visibleFormFields(fields, values) {
|
|
7287
|
+
return fields.flatMap((field) => [
|
|
7288
|
+
field,
|
|
7289
|
+
...visibleFormFields(
|
|
7290
|
+
field.branches?.find((branch) => branch.value === values[field.key])?.fields ?? [],
|
|
7291
|
+
values
|
|
7292
|
+
)
|
|
7293
|
+
]);
|
|
7294
|
+
}
|
|
7295
|
+
function activeFormValues(definition, values) {
|
|
7296
|
+
const keys = new Set(
|
|
7297
|
+
visibleFormFields(formRootFields(definition), values).map(
|
|
7298
|
+
(field) => field.key
|
|
7299
|
+
)
|
|
7300
|
+
);
|
|
7301
|
+
return Object.fromEntries(
|
|
7302
|
+
Object.entries(values).filter(([key]) => keys.has(key))
|
|
7303
|
+
);
|
|
7304
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export { createBacanoClient } from "./client";
|
|
|
3
3
|
export type { ContentEntryLocatorAttributes, ContentEntryLocatorSource, } from "./content-entry-locator";
|
|
4
4
|
export { CONTENT_ENTRY_LOCATOR_SELECTOR, CONTENT_ENTRY_LOCATOR_VERSION, getContentEntryLocatorAttributes, } from "./content-entry-locator";
|
|
5
5
|
export { AuthError, CheckoutError, GraphQLRequestError, NotInitializedError, RateLimitError, WebsiteError, } from "./errors";
|
|
6
|
+
export type { FlowCaseSummary, FlowContentResource, FlowDemoSession, FlowParticipantCommand, FlowPublishedForm, FlowResponse, FlowsClient, FlowsClientConfig, ParticipantFlowStep, ParticipantJourney, } from "./flows";
|
|
7
|
+
export { createFlowsClient } from "./flows";
|
|
8
|
+
export { activeFormValues, formRootFields, visibleFormFields, } from "./form-conditions";
|
|
6
9
|
export type { WebsiteAdvertisingConsent, WebsiteMarketingAttribution, WebsiteMarketingBrowserEvent, WebsiteMarketingBrowserEventName, WebsiteMarketingContactPlacement, WebsiteMarketingDiagnostic, WebsiteMarketingItem, WebsiteMarketingRuntime, WebsiteMarketingRuntimeOptions, WebsiteMarketingScriptLoadStrategy, WebsiteMarketingTouchpoint, } from "./marketing";
|
|
7
10
|
export { captureWebsiteMarketingAttribution, createWebsiteMarketingRuntime, getAllowedMarketingParameters, getWebsiteMarketingAttribution, MARKETING_SCHEMA_VERSION, sanitizeMarketingUrl, WEBSITE_MARKETING_CONTACT_PLACEMENTS, } from "./marketing";
|
|
8
11
|
export type { MediaResponsiveSource, MediaResponsiveSourceOptions, MediaTransformFormat, MediaTransformOptions, MediaUrlVariant, } from "./media";
|