strapi-plugin-hubspot 0.5.0 → 0.6.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 (51) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +110 -4
  3. package/dist/_chunks/Forms-B2y_0-x4.mjs +989 -0
  4. package/dist/_chunks/Forms-CaT0YEJo.js +1007 -0
  5. package/dist/_chunks/{HubspotObjectInput-DpXMFiPg.js → HubspotObjectInput-Crpcpa8T.js} +3 -3
  6. package/dist/_chunks/{HubspotObjectInput-D9r_sGFe.mjs → HubspotObjectInput-DdLAUh0N.mjs} +3 -3
  7. package/dist/_chunks/{HubspotPropertyInput-Dk0t0NVe.js → HubspotPropertyInput-SnJMFsII.js} +3 -3
  8. package/dist/_chunks/{HubspotPropertyInput-av9782v6.mjs → HubspotPropertyInput-k7wMSmeF.mjs} +3 -3
  9. package/dist/_chunks/Settings-BMOmj4NJ.mjs +321 -0
  10. package/dist/_chunks/Settings-BPAAD-QW.js +339 -0
  11. package/dist/_chunks/en-CJ9wYHgN.mjs +197 -0
  12. package/dist/_chunks/en-C_-N8cjv.js +197 -0
  13. package/dist/_chunks/fr-BHObPoUp.js +197 -0
  14. package/dist/_chunks/fr-DttDn-2Y.mjs +197 -0
  15. package/dist/_chunks/{index-B3c9qEYU.js → index-D_CPrIHe.js} +12 -4
  16. package/dist/_chunks/{index-C0XHwXog.mjs → index-foVSGFWb.mjs} +12 -4
  17. package/dist/_chunks/{objectLabels-DwOMxLfh.mjs → objectLabels-C9ocOgVY.mjs} +1 -1
  18. package/dist/_chunks/{objectLabels-DksWJnOK.js → objectLabels-VTt_-qTZ.js} +1 -1
  19. package/dist/_chunks/{useHubspotSchema-C3vn1DuR.js → useHubspotSchema-B8SctALV.js} +1 -1
  20. package/dist/_chunks/{useHubspotSchema-BGtg7Ffj.mjs → useHubspotSchema-Du3rLY_O.mjs} +1 -1
  21. package/dist/admin/index.js +2 -1
  22. package/dist/admin/index.mjs +2 -1
  23. package/dist/admin/src/builder/ConditionEditor.d.ts +17 -0
  24. package/dist/admin/src/builder/FieldPanel.d.ts +16 -0
  25. package/dist/admin/src/builder/types.d.ts +90 -0
  26. package/dist/admin/src/index.d.ts +1 -0
  27. package/dist/admin/src/pages/FormEditor.d.ts +9 -0
  28. package/dist/admin/src/pages/Forms.d.ts +4 -0
  29. package/dist/admin/src/pages/FormsList.d.ts +8 -0
  30. package/dist/server/index.js +880 -5
  31. package/dist/server/index.mjs +880 -5
  32. package/dist/server/src/__tests__/conditions.test.d.ts +1 -0
  33. package/dist/server/src/__tests__/forms.test.d.ts +1 -0
  34. package/dist/server/src/__tests__/formsSubmit.test.d.ts +1 -0
  35. package/dist/server/src/__tests__/importLegacy.test.d.ts +1 -0
  36. package/dist/server/src/conditions.d.ts +88 -0
  37. package/dist/server/src/content-types.d.ts +161 -9
  38. package/dist/server/src/forms.d.ts +81 -0
  39. package/dist/server/src/formsAdmin.d.ts +39 -0
  40. package/dist/server/src/importLegacy.d.ts +25 -0
  41. package/dist/server/src/index.d.ts +214 -16
  42. package/dist/shared/types.d.ts +103 -0
  43. package/dist/shared/types.js +2 -0
  44. package/dist/shared/types.mjs +2 -0
  45. package/package.json +24 -6
  46. package/dist/_chunks/Settings-CPxe6LdH.js +0 -1311
  47. package/dist/_chunks/Settings-DTzk6GWO.mjs +0 -1293
  48. package/dist/_chunks/en-BN5fD3ai.js +0 -83
  49. package/dist/_chunks/en-xeTTAUtX.mjs +0 -83
  50. package/dist/_chunks/fr-BKODkfPy.mjs +0 -83
  51. package/dist/_chunks/fr-D3-oO8Lt.js +0 -83
