strapi-plugin-hubspot 0.16.7 → 0.16.9
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/CHANGELOG.md +26 -0
- package/dist/_chunks/{Forms-DyV6KyiO.mjs → Forms-CUNHDvhI.mjs} +52 -6
- package/dist/_chunks/{Forms-uUN4XjhW.js → Forms-CylJ0nD3.js} +52 -6
- package/dist/_chunks/{HubspotFormInput-BkWat_wu.js → HubspotFormInput-D2H2u9fZ.js} +1 -1
- package/dist/_chunks/{HubspotFormInput-DEXPX-6j.mjs → HubspotFormInput-Dppgr_rd.mjs} +1 -1
- package/dist/_chunks/{HubspotObjectInput-CFDYW-TM.js → HubspotObjectInput-BjRCaqXr.js} +3 -3
- package/dist/_chunks/{HubspotObjectInput-DL8fYK2x.mjs → HubspotObjectInput-CWFddNNw.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-CFMkbQeT.js → HubspotPropertyInput-BlDarkcj.js} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-WU5FMJj3.mjs → HubspotPropertyInput-TGG9ozTa.mjs} +3 -3
- package/dist/_chunks/{Settings-B_hhdpHa.js → Settings-DOx7YSqA.js} +2 -2
- package/dist/_chunks/{Settings-CiXEps_C.mjs → Settings-tct49GYU.mjs} +2 -2
- package/dist/_chunks/{index-BeBn7bJa.mjs → index-Au3W85GX.mjs} +5 -5
- package/dist/_chunks/{index-CG_WQzSa.js → index-DhGVA3ZL.js} +5 -5
- package/dist/_chunks/{objectLabels-CS_0QCNz.mjs → objectLabels-3rnJ0WUc.mjs} +1 -1
- package/dist/_chunks/{objectLabels-BGq-Ypgn.js → objectLabels-Bx7x8fFO.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-CP7LRdzO.mjs → useHubspotSchema-BlVXfwju.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-BZP2qkAu.js → useHubspotSchema-DrGeidXC.js} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/builder/types.d.ts +2 -1
- package/dist/server/index.js +243 -41
- package/dist/server/index.mjs +243 -41
- package/dist/server/src/conditions.d.ts +1 -0
- package/dist/server/src/formSync.d.ts +20 -0
- package/dist/server/src/formsAdmin.d.ts +1 -0
- package/dist/server/src/hsforms.d.ts +14 -1
- package/dist/server/src/importHubspot.d.ts +2 -1
- package/dist/server/src/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -1600,6 +1600,48 @@ function missingMappedFields(definition, existingNames) {
|
|
|
1600
1600
|
const existing = new Set(existingNames);
|
|
1601
1601
|
return mappedContactFields(definition).filter((field) => !existing.has(field.property));
|
|
1602
1602
|
}
|
|
1603
|
+
const OBJECT_TYPE_BY_NAME = {
|
|
1604
|
+
contact: "0-1",
|
|
1605
|
+
company: "0-2"
|
|
1606
|
+
};
|
|
1607
|
+
function collectedHubspotKeys(definition) {
|
|
1608
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1609
|
+
const add = (object, property) => {
|
|
1610
|
+
const typeId = OBJECT_TYPE_BY_NAME[object] || object;
|
|
1611
|
+
if (property) keys.add(`${typeId}:${property}`);
|
|
1612
|
+
};
|
|
1613
|
+
for (const step of definition.steps ?? []) {
|
|
1614
|
+
for (const fld of step.fields ?? []) {
|
|
1615
|
+
if (fld.type === "company") {
|
|
1616
|
+
const map = fld.companyMap ?? {};
|
|
1617
|
+
for (const slot of Object.values(map)) {
|
|
1618
|
+
if (slot?.property?.trim()) add(slot.object?.trim() || "company", slot.property.trim());
|
|
1619
|
+
}
|
|
1620
|
+
continue;
|
|
1621
|
+
}
|
|
1622
|
+
const mapping = fld.hubspot ?? {};
|
|
1623
|
+
const object = mapping.object?.trim() || "contact";
|
|
1624
|
+
const property = mapping.property?.trim() || fld.name;
|
|
1625
|
+
if (property) add(object, property);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
return keys;
|
|
1629
|
+
}
|
|
1630
|
+
function missingRequiredHubspotFields(definition, required) {
|
|
1631
|
+
const collected = collectedHubspotKeys(definition);
|
|
1632
|
+
const missing = [];
|
|
1633
|
+
for (const field of required) {
|
|
1634
|
+
if (!field.name) continue;
|
|
1635
|
+
const objectTypeId = field.objectTypeId?.trim() || "0-1";
|
|
1636
|
+
if (collected.has(`${objectTypeId}:${field.name}`)) continue;
|
|
1637
|
+
missing.push({
|
|
1638
|
+
name: field.name,
|
|
1639
|
+
objectTypeId,
|
|
1640
|
+
object: objectTypeId === "0-2" ? "company" : "contact"
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
return missing;
|
|
1644
|
+
}
|
|
1603
1645
|
function hsFieldType(type, options) {
|
|
1604
1646
|
switch (type) {
|
|
1605
1647
|
case "email":
|
|
@@ -1650,6 +1692,74 @@ function appendFieldGroups(existing, extra) {
|
|
|
1650
1692
|
}))
|
|
1651
1693
|
];
|
|
1652
1694
|
}
|
|
1695
|
+
function conditionToHubspot(condition, parentId) {
|
|
1696
|
+
const rules = (condition.rules ?? []).filter((rule) => rule.field === parentId);
|
|
1697
|
+
if (!rules.length || rules.length !== (condition.rules ?? []).length) return null;
|
|
1698
|
+
const op = rules[0]?.operator;
|
|
1699
|
+
if (rules.some((rule) => rule.operator !== op)) return null;
|
|
1700
|
+
const values = rules.map((rule) => rule.value).filter((value) => Boolean(value));
|
|
1701
|
+
switch (op) {
|
|
1702
|
+
case "eq":
|
|
1703
|
+
return { operator: values.length > 1 ? "SET_ANY" : "EQ", values };
|
|
1704
|
+
case "neq":
|
|
1705
|
+
return { operator: values.length > 1 ? "NOT_SET_ANY" : "NEQ", values };
|
|
1706
|
+
case "contains":
|
|
1707
|
+
return { operator: "CONTAINS", values };
|
|
1708
|
+
case "gt":
|
|
1709
|
+
return { operator: "GT", values };
|
|
1710
|
+
case "lt":
|
|
1711
|
+
return { operator: "LT", values };
|
|
1712
|
+
case "notEmpty":
|
|
1713
|
+
return { operator: "SET", values: [] };
|
|
1714
|
+
case "empty":
|
|
1715
|
+
return { operator: "NOT_SET", values: [] };
|
|
1716
|
+
default:
|
|
1717
|
+
return null;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
function applyVisibleIfToFieldGroups(groups, definition) {
|
|
1721
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1722
|
+
for (const step of definition.steps ?? []) {
|
|
1723
|
+
for (const fld of step.fields ?? []) {
|
|
1724
|
+
const mapping = fld.hubspot ?? {};
|
|
1725
|
+
byId.set(fld.id, { name: fld.name, property: mapping.property?.trim() || fld.name });
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
const moves = /* @__PURE__ */ new Map();
|
|
1729
|
+
for (const step of definition.steps ?? []) {
|
|
1730
|
+
for (const fld of step.fields ?? []) {
|
|
1731
|
+
const visibleIf = fld.visibleIf;
|
|
1732
|
+
const parentId = visibleIf?.rules?.[0]?.field;
|
|
1733
|
+
if (!visibleIf || !parentId) continue;
|
|
1734
|
+
const converted = conditionToHubspot(visibleIf, parentId);
|
|
1735
|
+
const parent = byId.get(parentId);
|
|
1736
|
+
const mapping = fld.hubspot ?? {};
|
|
1737
|
+
const property = mapping.property?.trim() || fld.name;
|
|
1738
|
+
if (!converted || !parent) continue;
|
|
1739
|
+
moves.set(property, { parent: parent.property, ...converted });
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
if (!moves.size) return groups;
|
|
1743
|
+
const cloned = JSON.parse(JSON.stringify(groups));
|
|
1744
|
+
const flat = [];
|
|
1745
|
+
for (const group of cloned) {
|
|
1746
|
+
(group.fields ?? []).forEach((field, index2) => flat.push({ group, index: index2, field }));
|
|
1747
|
+
}
|
|
1748
|
+
for (const [property, move] of moves) {
|
|
1749
|
+
const child = flat.find((item) => item.field.name === property);
|
|
1750
|
+
const parent = flat.find((item) => item.field.name === move.parent);
|
|
1751
|
+
if (!child || !parent || child === parent) continue;
|
|
1752
|
+
parent.field.dependentFields = [
|
|
1753
|
+
...parent.field.dependentFields ?? [],
|
|
1754
|
+
{
|
|
1755
|
+
dependentCondition: { operator: move.operator, values: move.values },
|
|
1756
|
+
field: child.field
|
|
1757
|
+
}
|
|
1758
|
+
];
|
|
1759
|
+
child.group.fields?.splice(child.index, 1);
|
|
1760
|
+
}
|
|
1761
|
+
return cloned;
|
|
1762
|
+
}
|
|
1653
1763
|
const HS_BASE$2 = "https://api.hubapi.com";
|
|
1654
1764
|
const OBJECT_BY_TYPE_ID = {
|
|
1655
1765
|
"0-1": "contact",
|
|
@@ -1731,7 +1841,7 @@ function convertField(raw, ctx) {
|
|
|
1731
1841
|
helpText: raw.description || void 0,
|
|
1732
1842
|
...options.length ? { options } : {},
|
|
1733
1843
|
hubspot: { object, property: name },
|
|
1734
|
-
...ctx.parentCondition ? { visibleIf: ctx.parentCondition } : {}
|
|
1844
|
+
...ctx.parentCondition ? { visibleIf: ctx.parentCondition, visibleIfSource: "hubspot" } : {}
|
|
1735
1845
|
};
|
|
1736
1846
|
const out = [field];
|
|
1737
1847
|
for (const dependent of raw.dependentFields ?? []) {
|
|
@@ -1754,6 +1864,12 @@ function convertHubspotForm(raw) {
|
|
|
1754
1864
|
const usedNames = /* @__PURE__ */ new Set();
|
|
1755
1865
|
const fields = [];
|
|
1756
1866
|
for (const group of raw.fieldGroups ?? []) {
|
|
1867
|
+
if (group.groupType === "progressive" || group.groupType === "queued") {
|
|
1868
|
+
skipped.push({
|
|
1869
|
+
code: "progressive",
|
|
1870
|
+
detail: group.groupType
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1757
1873
|
if (group.richText && !(group.fields ?? []).length) {
|
|
1758
1874
|
skipped.push({ code: "rich-text", detail: group.richText.slice(0, 80) });
|
|
1759
1875
|
continue;
|
|
@@ -1825,7 +1941,10 @@ function mergeHubspotImport(current, incoming) {
|
|
|
1825
1941
|
existing.helpText = next.helpText;
|
|
1826
1942
|
if (next.options) existing.options = next.options;
|
|
1827
1943
|
else delete existing.options;
|
|
1828
|
-
if (
|
|
1944
|
+
if (next.visibleIf && (existing.visibleIfSource === "hubspot" || !existing.visibleIf)) {
|
|
1945
|
+
existing.visibleIf = next.visibleIf;
|
|
1946
|
+
if (existing.visibleIfSource !== "editor") existing.visibleIfSource = "hubspot";
|
|
1947
|
+
}
|
|
1829
1948
|
updated.push(key);
|
|
1830
1949
|
continue;
|
|
1831
1950
|
}
|
|
@@ -2048,24 +2167,20 @@ async function loadFormShape(apiKey, formGuid) {
|
|
|
2048
2167
|
return null;
|
|
2049
2168
|
}
|
|
2050
2169
|
}
|
|
2051
|
-
async function findContactIdByEmail(apiKey, email) {
|
|
2052
|
-
const
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
});
|
|
2066
|
-
const body = await res.json().catch(() => ({}));
|
|
2067
|
-
if (!res.ok) return void 0;
|
|
2068
|
-
return body.results?.[0]?.id;
|
|
2170
|
+
async function findContactIdByEmail(apiKey, email, retryDelaysMs = [400, 1200]) {
|
|
2171
|
+
for (const delay of [0, ...retryDelaysMs]) {
|
|
2172
|
+
if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
|
|
2173
|
+
const res = await fetch(
|
|
2174
|
+
`https://api.hubapi.com/crm/v3/objects/contacts/${encodeURIComponent(email)}?idProperty=email`,
|
|
2175
|
+
{ headers: { Authorization: `Bearer ${apiKey}` } }
|
|
2176
|
+
);
|
|
2177
|
+
if (res.ok) {
|
|
2178
|
+
const body = await res.json().catch(() => ({}));
|
|
2179
|
+
return body.id || void 0;
|
|
2180
|
+
}
|
|
2181
|
+
if (res.status !== 404) return void 0;
|
|
2182
|
+
}
|
|
2183
|
+
return void 0;
|
|
2069
2184
|
}
|
|
2070
2185
|
function contextPayload(ctx) {
|
|
2071
2186
|
const out = {};
|
|
@@ -2146,13 +2261,62 @@ async function submitMarketingForm(input) {
|
|
|
2146
2261
|
async function syncFieldsToHubspotForm(apiKey, formGuid, definition) {
|
|
2147
2262
|
const raw = await fetchHubspotForm(apiKey, formGuid);
|
|
2148
2263
|
const extra = missingMappedFields(definition, formFieldNames(raw));
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2264
|
+
const fieldGroups = applyVisibleIfToFieldGroups(
|
|
2265
|
+
appendFieldGroups(raw.fieldGroups ?? [], extra),
|
|
2266
|
+
definition
|
|
2267
|
+
);
|
|
2268
|
+
if (!extra.length && JSON.stringify(fieldGroups) === JSON.stringify(appendFieldGroups(raw.fieldGroups ?? [], []))) {
|
|
2269
|
+
return [];
|
|
2270
|
+
}
|
|
2271
|
+
await patchHubspotForm(apiKey, formGuid, { fieldGroups });
|
|
2153
2272
|
clearFormShapeCache(formGuid);
|
|
2154
2273
|
return extra.map((field) => field.property);
|
|
2155
2274
|
}
|
|
2275
|
+
async function createMarketingForm(apiKey, name, definition) {
|
|
2276
|
+
const fields = mappedContactFields(definition).map((field) => toHsFormField(field));
|
|
2277
|
+
if (!fields.length) {
|
|
2278
|
+
throw new Error("Add at least one mapped contact field before creating a HubSpot form");
|
|
2279
|
+
}
|
|
2280
|
+
const res = await fetch("https://api.hubapi.com/marketing/v3/forms", {
|
|
2281
|
+
method: "POST",
|
|
2282
|
+
headers: {
|
|
2283
|
+
Authorization: `Bearer ${apiKey}`,
|
|
2284
|
+
"Content-Type": "application/json"
|
|
2285
|
+
},
|
|
2286
|
+
body: JSON.stringify({
|
|
2287
|
+
name,
|
|
2288
|
+
formType: "hubspot",
|
|
2289
|
+
fieldGroups: applyVisibleIfToFieldGroups(
|
|
2290
|
+
fields.map((field) => ({
|
|
2291
|
+
groupType: "default_group",
|
|
2292
|
+
richTextType: "text",
|
|
2293
|
+
fields: [field]
|
|
2294
|
+
})),
|
|
2295
|
+
definition
|
|
2296
|
+
),
|
|
2297
|
+
configuration: {
|
|
2298
|
+
language: "fr",
|
|
2299
|
+
recaptchaEnabled: false,
|
|
2300
|
+
createNewContactForNewEmail: true,
|
|
2301
|
+
prePopulateKnownValues: true,
|
|
2302
|
+
notifyContactOwner: false,
|
|
2303
|
+
notifyRecipients: [],
|
|
2304
|
+
editable: true,
|
|
2305
|
+
archivable: true,
|
|
2306
|
+
cloneable: true,
|
|
2307
|
+
allowLinkToResetKnownValues: false,
|
|
2308
|
+
postSubmitAction: { type: "thank_you", value: "Merci." }
|
|
2309
|
+
},
|
|
2310
|
+
displayOptions: { submitButtonText: "Envoyer", style: { submitButtonText: "Envoyer" } },
|
|
2311
|
+
legalConsentOptions: { type: "none" }
|
|
2312
|
+
})
|
|
2313
|
+
});
|
|
2314
|
+
const body = await res.json().catch(() => ({}));
|
|
2315
|
+
if (!res.ok || !body.id) {
|
|
2316
|
+
throw new Error(body.message || `HubSpot ${res.status}`);
|
|
2317
|
+
}
|
|
2318
|
+
return body.id;
|
|
2319
|
+
}
|
|
2156
2320
|
function publicForm(entry) {
|
|
2157
2321
|
return {
|
|
2158
2322
|
slug: entry.slug,
|
|
@@ -2166,7 +2330,9 @@ function publicForm(entry) {
|
|
|
2166
2330
|
steps: (entry.definition?.steps ?? []).map((step) => ({
|
|
2167
2331
|
...step,
|
|
2168
2332
|
// The CRM mappings are the server's business — never the browser's.
|
|
2169
|
-
fields: (step.fields ?? []).map(
|
|
2333
|
+
fields: (step.fields ?? []).map(
|
|
2334
|
+
({ hubspot: _hubspot, companyMap: _companyMap, visibleIfSource: _source, ...fld }) => fld
|
|
2335
|
+
)
|
|
2170
2336
|
}))
|
|
2171
2337
|
};
|
|
2172
2338
|
}
|
|
@@ -2910,6 +3076,22 @@ function createFormsAdminController(strapi) {
|
|
|
2910
3076
|
ctx.body = { errors: structural, problems: mappings };
|
|
2911
3077
|
return;
|
|
2912
3078
|
}
|
|
3079
|
+
const { apiKey } = await resolveApiKey(strapi);
|
|
3080
|
+
const account = await resolveAccount(strapi);
|
|
3081
|
+
const ownGuid = typeof entry.hubspotFormId === "string" ? entry.hubspotFormId.trim() : "";
|
|
3082
|
+
const formGuid = isFormGuid(ownGuid) ? ownGuid : isFormGuid(account.defaultFormId) ? account.defaultFormId.trim() : "";
|
|
3083
|
+
if (apiKey && formGuid) {
|
|
3084
|
+
const shape = await loadFormShape(apiKey, formGuid);
|
|
3085
|
+
const missingHubspot = shape ? missingRequiredHubspotFields(
|
|
3086
|
+
entry.definition ?? EMPTY_DEFINITION,
|
|
3087
|
+
[...shape.fields.filter((field) => field.required)]
|
|
3088
|
+
) : [];
|
|
3089
|
+
if (missingHubspot.length) {
|
|
3090
|
+
ctx.status = 400;
|
|
3091
|
+
ctx.body = { errors: structural, problems: mappings, missingHubspot };
|
|
3092
|
+
return;
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
2913
3095
|
await documents().publish({
|
|
2914
3096
|
documentId: ctx.params.documentId,
|
|
2915
3097
|
locale: ctx.query.locale
|
|
@@ -2917,22 +3099,16 @@ function createFormsAdminController(strapi) {
|
|
|
2917
3099
|
const policy = await resolvePolicy(strapi);
|
|
2918
3100
|
let addedFields = [];
|
|
2919
3101
|
let syncWarning;
|
|
2920
|
-
if (policy.syncFieldsOnPublish) {
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
entry.definition ?? EMPTY_DEFINITION
|
|
2931
|
-
);
|
|
2932
|
-
} catch (err) {
|
|
2933
|
-
syncWarning = err.message;
|
|
2934
|
-
strapi.log.warn(`[hubspot] field sync on publish failed — ${syncWarning}`);
|
|
2935
|
-
}
|
|
3102
|
+
if (policy.syncFieldsOnPublish && apiKey && formGuid) {
|
|
3103
|
+
try {
|
|
3104
|
+
addedFields = await syncFieldsToHubspotForm(
|
|
3105
|
+
apiKey,
|
|
3106
|
+
formGuid,
|
|
3107
|
+
entry.definition ?? EMPTY_DEFINITION
|
|
3108
|
+
);
|
|
3109
|
+
} catch (err) {
|
|
3110
|
+
syncWarning = err.message;
|
|
3111
|
+
strapi.log.warn(`[hubspot] field sync on publish failed — ${syncWarning}`);
|
|
2936
3112
|
}
|
|
2937
3113
|
}
|
|
2938
3114
|
ctx.body = {
|
|
@@ -2941,6 +3117,31 @@ function createFormsAdminController(strapi) {
|
|
|
2941
3117
|
...syncWarning ? { syncWarning } : {}
|
|
2942
3118
|
};
|
|
2943
3119
|
},
|
|
3120
|
+
async createInHubspot(ctx) {
|
|
3121
|
+
const entry = await documents().findOne({
|
|
3122
|
+
documentId: ctx.params.documentId,
|
|
3123
|
+
locale: ctx.query.locale,
|
|
3124
|
+
status: "draft"
|
|
3125
|
+
});
|
|
3126
|
+
if (!entry) ctx.throw(404, "Form not found");
|
|
3127
|
+
const { apiKey } = await resolveApiKey(strapi);
|
|
3128
|
+
if (!apiKey) ctx.throw(400, "HubSpot API key is missing");
|
|
3129
|
+
try {
|
|
3130
|
+
const id = await createMarketingForm(
|
|
3131
|
+
apiKey,
|
|
3132
|
+
entry.name || entry.slug || "Formulaire",
|
|
3133
|
+
entry.definition ?? EMPTY_DEFINITION
|
|
3134
|
+
);
|
|
3135
|
+
const updated = await documents().update({
|
|
3136
|
+
documentId: ctx.params.documentId,
|
|
3137
|
+
locale: ctx.query.locale,
|
|
3138
|
+
data: { hubspotFormId: id }
|
|
3139
|
+
});
|
|
3140
|
+
ctx.body = { form: updated, hubspotFormId: id };
|
|
3141
|
+
} catch (err) {
|
|
3142
|
+
ctx.throw(400, err.message);
|
|
3143
|
+
}
|
|
3144
|
+
},
|
|
2944
3145
|
async unpublish(ctx) {
|
|
2945
3146
|
await documents().unpublish({
|
|
2946
3147
|
documentId: ctx.params.documentId,
|
|
@@ -3707,6 +3908,7 @@ const routes = {
|
|
|
3707
3908
|
adminRoute("GET", "/builder/forms/:documentId", "formsAdmin.findOne", [FORMS_ACTION]),
|
|
3708
3909
|
adminRoute("PUT", "/builder/forms/:documentId", "formsAdmin.update", [FORMS_ACTION]),
|
|
3709
3910
|
adminRoute("POST", "/builder/forms/:documentId/publish", "formsAdmin.publish", [FORMS_ACTION]),
|
|
3911
|
+
adminRoute("POST", "/builder/forms/:documentId/create-hubspot", "formsAdmin.createInHubspot", [FORMS_ACTION]),
|
|
3710
3912
|
adminRoute("POST", "/builder/forms/:documentId/unpublish", "formsAdmin.unpublish", [FORMS_ACTION]),
|
|
3711
3913
|
adminRoute("DELETE", "/builder/forms/:documentId", "formsAdmin.remove", [FORMS_ACTION]),
|
|
3712
3914
|
adminRoute("POST", "/builder/forms/:documentId/duplicate", "formsAdmin.duplicate", [FORMS_ACTION]),
|