@bacano/sdk 1.2.1 → 1.2.3
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/FLOWS.md +114 -0
- package/README.md +93 -18
- package/STOREFRONT_FORMS.md +50 -0
- package/STOREFRONT_MARKETING.md +58 -2
- package/STOREFRONT_PAYMENTS.md +231 -0
- package/client.d.ts +8 -1
- package/flows.d.ts +109 -0
- package/form-conditions.d.ts +6 -0
- package/index.cjs +153 -4
- package/index.d.ts +3 -0
- package/index.js +153 -4
- package/marketing/gtm.d.ts +6 -0
- package/modules/checkout.d.ts +1 -1
- 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 +117 -3
- package/react.js +117 -3
- package/skills/bacano-web/SKILL.md +2 -0
- package/skills/bacano-web/references/storefront.md +2 -0
- package/transport/documents.d.ts +1 -1
- package/types.d.ts +18 -1
package/react.cjs
CHANGED
|
@@ -1998,7 +1998,7 @@ var RECONCILE_PAYMENT_SESSION = (
|
|
|
1998
1998
|
$orderId: uuid!
|
|
1999
1999
|
$publicOrderToken: String!
|
|
2000
2000
|
$paymentSessionId: uuid!
|
|
2001
|
-
$gatewayTransactionId: String
|
|
2001
|
+
$gatewayTransactionId: String
|
|
2002
2002
|
) {
|
|
2003
2003
|
websiteReconcilePaymentSession(
|
|
2004
2004
|
order_id: $orderId
|
|
@@ -5105,6 +5105,61 @@ function matchesCanonicalMarketingHost(canonicalDomain, currentHostname) {
|
|
|
5105
5105
|
}
|
|
5106
5106
|
}
|
|
5107
5107
|
|
|
5108
|
+
// libs/sdk/src/marketing/gtm.ts
|
|
5109
|
+
var CONTAINER_ID = /^GTM-[A-Z0-9]{4,32}$/;
|
|
5110
|
+
var preparedQueues = /* @__PURE__ */ new WeakMap();
|
|
5111
|
+
function prepareGtm(containerId) {
|
|
5112
|
+
const target = marketingWindow();
|
|
5113
|
+
if (!target || !CONTAINER_ID.test(containerId)) return;
|
|
5114
|
+
target.dataLayer ??= [];
|
|
5115
|
+
const containers = preparedQueues.get(target.dataLayer) ?? /* @__PURE__ */ new Set();
|
|
5116
|
+
if (containers.has(containerId)) return;
|
|
5117
|
+
target.dataLayer.push({ "gtm.start": Date.now(), event: "gtm.js" });
|
|
5118
|
+
containers.add(containerId);
|
|
5119
|
+
preparedQueues.set(target.dataLayer, containers);
|
|
5120
|
+
}
|
|
5121
|
+
function loadGtmScript(containerId, onError) {
|
|
5122
|
+
const target = marketingWindow();
|
|
5123
|
+
if (!target || typeof document === "undefined" || !CONTAINER_ID.test(containerId))
|
|
5124
|
+
return;
|
|
5125
|
+
const id = `bacano-gtm-${containerId}`;
|
|
5126
|
+
if (document.getElementById(id)) return;
|
|
5127
|
+
prepareGtm(containerId);
|
|
5128
|
+
const script = document.createElement("script");
|
|
5129
|
+
script.id = id;
|
|
5130
|
+
script.async = true;
|
|
5131
|
+
script.src = `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(containerId)}`;
|
|
5132
|
+
script.referrerPolicy = "strict-origin-when-cross-origin";
|
|
5133
|
+
script.onerror = () => onError();
|
|
5134
|
+
document.head.appendChild(script);
|
|
5135
|
+
}
|
|
5136
|
+
function sendGtm(event) {
|
|
5137
|
+
const target = marketingWindow();
|
|
5138
|
+
if (!target?.dataLayer) return;
|
|
5139
|
+
target.dataLayer.push({ bacano: null });
|
|
5140
|
+
target.dataLayer.push({
|
|
5141
|
+
event: `bacano_${event.eventName}`,
|
|
5142
|
+
bacano: {
|
|
5143
|
+
schema_version: event.schemaVersion,
|
|
5144
|
+
event_name: event.eventName,
|
|
5145
|
+
event_id: event.eventId,
|
|
5146
|
+
...interactionParameters(event),
|
|
5147
|
+
page_location: event.pageLocation,
|
|
5148
|
+
currency: event.currency,
|
|
5149
|
+
value: event.value,
|
|
5150
|
+
items: mapGa4Items(event.items),
|
|
5151
|
+
item_list_id: event.itemListId,
|
|
5152
|
+
item_list_name: event.itemListName,
|
|
5153
|
+
shipping_tier: event.shippingTier,
|
|
5154
|
+
payment_type: event.paymentType,
|
|
5155
|
+
method: event.contactMethod,
|
|
5156
|
+
contact_placement: event.eventName === "contact" && WEBSITE_MARKETING_CONTACT_PLACEMENTS.some(
|
|
5157
|
+
(value) => value === event.contactPlacement
|
|
5158
|
+
) ? event.contactPlacement : void 0
|
|
5159
|
+
}
|
|
5160
|
+
});
|
|
5161
|
+
}
|
|
5162
|
+
|
|
5108
5163
|
// libs/sdk/src/marketing/runtime.ts
|
|
5109
5164
|
function createWebsiteMarketingRuntime(options) {
|
|
5110
5165
|
let destroyed = false;
|
|
@@ -5125,7 +5180,7 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5125
5180
|
target.location.hostname
|
|
5126
5181
|
)
|
|
5127
5182
|
) && Boolean(
|
|
5128
|
-
options.config.destinations.ga4 || options.config.destinations.meta || options.config.destinations.clarity
|
|
5183
|
+
options.config.destinations.ga4 || options.config.destinations.meta || options.config.destinations.clarity || options.config.destinations.gtm
|
|
5129
5184
|
);
|
|
5130
5185
|
if (!enabled)
|
|
5131
5186
|
diagnostic({
|
|
@@ -5166,6 +5221,10 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5166
5221
|
const { projectId } = options.config.destinations.clarity;
|
|
5167
5222
|
guard("Clarity", () => prepareClarity(projectId));
|
|
5168
5223
|
}
|
|
5224
|
+
if (options.config.destinations.gtm) {
|
|
5225
|
+
const { containerId } = options.config.destinations.gtm;
|
|
5226
|
+
guard("GTM", () => prepareGtm(containerId));
|
|
5227
|
+
}
|
|
5169
5228
|
cancelScheduledLoad = scheduleScriptLoad(() => {
|
|
5170
5229
|
if (destroyed) return;
|
|
5171
5230
|
if (options.config.destinations.ga4) {
|
|
@@ -5181,6 +5240,10 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5181
5240
|
() => loadClarityScript(projectId, scriptError("Clarity"))
|
|
5182
5241
|
);
|
|
5183
5242
|
}
|
|
5243
|
+
if (options.config.destinations.gtm) {
|
|
5244
|
+
const { containerId } = options.config.destinations.gtm;
|
|
5245
|
+
guard("GTM", () => loadGtmScript(containerId, scriptError("GTM")));
|
|
5246
|
+
}
|
|
5184
5247
|
}, options.scriptLoadStrategy);
|
|
5185
5248
|
captureWebsiteMarketingAttribution(
|
|
5186
5249
|
options.websiteId,
|
|
@@ -5300,6 +5363,9 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5300
5363
|
if (options.config.destinations.clarity) {
|
|
5301
5364
|
dispatch("Clarity", () => sendClarityEvent(event.eventName));
|
|
5302
5365
|
}
|
|
5366
|
+
if (options.config.destinations.gtm && /^GTM-[A-Z0-9]{4,32}$/.test(options.config.destinations.gtm.containerId)) {
|
|
5367
|
+
dispatch("GTM", () => sendGtm(event));
|
|
5368
|
+
}
|
|
5303
5369
|
},
|
|
5304
5370
|
captureAttribution() {
|
|
5305
5371
|
if (!enabled || destroyed) return null;
|
|
@@ -5392,6 +5458,52 @@ function BacanoMarketingProvider({
|
|
|
5392
5458
|
// libs/sdk/src/react/provider.tsx
|
|
5393
5459
|
var import_react6 = require("react");
|
|
5394
5460
|
|
|
5461
|
+
// libs/sdk/src/flows.ts
|
|
5462
|
+
function createFlowsClient(config) {
|
|
5463
|
+
const base = config.apiUrl.replace(/\/+$/, "") + "/api/v1/website/flows";
|
|
5464
|
+
async function request(path, body, binary = false) {
|
|
5465
|
+
const token = await config.getAccessToken?.();
|
|
5466
|
+
const response = await fetch(base + path, {
|
|
5467
|
+
method: body === void 0 ? "GET" : "POST",
|
|
5468
|
+
cache: "no-store",
|
|
5469
|
+
headers: {
|
|
5470
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
5471
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
5472
|
+
...config.websiteSlug ? { "x-bacano-website-slug": config.websiteSlug } : {}
|
|
5473
|
+
},
|
|
5474
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
5475
|
+
});
|
|
5476
|
+
if (!response.ok) {
|
|
5477
|
+
const result = await response.json().catch(() => ({ error: "FLOW_REQUEST_FAILED" }));
|
|
5478
|
+
throw new WebsiteError(
|
|
5479
|
+
result.error ?? "FLOW_REQUEST_FAILED",
|
|
5480
|
+
result.error ?? "FLOW_REQUEST_FAILED"
|
|
5481
|
+
);
|
|
5482
|
+
}
|
|
5483
|
+
return binary ? await response.blob() : await response.json();
|
|
5484
|
+
}
|
|
5485
|
+
const stepPath = (caseId, stepId) => `/cases/${encodeURIComponent(caseId)}/steps/${encodeURIComponent(stepId)}`;
|
|
5486
|
+
return {
|
|
5487
|
+
/** Only the explicitly enabled local demo gateway accepts these credentials. */
|
|
5488
|
+
localDemoLogin: (email, password) => request("/local-session", { email, password }),
|
|
5489
|
+
logout: () => request("/logout", {}),
|
|
5490
|
+
listCases: () => request("/cases"),
|
|
5491
|
+
getJourney: (caseId) => request(`/cases/${encodeURIComponent(caseId)}`),
|
|
5492
|
+
getContent: (caseId, stepId) => request(stepPath(caseId, stepId) + "/content"),
|
|
5493
|
+
getForm: (caseId, stepId) => request(stepPath(caseId, stepId) + "/form"),
|
|
5494
|
+
getResponse: (caseId, stepId) => request(stepPath(caseId, stepId) + "/response"),
|
|
5495
|
+
getFile: (caseId, stepId, fileId) => request(
|
|
5496
|
+
stepPath(caseId, stepId) + `/files/${encodeURIComponent(fileId)}`,
|
|
5497
|
+
void 0,
|
|
5498
|
+
true
|
|
5499
|
+
),
|
|
5500
|
+
act: (caseId, command) => request(
|
|
5501
|
+
`/cases/${encodeURIComponent(caseId)}/actions`,
|
|
5502
|
+
command
|
|
5503
|
+
)
|
|
5504
|
+
};
|
|
5505
|
+
}
|
|
5506
|
+
|
|
5395
5507
|
// libs/sdk/src/modules/auth.ts
|
|
5396
5508
|
function createAuthHeaders(accessToken) {
|
|
5397
5509
|
return accessToken ? { Authorization: `Bearer ${accessToken}` } : {};
|
|
@@ -5574,7 +5686,8 @@ async function getWebsitePublicConfig(options) {
|
|
|
5574
5686
|
pixelId: marketing.destinations.meta.pixel_id,
|
|
5575
5687
|
diagnosticMode: marketing.destinations.meta.diagnostic_mode ?? false
|
|
5576
5688
|
} : null,
|
|
5577
|
-
clarity: marketing.destinations.clarity ? { projectId: marketing.destinations.clarity.project_id } : null
|
|
5689
|
+
clarity: marketing.destinations.clarity ? { projectId: marketing.destinations.clarity.project_id } : null,
|
|
5690
|
+
...marketing.destinations.gtm ? { gtm: { containerId: marketing.destinations.gtm.container_id } } : {}
|
|
5578
5691
|
}
|
|
5579
5692
|
},
|
|
5580
5693
|
legal: {
|
|
@@ -7415,6 +7528,7 @@ function createBacanoClient(config) {
|
|
|
7415
7528
|
await initialization;
|
|
7416
7529
|
},
|
|
7417
7530
|
getContext,
|
|
7531
|
+
flows: createFlowsClient(config),
|
|
7418
7532
|
auth: {
|
|
7419
7533
|
async getAccessToken() {
|
|
7420
7534
|
return config.getAccessToken ? await config.getAccessToken() : null;
|
package/react.js
CHANGED
|
@@ -1941,7 +1941,7 @@ var RECONCILE_PAYMENT_SESSION = (
|
|
|
1941
1941
|
$orderId: uuid!
|
|
1942
1942
|
$publicOrderToken: String!
|
|
1943
1943
|
$paymentSessionId: uuid!
|
|
1944
|
-
$gatewayTransactionId: String
|
|
1944
|
+
$gatewayTransactionId: String
|
|
1945
1945
|
) {
|
|
1946
1946
|
websiteReconcilePaymentSession(
|
|
1947
1947
|
order_id: $orderId
|
|
@@ -5052,6 +5052,61 @@ function matchesCanonicalMarketingHost(canonicalDomain, currentHostname) {
|
|
|
5052
5052
|
}
|
|
5053
5053
|
}
|
|
5054
5054
|
|
|
5055
|
+
// libs/sdk/src/marketing/gtm.ts
|
|
5056
|
+
var CONTAINER_ID = /^GTM-[A-Z0-9]{4,32}$/;
|
|
5057
|
+
var preparedQueues = /* @__PURE__ */ new WeakMap();
|
|
5058
|
+
function prepareGtm(containerId) {
|
|
5059
|
+
const target = marketingWindow();
|
|
5060
|
+
if (!target || !CONTAINER_ID.test(containerId)) return;
|
|
5061
|
+
target.dataLayer ??= [];
|
|
5062
|
+
const containers = preparedQueues.get(target.dataLayer) ?? /* @__PURE__ */ new Set();
|
|
5063
|
+
if (containers.has(containerId)) return;
|
|
5064
|
+
target.dataLayer.push({ "gtm.start": Date.now(), event: "gtm.js" });
|
|
5065
|
+
containers.add(containerId);
|
|
5066
|
+
preparedQueues.set(target.dataLayer, containers);
|
|
5067
|
+
}
|
|
5068
|
+
function loadGtmScript(containerId, onError) {
|
|
5069
|
+
const target = marketingWindow();
|
|
5070
|
+
if (!target || typeof document === "undefined" || !CONTAINER_ID.test(containerId))
|
|
5071
|
+
return;
|
|
5072
|
+
const id = `bacano-gtm-${containerId}`;
|
|
5073
|
+
if (document.getElementById(id)) return;
|
|
5074
|
+
prepareGtm(containerId);
|
|
5075
|
+
const script = document.createElement("script");
|
|
5076
|
+
script.id = id;
|
|
5077
|
+
script.async = true;
|
|
5078
|
+
script.src = `https://www.googletagmanager.com/gtm.js?id=${encodeURIComponent(containerId)}`;
|
|
5079
|
+
script.referrerPolicy = "strict-origin-when-cross-origin";
|
|
5080
|
+
script.onerror = () => onError();
|
|
5081
|
+
document.head.appendChild(script);
|
|
5082
|
+
}
|
|
5083
|
+
function sendGtm(event) {
|
|
5084
|
+
const target = marketingWindow();
|
|
5085
|
+
if (!target?.dataLayer) return;
|
|
5086
|
+
target.dataLayer.push({ bacano: null });
|
|
5087
|
+
target.dataLayer.push({
|
|
5088
|
+
event: `bacano_${event.eventName}`,
|
|
5089
|
+
bacano: {
|
|
5090
|
+
schema_version: event.schemaVersion,
|
|
5091
|
+
event_name: event.eventName,
|
|
5092
|
+
event_id: event.eventId,
|
|
5093
|
+
...interactionParameters(event),
|
|
5094
|
+
page_location: event.pageLocation,
|
|
5095
|
+
currency: event.currency,
|
|
5096
|
+
value: event.value,
|
|
5097
|
+
items: mapGa4Items(event.items),
|
|
5098
|
+
item_list_id: event.itemListId,
|
|
5099
|
+
item_list_name: event.itemListName,
|
|
5100
|
+
shipping_tier: event.shippingTier,
|
|
5101
|
+
payment_type: event.paymentType,
|
|
5102
|
+
method: event.contactMethod,
|
|
5103
|
+
contact_placement: event.eventName === "contact" && WEBSITE_MARKETING_CONTACT_PLACEMENTS.some(
|
|
5104
|
+
(value) => value === event.contactPlacement
|
|
5105
|
+
) ? event.contactPlacement : void 0
|
|
5106
|
+
}
|
|
5107
|
+
});
|
|
5108
|
+
}
|
|
5109
|
+
|
|
5055
5110
|
// libs/sdk/src/marketing/runtime.ts
|
|
5056
5111
|
function createWebsiteMarketingRuntime(options) {
|
|
5057
5112
|
let destroyed = false;
|
|
@@ -5072,7 +5127,7 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5072
5127
|
target.location.hostname
|
|
5073
5128
|
)
|
|
5074
5129
|
) && Boolean(
|
|
5075
|
-
options.config.destinations.ga4 || options.config.destinations.meta || options.config.destinations.clarity
|
|
5130
|
+
options.config.destinations.ga4 || options.config.destinations.meta || options.config.destinations.clarity || options.config.destinations.gtm
|
|
5076
5131
|
);
|
|
5077
5132
|
if (!enabled)
|
|
5078
5133
|
diagnostic({
|
|
@@ -5113,6 +5168,10 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5113
5168
|
const { projectId } = options.config.destinations.clarity;
|
|
5114
5169
|
guard("Clarity", () => prepareClarity(projectId));
|
|
5115
5170
|
}
|
|
5171
|
+
if (options.config.destinations.gtm) {
|
|
5172
|
+
const { containerId } = options.config.destinations.gtm;
|
|
5173
|
+
guard("GTM", () => prepareGtm(containerId));
|
|
5174
|
+
}
|
|
5116
5175
|
cancelScheduledLoad = scheduleScriptLoad(() => {
|
|
5117
5176
|
if (destroyed) return;
|
|
5118
5177
|
if (options.config.destinations.ga4) {
|
|
@@ -5128,6 +5187,10 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5128
5187
|
() => loadClarityScript(projectId, scriptError("Clarity"))
|
|
5129
5188
|
);
|
|
5130
5189
|
}
|
|
5190
|
+
if (options.config.destinations.gtm) {
|
|
5191
|
+
const { containerId } = options.config.destinations.gtm;
|
|
5192
|
+
guard("GTM", () => loadGtmScript(containerId, scriptError("GTM")));
|
|
5193
|
+
}
|
|
5131
5194
|
}, options.scriptLoadStrategy);
|
|
5132
5195
|
captureWebsiteMarketingAttribution(
|
|
5133
5196
|
options.websiteId,
|
|
@@ -5247,6 +5310,9 @@ function createWebsiteMarketingRuntime(options) {
|
|
|
5247
5310
|
if (options.config.destinations.clarity) {
|
|
5248
5311
|
dispatch("Clarity", () => sendClarityEvent(event.eventName));
|
|
5249
5312
|
}
|
|
5313
|
+
if (options.config.destinations.gtm && /^GTM-[A-Z0-9]{4,32}$/.test(options.config.destinations.gtm.containerId)) {
|
|
5314
|
+
dispatch("GTM", () => sendGtm(event));
|
|
5315
|
+
}
|
|
5250
5316
|
},
|
|
5251
5317
|
captureAttribution() {
|
|
5252
5318
|
if (!enabled || destroyed) return null;
|
|
@@ -5339,6 +5405,52 @@ function BacanoMarketingProvider({
|
|
|
5339
5405
|
// libs/sdk/src/react/provider.tsx
|
|
5340
5406
|
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
5341
5407
|
|
|
5408
|
+
// libs/sdk/src/flows.ts
|
|
5409
|
+
function createFlowsClient(config) {
|
|
5410
|
+
const base = config.apiUrl.replace(/\/+$/, "") + "/api/v1/website/flows";
|
|
5411
|
+
async function request(path, body, binary = false) {
|
|
5412
|
+
const token = await config.getAccessToken?.();
|
|
5413
|
+
const response = await fetch(base + path, {
|
|
5414
|
+
method: body === void 0 ? "GET" : "POST",
|
|
5415
|
+
cache: "no-store",
|
|
5416
|
+
headers: {
|
|
5417
|
+
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
5418
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
5419
|
+
...config.websiteSlug ? { "x-bacano-website-slug": config.websiteSlug } : {}
|
|
5420
|
+
},
|
|
5421
|
+
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
5422
|
+
});
|
|
5423
|
+
if (!response.ok) {
|
|
5424
|
+
const result = await response.json().catch(() => ({ error: "FLOW_REQUEST_FAILED" }));
|
|
5425
|
+
throw new WebsiteError(
|
|
5426
|
+
result.error ?? "FLOW_REQUEST_FAILED",
|
|
5427
|
+
result.error ?? "FLOW_REQUEST_FAILED"
|
|
5428
|
+
);
|
|
5429
|
+
}
|
|
5430
|
+
return binary ? await response.blob() : await response.json();
|
|
5431
|
+
}
|
|
5432
|
+
const stepPath = (caseId, stepId) => `/cases/${encodeURIComponent(caseId)}/steps/${encodeURIComponent(stepId)}`;
|
|
5433
|
+
return {
|
|
5434
|
+
/** Only the explicitly enabled local demo gateway accepts these credentials. */
|
|
5435
|
+
localDemoLogin: (email, password) => request("/local-session", { email, password }),
|
|
5436
|
+
logout: () => request("/logout", {}),
|
|
5437
|
+
listCases: () => request("/cases"),
|
|
5438
|
+
getJourney: (caseId) => request(`/cases/${encodeURIComponent(caseId)}`),
|
|
5439
|
+
getContent: (caseId, stepId) => request(stepPath(caseId, stepId) + "/content"),
|
|
5440
|
+
getForm: (caseId, stepId) => request(stepPath(caseId, stepId) + "/form"),
|
|
5441
|
+
getResponse: (caseId, stepId) => request(stepPath(caseId, stepId) + "/response"),
|
|
5442
|
+
getFile: (caseId, stepId, fileId) => request(
|
|
5443
|
+
stepPath(caseId, stepId) + `/files/${encodeURIComponent(fileId)}`,
|
|
5444
|
+
void 0,
|
|
5445
|
+
true
|
|
5446
|
+
),
|
|
5447
|
+
act: (caseId, command) => request(
|
|
5448
|
+
`/cases/${encodeURIComponent(caseId)}/actions`,
|
|
5449
|
+
command
|
|
5450
|
+
)
|
|
5451
|
+
};
|
|
5452
|
+
}
|
|
5453
|
+
|
|
5342
5454
|
// libs/sdk/src/modules/auth.ts
|
|
5343
5455
|
function createAuthHeaders(accessToken) {
|
|
5344
5456
|
return accessToken ? { Authorization: `Bearer ${accessToken}` } : {};
|
|
@@ -5521,7 +5633,8 @@ async function getWebsitePublicConfig(options) {
|
|
|
5521
5633
|
pixelId: marketing.destinations.meta.pixel_id,
|
|
5522
5634
|
diagnosticMode: marketing.destinations.meta.diagnostic_mode ?? false
|
|
5523
5635
|
} : null,
|
|
5524
|
-
clarity: marketing.destinations.clarity ? { projectId: marketing.destinations.clarity.project_id } : null
|
|
5636
|
+
clarity: marketing.destinations.clarity ? { projectId: marketing.destinations.clarity.project_id } : null,
|
|
5637
|
+
...marketing.destinations.gtm ? { gtm: { containerId: marketing.destinations.gtm.container_id } } : {}
|
|
5525
5638
|
}
|
|
5526
5639
|
},
|
|
5527
5640
|
legal: {
|
|
@@ -7362,6 +7475,7 @@ function createBacanoClient(config) {
|
|
|
7362
7475
|
await initialization;
|
|
7363
7476
|
},
|
|
7364
7477
|
getContext,
|
|
7478
|
+
flows: createFlowsClient(config),
|
|
7365
7479
|
auth: {
|
|
7366
7480
|
async getAccessToken() {
|
|
7367
7481
|
return config.getAccessToken ? await config.getAccessToken() : null;
|
|
@@ -52,6 +52,8 @@ aplicar obligatoriamente `STOREFRONT_CONTENT_LOCATOR.md`; añadir
|
|
|
52
52
|
`AUTHENTICATION.md`, `STOREFRONT_LEADS.md`, `STOREFRONT_CLARITY.md` y
|
|
53
53
|
otros contratos únicamente cuando esas capacidades existan. Leer
|
|
54
54
|
`STOREFRONT_CONSTRUCTION.md` cuando el website permita ocultarse temporalmente.
|
|
55
|
+
Si la tienda acepta pagos, leer obligatoriamente `STOREFRONT_PAYMENTS.md` antes
|
|
56
|
+
de implementar, depurar o auditar checkout, retorno, reintentos o webhooks.
|
|
55
57
|
Si existen formularios administrados desde Bacano, leer obligatoriamente
|
|
56
58
|
`STOREFRONT_FORMS.md` y
|
|
57
59
|
[references/forms.md](references/forms.md) antes de auditarlos o modificarlos.
|
|
@@ -54,6 +54,8 @@ Aplicar además de los controles comunes.
|
|
|
54
54
|
|
|
55
55
|
## Pagos y pedidos
|
|
56
56
|
|
|
57
|
+
- Leer y aplicar `STOREFRONT_PAYMENTS.md`; no reconstruir en la tienda URLs,
|
|
58
|
+
credenciales ni payloads privados de Wompi, Mercado Pago o Addi.
|
|
57
59
|
- Ejecutar al menos un happy path real o sandbox por cada método crítico
|
|
58
60
|
publicado. Probar pago inmediato, transferencia, Wompi y contraentrega solo
|
|
59
61
|
si están activos; los estados alternos de cada proveedor quedan en su matriz
|
package/transport/documents.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare const VALIDATE_COUPON = "\n mutation ValidateCoupon(\n $order
|
|
|
33
33
|
export declare const APPLY_COUPON = "\n mutation ApplyCoupon($orderId: uuid!, $cartToken: String!, $code: String!) {\n websiteApplyCoupon(\n order_id: $orderId\n cart_token: $cartToken\n code: $code\n ) {\n success\n order_id\n coupon_id\n code\n name\n coupon_type\n discount_amount\n eligible_subtotal\n message\n cart {\n id\n status\n discount\n total_without_tax\n tax\n total_with_tax\n total_with_discount\n created_at\n updated_at\n items {\n id\n product_variant_id\n quantity\n product_variant {\n id\n sku\n product {\n id\n name\n }\n prices {\n id\n price\n price_type\n chain_id\n }\n }\n }\n }\n errors\n }\n }\n";
|
|
34
34
|
export declare const REMOVE_COUPON = "\n mutation RemoveCoupon(\n $orderId: uuid!\n $cartToken: String!\n $couponId: uuid!\n ) {\n websiteRemoveCoupon(\n order_id: $orderId\n cart_token: $cartToken\n coupon_id: $couponId\n ) {\n success\n order_id\n coupon_id\n code\n name\n coupon_type\n discount_amount\n eligible_subtotal\n message\n cart {\n id\n status\n discount\n total_without_tax\n tax\n total_with_tax\n total_with_discount\n created_at\n updated_at\n items {\n id\n product_variant_id\n quantity\n product_variant {\n id\n sku\n product {\n id\n name\n }\n prices {\n id\n price\n price_type\n chain_id\n }\n }\n }\n }\n errors\n }\n }\n";
|
|
35
35
|
export declare const CREATE_PAYMENT_SESSION = "\n mutation CreatePaymentSession(\n $orderId: uuid!\n $cartToken: String\n $publicOrderToken: String\n $paymentMethodId: uuid!\n $returnUrl: String!\n ) {\n websiteCreatePaymentSession(\n order_id: $orderId\n cart_token: $cartToken\n public_order_token: $publicOrderToken\n payment_method_id: $paymentMethodId\n return_url: $returnUrl\n ) {\n success\n order_id\n payment_method_id\n payment_session_id\n gateway_code\n integration_mode\n status\n redirect_url\n public_payload\n errors\n }\n }\n";
|
|
36
|
-
export declare const RECONCILE_PAYMENT_SESSION = "\n mutation ReconcilePaymentSession(\n $orderId: uuid!\n $publicOrderToken: String!\n $paymentSessionId: uuid!\n $gatewayTransactionId: String
|
|
36
|
+
export declare const RECONCILE_PAYMENT_SESSION = "\n mutation ReconcilePaymentSession(\n $orderId: uuid!\n $publicOrderToken: String!\n $paymentSessionId: uuid!\n $gatewayTransactionId: String\n ) {\n websiteReconcilePaymentSession(\n order_id: $orderId\n public_order_token: $publicOrderToken\n payment_session_id: $paymentSessionId\n gateway_transaction_id: $gatewayTransactionId\n ) {\n success\n order_id\n payment_method_id\n payment_session_id\n gateway_code\n integration_mode\n status\n redirect_url\n public_payload\n errors\n }\n }\n";
|
|
37
37
|
export declare const GET_ORDERS = "\n query GetOrders($limit: Int = 20, $offset: Int = 0) {\n orders(\n where: { order_number: { _is_null: false } }\n order_by: { created_at: desc }\n limit: $limit\n offset: $offset\n ) {\n id\n order_number\n status\n fulfillment_family\n discount\n tax\n total_without_tax\n total_with_tax\n total_with_discount\n created_at\n updated_at\n order_product_variants {\n id\n product_variant_id\n quantity\n product_variant {\n sku\n product {\n id\n name\n }\n }\n }\n }\n }\n";
|
|
38
38
|
export declare const GET_ORDER_BY_PK = "\n query GetOrderByPk($orderId: uuid!) {\n orders(where: { id: { _eq: $orderId } }) {\n id\n order_number\n status\n fulfillment_family\n discount\n tax\n total_without_tax\n total_with_tax\n total_with_discount\n created_at\n updated_at\n order_product_variants {\n id\n product_variant_id\n quantity\n product_variant {\n sku\n product {\n id\n name\n }\n }\n }\n }\n }\n";
|
|
39
39
|
export declare const GET_PUBLIC_ORDER = "\n mutation GetPublicOrder($websiteId: uuid!, $orderId: uuid!, $token: String!) {\n websiteGetPublicOrder(\n website_id: $websiteId\n order_id: $orderId\n token: $token\n ) {\n success\n order {\n order_id\n order_number\n status\n payment_status\n fulfillment_family\n delivery {\n fulfillment_family\n shipping {\n label\n amount\n method_type\n collection_mode\n total_policy\n address\n }\n pickup {\n label\n }\n }\n payment {\n mode\n label\n method {\n id\n label\n payment_method_type\n gateway_code\n requires_payment_session\n }\n initial_payment {\n amount\n payment_method_id\n method_label\n payment_method_type\n gateway_code\n requires_payment_session\n }\n requires_payment_session\n next_action\n session {\n id\n gateway_code\n integration_mode\n status\n reference\n amount\n currency\n gateway_transaction_id\n error_message\n expires_at\n created_at\n updated_at\n }\n }\n totals {\n subtotal\n tax\n discount\n total\n total_with_discount\n }\n items {\n id\n product_variant_id\n sku\n name\n image_file_id\n quantity\n unit_price\n line_total\n }\n next_steps\n created_at\n updated_at\n }\n errors\n }\n }\n";
|
package/types.d.ts
CHANGED
|
@@ -151,7 +151,7 @@ export interface WebsiteCampaignCaptureResult {
|
|
|
151
151
|
}
|
|
152
152
|
export type WebsiteFormAction = "STORE_RESPONSE" | "CAPTURE_LEAD";
|
|
153
153
|
export type WebsiteFormStatus = "ACTIVE" | "PAUSED";
|
|
154
|
-
export type WebsiteFormFieldType = "text" | "textarea" | "email" | "phone" | "number" | "date" | "select" | "radio" | "multi_select" | "checkbox";
|
|
154
|
+
export type WebsiteFormFieldType = "text" | "textarea" | "email" | "phone" | "number" | "scale" | "date" | "select" | "radio" | "multi_select" | "checkbox";
|
|
155
155
|
export interface WebsiteFormOption {
|
|
156
156
|
value: string;
|
|
157
157
|
label: string;
|
|
@@ -164,10 +164,23 @@ export type WebsiteFormOptionSource = {
|
|
|
164
164
|
listKey: string;
|
|
165
165
|
};
|
|
166
166
|
export interface WebsiteFormField {
|
|
167
|
+
/** A single-choice question may reveal one branch, recursively. */
|
|
168
|
+
branches?: Array<{
|
|
169
|
+
value: string;
|
|
170
|
+
fields: WebsiteFormField[];
|
|
171
|
+
}>;
|
|
167
172
|
key: string;
|
|
168
173
|
label: string;
|
|
169
174
|
type: WebsiteFormFieldType;
|
|
170
175
|
required: boolean;
|
|
176
|
+
/** Discrete integer scale; submitted as a string, stored as a number. */
|
|
177
|
+
scale?: {
|
|
178
|
+
min: number;
|
|
179
|
+
max: number;
|
|
180
|
+
display: "numbers" | "stars";
|
|
181
|
+
minLabel?: string;
|
|
182
|
+
maxLabel?: string;
|
|
183
|
+
};
|
|
171
184
|
placeholder?: string | null;
|
|
172
185
|
helpText?: string | null;
|
|
173
186
|
optionSource?: WebsiteFormOptionSource | null;
|
|
@@ -267,6 +280,10 @@ export interface WebsiteMarketingPublicConfig {
|
|
|
267
280
|
clarity?: {
|
|
268
281
|
projectId: string;
|
|
269
282
|
} | null;
|
|
283
|
+
/** Optional web container. Does not replace native GA4/Meta destinations. */
|
|
284
|
+
gtm?: {
|
|
285
|
+
containerId: string;
|
|
286
|
+
} | null;
|
|
270
287
|
};
|
|
271
288
|
}
|
|
272
289
|
export type WebsiteCustomerIdentifierType = "AUTO" | "EMAIL" | "PHONE" | "DOCUMENT";
|