package/CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ ## 0.6.1 — 2026-08-28
4
+
5
+ ### Fixed
6
+ - **Admin crash on the HubSpot Forms page** ("Error" with no message, from a
7
+ react-router invariant): `react-router-dom` was missing from
8
+ `peerDependencies`, so 0.6.0 shipped its own inlined copy — a second Router
9
+ context the plugin's `<Routes>` could not reach. It is now externalized to
10
+ the host admin's copy, like every other shared library.
11
+ - A `check-externals` step now runs on every build and fails when a
12
+ must-be-external library gets inlined, so this class of bug can't ship again.
13
+
14
+ ## 0.6.0 — 2026-08-28
15
+
16
+ The plugin becomes **the form builder for HubSpot**.
17
+
18
+ ### Added
19
+ - `plugin::hubspot.form` content type (draft & publish, i18n) with a versioned
20
+ JSON `definition` — steps → fields → conditions — hidden from the Content
21
+ Manager: the builder is its editor.
22
+ - **HubSpot Forms** admin page (new RBAC action `plugin::hubspot.forms`):
23
+ list, create, delete; builder with reorderable step/field cards, a field
24
+ panel reusing the portal pickers (object, property, enumeration option
25
+ import, deep link), and a condition editor (AND/OR, earlier fields only,
26
+ option-aware values).
27
+ - Conditional visibility for fields **and steps** — `eq`, `neq`, `contains`,
28
+ `empty`, `notEmpty`, `gt`, `lt` — enforced server-side at submission: hidden
29
+ fields lose `required` and their values never reach the CRM.
30
+ - Public content-api routes: `GET /api/hubspot/forms/:slug` (published form,
31
+ CRM mapping stripped) and `POST /api/hubspot/forms/:slug/submit`
32
+ (bounds-checked, conditions re-evaluated, contact upsert through the
33
+ existing retry/replay pipeline, optional company-by-corporate-domain +
34
+ association, optional timeline recap note).
35
+ - `plugin::hubspot.submission` collection — every submission stored, synced
36
+ or not, visible in the Content Manager.
37
+ - One-click **import** of legacy content-type forms (`forms.import.uid`,
38
+ attribute names remappable) — all locales, same slug, source untouched.
39
+ - Structural validation of definitions (duplicate names, forward/unknown
40
+ references, incomplete rules) blocking saves; mapping validation flagging
41
+ drafts and blocking publish.
42
+ - `strapi-plugin-hubspot/types` export: typed public payloads for host apps.
43
+ - ESLint (typescript-eslint + react-hooks) and a `lint` CI step.
44
+
45
+ ### Config
46
+ - New `forms` block: `companyFromDomain` (default `true`), `timelineNote`
47
+ (default `true`), `import` (off unless configured).
48
+
49
+ ## 0.5.0
50
+
51
+ - Shared schema cache across pickers, refresh button, auto-clear of a
52
+ property orphaned by an object switch.
53
+
54
+ ## 0.4.0
55
+
56
+ - Sending service (`submit.upsert`) with pre-validation, retries and the
57
+ failed-submissions replay queue; mapping audit; `hubspot.object` custom
58
+ field; enumeration option import; strict/non-strict validate targets;
59
+ admin i18n (en/fr); RBAC-gated settings; CI + npm publish workflows.
package/README.md CHANGED
@@ -1,9 +1,115 @@
1
1
  # Strapi HubSpot
2
2
 
