strapi-plugin-hubspot 0.13.1 → 0.15.0
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 +33 -0
- package/README.md +58 -32
- package/dist/_chunks/{Forms-CHB-sKem.mjs → Forms-B7eIm0Fi.mjs} +38 -3
- package/dist/_chunks/{Forms-lrzuWzoB.js → Forms-ClyI4MJ1.js} +38 -3
- package/dist/_chunks/{HubspotFormInput-Bb6it0nP.js → HubspotFormInput-Do7F83V6.js} +1 -1
- package/dist/_chunks/{HubspotFormInput-YI09keTC.mjs → HubspotFormInput-cZAiaAaq.mjs} +1 -1
- package/dist/_chunks/{HubspotObjectInput-D3A6xzb3.js → HubspotObjectInput-DWqk2C26.js} +3 -3
- package/dist/_chunks/{HubspotObjectInput-CzLKT9oj.mjs → HubspotObjectInput-ZZk_7hWq.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-DicskLcN.mjs → HubspotPropertyInput-5bkDGmGo.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-Dss3eUlL.js → HubspotPropertyInput-v9B3wb1a.js} +3 -3
- package/dist/_chunks/{Settings-4CbX3SPK.mjs → Settings-QcFbm3s5.mjs} +132 -36
- package/dist/_chunks/{Settings-Ch8tPZAV.js → Settings-X3EHnTaO.js} +131 -35
- package/dist/_chunks/{en-D8DJiSxd.mjs → en-DMJeF7EN.mjs} +19 -6
- package/dist/_chunks/{en-PYFibnDc.js → en-ZHvaZLi7.js} +19 -6
- package/dist/_chunks/{fr-BMjixfXn.mjs → fr-CVAntLmc.mjs} +18 -5
- package/dist/_chunks/{fr-yHk4sSEl.js → fr-Ds_2EAzZ.js} +18 -5
- package/dist/_chunks/{index-BE2ribUL.mjs → index-BSJAhj8r.mjs} +6 -6
- package/dist/_chunks/{index-BAvedd2m.js → index-BpcilDy1.js} +6 -6
- package/dist/_chunks/{objectLabels-CycoU0zY.js → objectLabels-CYXXFpNB.js} +1 -1
- package/dist/_chunks/{objectLabels-DGJxYjKz.mjs → objectLabels-CrYRzsqe.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-DRfaI6mF.js → useHubspotSchema-Ba6xZUCL.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-e31UsYb2.mjs → useHubspotSchema-CBF4GkmK.mjs} +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 -0
- package/dist/server/index.js +502 -197
- package/dist/server/index.mjs +502 -197
- package/dist/server/src/__tests__/hsforms.test.d.ts +1 -0
- package/dist/server/src/__tests__/settings.test.d.ts +1 -0
- package/dist/server/src/content-types.d.ts +8 -0
- package/dist/server/src/forms.d.ts +10 -6
- package/dist/server/src/hsforms.d.ts +75 -0
- package/dist/server/src/importHubspot.d.ts +1 -0
- package/dist/server/src/index.d.ts +17 -2
- package/dist/server/src/settings.d.ts +36 -5
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The form-builder server side: shaping a published form for the public API,
|
|
3
|
-
* and turning a submission into HubSpot
|
|
3
|
+
* and turning a submission into a HubSpot marketing-form conversion.
|
|
4
4
|
*
|
|
5
|
-
* The pipeline
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* The pipeline: post the answers to HubSpot's Forms API (native conversion,
|
|
6
|
+
* workflows, original source, lead-center notifications) with the visitor's
|
|
7
|
+
* `hutk`; look the contact back up by email; when the email is on a corporate
|
|
8
|
+
* domain the company is found-or-created by `domain` and associated. A CRM
|
|
9
|
+
* contact upsert is the fallback when no form GUID is configured — it does
|
|
10
|
+
* not count as a form conversion. Timeline notes are opt-in and only used
|
|
11
|
+
* on that fallback. Company sync is best-effort; the form submission is
|
|
12
|
+
* the lead.
|
|
10
13
|
*/
|
|
11
14
|
import type { Core } from "@strapi/strapi";
|
|
12
15
|
import { type FormDefinition, type Primitive } from "./conditions";
|
|
@@ -21,6 +24,7 @@ export interface FormEntry {
|
|
|
21
24
|
submitLabel?: string | null;
|
|
22
25
|
successMessage?: string | null;
|
|
23
26
|
class?: string | null;
|
|
27
|
+
hubspotFormId?: string | null;
|
|
24
28
|
locale?: string | null;
|
|
25
29
|
definition: FormDefinition;
|
|
26
30
|
[key: string]: unknown;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HubSpot marketing Forms API — native form submissions.
|
|
3
|
+
*
|
|
4
|
+
* CRM upserts never count as form conversions: Original Source stays
|
|
5
|
+
* "Offline / Integration", workflows that listen to a form don't fire, and
|
|
6
|
+
* the lead-center notification attached to the form never runs. Posting to
|
|
7
|
+
* `/submissions/v3/integration/secure/submit/{portalId}/{formGuid}` with the
|
|
8
|
+
* visitor's `hutk` is what HubSpot treats as a real conversion.
|
|
9
|
+
*
|
|
10
|
+
* Portal id, region and form GUIDs are configuration — a test portal today,
|
|
11
|
+
* production tomorrow, no code change.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isFormGuid(value: string): boolean;
|
|
14
|
+
export declare function sanitizeHutk(value: unknown): string | undefined;
|
|
15
|
+
export declare function sanitizePortalId(value: unknown): string | undefined;
|
|
16
|
+
export declare function sanitizeIp(value: unknown): string | undefined;
|
|
17
|
+
/** Forms submit host. CRM stays on api.hubapi.com; this endpoint is regional. */
|
|
18
|
+
export declare function formsHost(region: string): string;
|
|
19
|
+
export declare function formsSubmitUrl(portalId: string, formGuid: string, region?: string): string;
|
|
20
|
+
export declare function trackingScriptUrl(portalId: string, region?: string): string;
|
|
21
|
+
export declare function toHsFields(props: Record<string, string>): {
|
|
22
|
+
name: string;
|
|
23
|
+
value: string;
|
|
24
|
+
}[];
|
|
25
|
+
export declare function filterToFormFields(fields: {
|
|
26
|
+
name: string;
|
|
27
|
+
value: string;
|
|
28
|
+
}[], allowed: Set<string> | null): {
|
|
29
|
+
name: string;
|
|
30
|
+
value: string;
|
|
31
|
+
}[];
|
|
32
|
+
export declare function formFieldNames(raw: {
|
|
33
|
+
fieldGroups?: {
|
|
34
|
+
fields?: {
|
|
35
|
+
name?: string;
|
|
36
|
+
}[];
|
|
37
|
+
}[];
|
|
38
|
+
}): string[];
|
|
39
|
+
export interface FormSubmitContext {
|
|
40
|
+
hutk?: string;
|
|
41
|
+
pageUri?: string;
|
|
42
|
+
pageName?: string;
|
|
43
|
+
ipAddress?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface FormSubmitInput {
|
|
46
|
+
apiKey: string;
|
|
47
|
+
portalId: string;
|
|
48
|
+
formGuid: string;
|
|
49
|
+
region?: string;
|
|
50
|
+
fields: {
|
|
51
|
+
name: string;
|
|
52
|
+
value: string;
|
|
53
|
+
}[];
|
|
54
|
+
context?: FormSubmitContext;
|
|
55
|
+
consent?: {
|
|
56
|
+
given: boolean;
|
|
57
|
+
text?: string;
|
|
58
|
+
};
|
|
59
|
+
formHasLegalConsent?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export declare function loadFormShape(apiKey: string, formGuid: string): Promise<{
|
|
62
|
+
names: Set<string>;
|
|
63
|
+
hasLegalConsent: boolean;
|
|
64
|
+
} | null>;
|
|
65
|
+
export declare function findContactIdByEmail(apiKey: string, email: string): Promise<string | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* Submit a marketing form. Extra fields HubSpot doesn't know on that form
|
|
68
|
+
* 400 the whole request, so callers should filter first; we still retry
|
|
69
|
+
* without legal-consent and then email-only if HubSpot refuses the payload.
|
|
70
|
+
*/
|
|
71
|
+
export declare function submitMarketingForm(input: FormSubmitInput): Promise<{
|
|
72
|
+
ok: boolean;
|
|
73
|
+
status: number;
|
|
74
|
+
error?: string;
|
|
75
|
+
}>;
|
|
@@ -5,11 +5,14 @@ declare const _default: {
|
|
|
5
5
|
config: {
|
|
6
6
|
default: {
|
|
7
7
|
apiKey: string;
|
|
8
|
+
portalId: string;
|
|
9
|
+
region: string;
|
|
8
10
|
objects: unknown[];
|
|
9
11
|
validate: ValidateTarget[];
|
|
10
12
|
forms: {
|
|
11
13
|
companyFromDomain: boolean;
|
|
12
14
|
timelineNote: boolean;
|
|
15
|
+
defaultFormId: string;
|
|
13
16
|
rateLimit: {
|
|
14
17
|
submitPerMinute: number;
|
|
15
18
|
searchPerMinute: number;
|
|
@@ -39,7 +42,7 @@ declare const _default: {
|
|
|
39
42
|
visible: boolean;
|
|
40
43
|
};
|
|
41
44
|
"content-type-builder": {
|
|
42
|
-
visible: boolean;
|
|
45
|
+
visible: boolean;
|
|
43
46
|
};
|
|
44
47
|
i18n: {
|
|
45
48
|
localized: boolean;
|
|
@@ -47,6 +50,7 @@ declare const _default: {
|
|
|
47
50
|
};
|
|
48
51
|
attributes: {
|
|
49
52
|
name: {
|
|
53
|
+
/** RBAC action gating the settings screen and its routes. */
|
|
50
54
|
type: string;
|
|
51
55
|
required: boolean;
|
|
52
56
|
pluginOptions: {
|
|
@@ -103,6 +107,14 @@ declare const _default: {
|
|
|
103
107
|
class: {
|
|
104
108
|
type: string;
|
|
105
109
|
};
|
|
110
|
+
hubspotFormId: {
|
|
111
|
+
type: string;
|
|
112
|
+
pluginOptions: {
|
|
113
|
+
i18n: {
|
|
114
|
+
localized: boolean;
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
};
|
|
106
118
|
definition: {
|
|
107
119
|
type: string;
|
|
108
120
|
required: boolean;
|
|
@@ -347,8 +359,11 @@ declare const _default: {
|
|
|
347
359
|
}): Promise<void>;
|
|
348
360
|
update(ctx: {
|
|
349
361
|
request: {
|
|
350
|
-
body
|
|
362
|
+
body?: {
|
|
351
363
|
apiKey?: string;
|
|
364
|
+
portalId?: string;
|
|
365
|
+
region?: string;
|
|
366
|
+
defaultFormId?: string;
|
|
352
367
|
};
|
|
353
368
|
};
|
|
354
369
|
body: unknown;
|
|
@@ -1,28 +1,59 @@
|
|
|
1
1
|
import type { Core } from "@strapi/strapi";
|
|
2
2
|
/**
|
|
3
|
-
* API key resolution, in order of precedence:
|
|
3
|
+
* API key + portal resolution, in order of precedence:
|
|
4
4
|
* 1. saved from the admin UI (plugin core store)
|
|
5
5
|
* 2. plugin config (config/plugins of the host app)
|
|
6
|
-
* 3. environment variable
|
|
6
|
+
* 3. environment variable
|
|
7
7
|
*
|
|
8
8
|
* The key is only ever read server-side; `publicSettings` is what the admin UI
|
|
9
|
-
* receives, and it deliberately never carries the key itself.
|
|
9
|
+
* receives, and it deliberately never carries the key itself. Portal id, region
|
|
10
|
+
* and the default form GUID are not secrets — they round-trip so they can be
|
|
11
|
+
* edited in Settings → HubSpot.
|
|
10
12
|
*/
|
|
11
13
|
export declare const ENV_VAR = "HUBSPOT_API_KEY";
|
|
14
|
+
export declare const ENV_PORTAL = "HUBSPOT_PORTAL_ID";
|
|
15
|
+
export declare const ENV_REGION = "HUBSPOT_REGION";
|
|
16
|
+
export declare const ENV_DEFAULT_FORM = "HUBSPOT_DEFAULT_FORM_ID";
|
|
17
|
+
export type SettingSource = "settings" | "config" | "env" | null;
|
|
12
18
|
export interface StoredSettings {
|
|
13
19
|
apiKey?: string;
|
|
20
|
+
portalId?: string;
|
|
21
|
+
region?: string;
|
|
22
|
+
defaultFormId?: string;
|
|
14
23
|
}
|
|
15
24
|
export interface PublicSettings {
|
|
16
25
|
configured: boolean;
|
|
17
26
|
/** Where the key comes from, so the UI can explain why it can't be edited. */
|
|
18
|
-
keySource:
|
|
27
|
+
keySource: SettingSource;
|
|
19
28
|
/** Last four characters, enough to recognise a key without exposing it. */
|
|
20
29
|
hint: string;
|
|
30
|
+
portalId: string;
|
|
31
|
+
region: string;
|
|
32
|
+
defaultFormId: string;
|
|
33
|
+
portalSource: SettingSource;
|
|
34
|
+
regionSource: SettingSource;
|
|
35
|
+
formSource: SettingSource;
|
|
36
|
+
}
|
|
37
|
+
export interface HubspotAccount {
|
|
38
|
+
portalId: string;
|
|
39
|
+
region: string;
|
|
40
|
+
defaultFormId: string;
|
|
21
41
|
}
|
|
22
42
|
export declare function getStoredSettings(strapi: Core.Strapi): Promise<StoredSettings>;
|
|
23
43
|
export declare function setStoredSettings(strapi: Core.Strapi, value: StoredSettings | null): Promise<void>;
|
|
24
44
|
export declare function resolveApiKey(strapi: Core.Strapi): Promise<{
|
|
25
45
|
apiKey: string;
|
|
26
|
-
source:
|
|
46
|
+
source: SettingSource;
|
|
27
47
|
}>;
|
|
48
|
+
/** Portal / region / default marketing form — settings UI overrides env. */
|
|
49
|
+
export declare function resolveAccount(strapi: Core.Strapi): Promise<HubspotAccount>;
|
|
28
50
|
export declare function publicSettings(strapi: Core.Strapi): Promise<PublicSettings>;
|
|
51
|
+
/** Merge a PATCH-like body into the store without dropping the saved key. */
|
|
52
|
+
export declare function patchStoredSettings(strapi: Core.Strapi, body: {
|
|
53
|
+
apiKey?: string;
|
|
54
|
+
portalId?: unknown;
|
|
55
|
+
region?: unknown;
|
|
56
|
+
defaultFormId?: unknown;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
/** Drop only the stored token; portal / form settings stay. */
|
|
59
|
+
export declare function clearStoredApiKey(strapi: Core.Strapi): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-hubspot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "The form builder for HubSpot in Strapi — multi-step forms with conditional fields mapped to real CRM properties, a public submit pipeline with retries, and save-time mapping validation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|