3
- **Stop typing HubSpot property names from memory.** This plugin turns any CRM
4
- property field in your content types into a searchable picker fed by your actual
5
- portal, and refuses a bad mapping at save time instead of letting it fail
6
- silently three weeks later.
3
+ **The form builder for HubSpot** and the safety net under it.
4
+
5
+ Build multi-step lead forms in a dedicated admin page: fields mapped to your
6
+ portal's *real* CRM properties through a searchable picker, conditional fields
7
+ and steps (AND/OR rules re-evaluated server-side), a public API your frontend
8
+ renders and posts to, and a submission pipeline that upserts the Contact,
9
+ finds-or-creates the Company by corporate domain, drops a recap note on the
10
+ timeline, and stores every submission in Strapi whatever the CRM's mood.
11
+
12
+ Under it, the safety net this plugin has always been: property pickers as
13
+ custom fields for your own content types, save-time mapping validation, a
14
+ portal-wide audit, and a sending service with retries and a replay queue.
15
+
16
+ ## The form builder
17
+
18
+ **HubSpot Forms**, in the admin menu (RBAC-gated), is a builder page — not a
19
+ Content Manager view. Steps and fields are cards you reorder and configure;
20
+ the right-hand panel holds the selected field's settings, including its CRM
21
+ mapping picked from the portal (object select, property search, one-click
22
+ import of an enumeration's options, deep link to the property).
23
+
24
+ ### Conditional fields and steps
25
+
26
+ Any field or step can declare `visibleIf`: rules like *[field] [is] [value]*
27
+ combined with AND/OR. The editor only offers fields placed **earlier** in the
28
+ form, so evaluation is a single deterministic pass. Operators: `eq`, `neq`,
29
+ `contains`, `empty`, `notEmpty`, `gt`, `lt`.
30
+
31
+ Conditions are enforced **server-side at submission**, not just in the UI: a
32
+ hidden field loses its `required`, and its value is discarded even if the
33
+ browser sent it — the payload that reaches HubSpot is the payload the visitor
34
+ actually saw.
35
+
36
+ ### The public API
37
+
38
+ Two content-api routes (grant them to the Public role in **Settings → Users &
39
+ Permissions**):
40
+
41
+ | Method | Path | Purpose |
42
+ |---|---|---|
43
+ | `GET` | `/api/hubspot/forms/:slug?locale=` | The published form — meta, steps, fields, conditions. The CRM mapping is stripped: the browser never learns your property names |
44
+ | `POST` | `/api/hubspot/forms/:slug/submit` | Validates (bounds, conditions, required), maps server-side, syncs HubSpot, stores the submission |
45
+
46
+ The submit pipeline, in order: contact upsert (`email` is the find-or-create
47
+ key) through the plugin's sending service — pre-validation against the portal
48
+ schema (a stale mapping costs one answer, never the lead), retries, replay
49
+ queue; then, when the email is on a corporate domain, company found-or-created
50
+ by `domain` and associated to the contact; then a timeline note recapping the
51
+ answers and the lead's origin. Company and note are best-effort and can be
52
+ turned off:
53
+
54
+ ```ts
55
+ hubspot: {
56
+ config: {
57
+ forms: {
58
+ companyFromDomain: true, // Company by corporate domain + association
59
+ timelineNote: true, // recap note on the contact (and company)
60
+ },
61
+ },
62
+ }
63
+ ```
64
+
65
+ Every submission is stored in **HubSpot form submissions** (Content Manager),
66
+ synced or not, with the CRM ids when the sync succeeded — the source of truth
67
+ lives in your database, not in HubSpot's availability.
68
+
69
+ Typed payloads for your frontend:
70
+
71
+ ```ts
72
+ import type { PublicForm, SubmitRequest } from "strapi-plugin-hubspot/types";
73
+ ```
74
+
75
+ ### Importing existing forms
76
+
77
+ If your forms currently live in a content type (the `steps`/`fields` +
78
+ `hsObject`/`hsProperty` shape this README documents below), point the builder
79
+ at it:
80
+
81
+ ```ts
82
+ hubspot: {
83
+ config: {
84
+ forms: {
85
+ import: {
86
+ uid: "api::form.form",
87
+ // Optional remapping when your attribute names differ:
88
+ // steps: "etapes", fields: "champs",
89
+ // field: { label: "libelle", object: "objet", property: "propriete" },
90
+ },
91
+ },
92
+ },
93
+ }
94
+ ```
95
+
96
+ The list page then offers **Import an existing form**: one click converts the
97
+ entry — every locale — into a builder draft with the same slug. The source is
98
+ never modified, re-importing overwrites the draft only, and unpublishing rolls
99
+ a migrated form back. Migrate form by form; the validation middleware keeps
100
+ protecting the ones that stay.
101
+
102
+ ### i18n and publishing
103
+
104
+ Forms are draft & publish, localized like your content: `name` and `slug` are
105
+ shared, everything else — including the structure — is per-locale. Opening a
106
+ locale that doesn't exist yet starts it from the default locale's structure.
107
+ Publishing is blocked while a mapping problem remains; drafts save anyway,
108
+ with the problem flagged on the field carrying it.
109
+
110
+ ---
111
+
112
+ ## The safety net
7
113
 
8
114
  ## The problem it solves
9
115