strapi-plugin-hubspot 0.4.2 → 0.6.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +116 -4
  3. package/dist/_chunks/Forms-BF4_zA-m.js +1007 -0
  4. package/dist/_chunks/Forms-CW1KFO9U.mjs +989 -0
  5. package/dist/_chunks/{HubspotObjectInput-DutelVp6.mjs → HubspotObjectInput-CpxeM2J0.mjs} +4 -16
  6. package/dist/_chunks/{HubspotObjectInput-Br2jTFkG.js → HubspotObjectInput-hjAYWtaU.js} +4 -16
  7. package/dist/_chunks/HubspotPropertyInput-C-52Lu24.mjs +227 -0
  8. package/dist/_chunks/HubspotPropertyInput-OSeIBaRC.js +245 -0
  9. package/dist/_chunks/Settings-2V7TH5CX.mjs +321 -0
  10. package/dist/_chunks/Settings-DcA9M5Tw.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/{Settings-CQsB0B2T.mjs → index-C1UJXE_o.mjs} +576 -317
  16. package/dist/_chunks/{index-BUlB1rK9.js → index-CMzg-x5i.js} +12 -4
  17. package/dist/_chunks/{Settings-CvbKVl-t.js → index-Dgbid2LK.js} +580 -322
  18. package/dist/_chunks/{index-CKoBcX1T.mjs → index-DkGOTp8p.mjs} +12 -4
  19. package/dist/_chunks/{objectLabels-dM4o67Fz.mjs → objectLabels-D9UEuOGr.mjs} +1 -1
  20. package/dist/_chunks/{objectLabels-B76t8qqg.js → objectLabels-Th7aYW-B.js} +1 -1
  21. package/dist/_chunks/useHubspotSchema-Bgrgg8Mt.js +75 -0
  22. package/dist/_chunks/useHubspotSchema-DQkQcA_V.mjs +58 -0
  23. package/dist/admin/index.js +2 -1
  24. package/dist/admin/index.mjs +2 -1
  25. package/dist/admin/src/builder/ConditionEditor.d.ts +17 -0
  26. package/dist/admin/src/builder/FieldPanel.d.ts +16 -0
  27. package/dist/admin/src/builder/types.d.ts +90 -0
  28. package/dist/admin/src/index.d.ts +1 -0
  29. package/dist/admin/src/pages/FormEditor.d.ts +9 -0
  30. package/dist/admin/src/pages/Forms.d.ts +4 -0
  31. package/dist/admin/src/pages/FormsList.d.ts +8 -0
  32. package/dist/admin/src/useHubspotSchema.d.ts +28 -0
  33. package/dist/server/index.js +880 -5
  34. package/dist/server/index.mjs +880 -5
  35. package/dist/server/src/__tests__/conditions.test.d.ts +1 -0
  36. package/dist/server/src/__tests__/forms.test.d.ts +1 -0
  37. package/dist/server/src/__tests__/formsSubmit.test.d.ts +1 -0
  38. package/dist/server/src/__tests__/importLegacy.test.d.ts +1 -0
  39. package/dist/server/src/conditions.d.ts +88 -0
  40. package/dist/server/src/content-types.d.ts +161 -9
  41. package/dist/server/src/forms.d.ts +81 -0
  42. package/dist/server/src/formsAdmin.d.ts +39 -0
  43. package/dist/server/src/importLegacy.d.ts +25 -0
  44. package/dist/server/src/index.d.ts +214 -16
  45. package/dist/shared/types.d.ts +103 -0
  46. package/dist/shared/types.js +2 -0
  47. package/dist/shared/types.mjs +2 -0
  48. package/package.json +23 -6
  49. package/dist/_chunks/HubspotPropertyInput-CK6Yj9rC.mjs +0 -177
  50. package/dist/_chunks/HubspotPropertyInput-DIPDPRXJ.js +0 -195
  51. package/dist/_chunks/en-D4ueeUcJ.mjs +0 -82
  52. package/dist/_chunks/en-PBG7-vMR.js +0 -82
  53. package/dist/_chunks/fr-DL4wdV8I.js +0 -82
  54. package/dist/_chunks/fr-DYnxVmIO.mjs +0 -82
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The condition engine — pure functions, no Strapi.
3
+ */
4
+ export type Primitive = string | number | boolean;
5
+ export type Operator = "eq" | "neq" | "contains" | "empty" | "notEmpty" | "gt" | "lt";
6
+ export interface Rule {
7
+ /** Stable id (`fld_…`) of the field the rule reads — never its name. */
8
+ field: string;
9
+ operator: Operator;
10
+ value?: string;
11
+ }
12
+ export interface Condition {
13
+ logic: "and" | "or";
14
+ rules: Rule[];
15
+ }
16
+ export interface FormFieldDef {
17
+ id: string;
18
+ name: string;
19
+ label?: string;
20
+ type: string;
21
+ required?: boolean;
22
+ visibleIf?: Condition | null;
23
+ [key: string]: unknown;
24
+ }
25
+ export interface FormStepDef {
26
+ id: string;
27
+ title?: string;
28
+ visibleIf?: Condition | null;
29
+ fields: FormFieldDef[];
30
+ [key: string]: unknown;
31
+ }
32
+ export interface FormDefinition {
33
+ version: 1;
34
+ steps: FormStepDef[];
35
+ }
36
+ export interface SubmissionResolution {
37
+ /** Visible, non-empty values keyed by field name. */
38
+ values: Record<string, Primitive>;
39
+ /** Names of fields masked by a condition (their values were discarded). */
40
+ hidden: string[];
41
+ /** Visible required fields the submission left empty. */
42
+ missingRequired: {
43
+ id: string;
44
+ name: string;
45
+ label: string;
46
+ }[];
47
+ /** Submitted keys the definition doesn't declare (discarded). */
48
+ unknown: string[];
49
+ }
50
+ export type DefinitionError = {
51
+ code: "duplicate-name";
52
+ fieldId: string;
53
+ name: string;
54
+ } | {
55
+ code: "missing-name";
56
+ fieldId: string;
57
+ name: string;
58
+ } | {
59
+ code: "unknown-field";
60
+ fieldId?: string;
61
+ stepId?: string;
62
+ target: string;
63
+ } | {
64
+ code: "forward-reference";
65
+ fieldId?: string;
66
+ stepId?: string;
67
+ target: string;
68
+ } | {
69
+ code: "missing-value";
70
+ fieldId?: string;
71
+ stepId?: string;
72
+ target: string;
73
+ };
74
+ /**
75
+ * Structural check of a definition — what the builder enforces, re-checked
76
+ * server-side so a hand-crafted PUT can't save a form the engine can't run:
77
+ * unique non-empty names, and conditions that only look back.
78
+ */
79
+ export declare function validateDefinition(definition: FormDefinition): DefinitionError[];
80
+ /** An absent condition, or one with no rules, never hides anything. */
81
+ export declare function evaluateCondition(condition: Condition | null | undefined, get: (fieldId: string) => unknown): boolean;
82
+ /**
83
+ * Single pass in document order. The builder only lets a rule reference an
84
+ * earlier field, so by the time a condition is evaluated every field it can
85
+ * read has already been resolved — and a hidden one reads as `undefined`,
86
+ * which cascades: fields depending on it fall with it.
87
+ */
88
+ export declare function resolveSubmission(definition: FormDefinition, rawValues: Record<string, unknown>): SubmissionResolution;
@@ -1,13 +1,165 @@
1
- /**
2
- * The dead-letter queue for submissions HubSpot couldn't take: transient
3
- * failures land here after the in-process retries are exhausted, and
4
- * `retryFailures()` replays them.
5
- *
6
- * Visible in the Content Manager on purpose — an admin can inspect a stuck
7
- * payload and delete it — but hidden from the Content-Type Builder: its shape
8
- * belongs to the plugin.
9
- */
10
1
  declare const _default: {
2
+ /**
3
+ * A form built in the plugin's builder page. The flat, queryable identity
4
+ * lives as attributes; the structure (steps → fields → conditions) lives in
5
+ * `definition`, a versioned JSON document — plugins cannot ship components,
6
+ * and the builder is a better editor for it than the Content Manager, which
7
+ * is why the type is hidden there.
8
+ */
9
+ form: {
10
+ schema: {
11
+ kind: string;
12
+ collectionName: string;
13
+ info: {
14
+ singularName: string;
15
+ pluralName: string;
16
+ displayName: string;
17
+ description: string;
18
+ };
19
+ options: {
20
+ draftAndPublish: boolean;
21
+ };
22
+ pluginOptions: {
23
+ "content-manager": {
24
+ visible: boolean;
25
+ };
26
+ "content-type-builder": {
27
+ visible: boolean;
28
+ };
29
+ i18n: {
30
+ localized: boolean;
31
+ };
32
+ };
33
+ attributes: {
34
+ name: {
35
+ type: string;
36
+ required: boolean;
37
+ pluginOptions: {
38
+ i18n: {
39
+ localized: boolean;
40
+ };
41
+ };
42
+ };
43
+ slug: {
44
+ type: string;
45
+ targetField: string;
46
+ required: boolean;
47
+ };
48
+ title: {
49
+ type: "string" | "text";
50
+ pluginOptions: {
51
+ i18n: {
52
+ localized: boolean;
53
+ };
54
+ };
55
+ };
56
+ subtitle: {
57
+ type: "string" | "text";
58
+ pluginOptions: {
59
+ i18n: {
60
+ localized: boolean;
61
+ };
62
+ };
63
+ };
64
+ nextLabel: {
65
+ type: "string" | "text";
66
+ pluginOptions: {
67
+ i18n: {
68
+ localized: boolean;
69
+ };
70
+ };
71
+ };
72
+ submitLabel: {
73
+ type: "string" | "text";
74
+ pluginOptions: {
75
+ i18n: {
76
+ localized: boolean;
77
+ };
78
+ };
79
+ };
80
+ successMessage: {
81
+ type: "string" | "text";
82
+ pluginOptions: {
83
+ i18n: {
84
+ localized: boolean;
85
+ };
86
+ };
87
+ };
88
+ definition: {
89
+ type: string;
90
+ required: boolean;
91
+ pluginOptions: {
92
+ i18n: {
93
+ localized: boolean;
94
+ };
95
+ };
96
+ };
97
+ };
98
+ };
99
+ };
100
+ /**
101
+ * One visitor submission of a built form — the source of truth for the
102
+ * lead, stored whatever the CRM's mood. Visible in the Content Manager so
103
+ * the team can browse and export; hidden from the Content-Type Builder.
104
+ */
105
+ submission: {
106
+ schema: {
107
+ kind: string;
108
+ collectionName: string;
109
+ info: {
110
+ singularName: string;
111
+ pluralName: string;
112
+ displayName: string;
113
+ description: string;
114
+ };
115
+ options: {
116
+ draftAndPublish: boolean;
117
+ };
118
+ pluginOptions: {
119
+ "content-manager": {
120
+ visible: boolean;
121
+ };
122
+ "content-type-builder": {
123
+ visible: boolean;
124
+ };
125
+ };
126
+ attributes: {
127
+ form: {
128
+ type: string;
129
+ required: boolean;
130
+ };
131
+ formTitle: {
132
+ type: string;
133
+ };
134
+ email: {
135
+ type: string;
136
+ };
137
+ values: {
138
+ type: string;
139
+ required: boolean;
140
+ };
141
+ meta: {
142
+ type: string;
143
+ };
144
+ locale: {
145
+ type: string;
146
+ };
147
+ hubspotSynced: {
148
+ type: string;
149
+ default: boolean;
150
+ };
151
+ contactId: {
152
+ type: string;
153
+ };
154
+ companyId: {
155
+ type: string;
156
+ };
157
+ rejected: {
158
+ type: string;
159
+ };
160
+ };
161
+ };
162
+ };
11
163
  failure: {
12
164
  schema: {
13
165
  kind: string;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The form-builder server side: shaping a published form for the public API,
3
+ * and turning a submission into HubSpot upserts.
4
+ *
5
+ * The pipeline mirrors what a B2B lead capture needs: the person is upserted
6
+ * as a Contact (email is the dedup key); when the email is on a corporate
7
+ * domain the company is found-or-created by `domain` and associated to the
8
+ * contact; a timeline note recaps the whole submission for whoever picks the
9
+ * lead up. Company and note are best-effort — the contact is the lead.
10
+ */
11
+ import type { Core } from "@strapi/strapi";
12
+ import { type FormDefinition, type Primitive } from "./conditions";
13
+ import { checkMapping, type Problem } from "./properties";
14
+ export interface FormEntry {
15
+ name: string;
16
+ slug: string;
17
+ title?: string | null;
18
+ subtitle?: string | null;
19
+ nextLabel?: string | null;
20
+ submitLabel?: string | null;
21
+ successMessage?: string | null;
22
+ locale?: string | null;
23
+ definition: FormDefinition;
24
+ [key: string]: unknown;
25
+ }
26
+ export interface PublicForm {
27
+ slug: string;
28
+ title?: string | null;
29
+ subtitle?: string | null;
30
+ nextLabel?: string | null;
31
+ submitLabel?: string | null;
32
+ successMessage?: string | null;
33
+ locale?: string | null;
34
+ steps: FormDefinition["steps"];
35
+ }
36
+ /** The public shape: rendering meta + structure, minus the CRM mapping. */
37
+ export declare function publicForm(entry: FormEntry): PublicForm;
38
+ /**
39
+ * Resolved values → one property bag per CRM object. A field with no mapping
40
+ * writes to `contact` under its own name, like the legacy pipeline did.
41
+ */
42
+ export declare function groupByObject(definition: FormDefinition, values: Record<string, Primitive>): Record<string, Record<string, Primitive>>;
43
+ /**
44
+ * Every CRM mapping of a definition, checked against the portal schema — the
45
+ * builder's save-time equivalent of the content-type validation middleware.
46
+ * A select's own options are checked against the enumeration too.
47
+ */
48
+ export declare function mappingProblems(definition: FormDefinition, portalProperties: Parameters<typeof checkMapping>[0]): (Problem & {
49
+ fieldId: string;
50
+ })[];
51
+ /** First value that looks like an email — the field named `email` wins. */
52
+ export declare function findEmail(values: Record<string, unknown>): string | undefined;
53
+ export declare function corporateDomain(email?: string): string | undefined;
54
+ export declare const SUBMISSION_UID = "plugin::hubspot.submission";
55
+ /**
56
+ * The raw request body → a flat bag of primitives, or null when the shape is
57
+ * abusive (not an object, too many keys). Non-primitive values are dropped —
58
+ * the definition decides what counts anyway — and long strings are clipped.
59
+ */
60
+ export declare function sanitizeRawValues(raw: unknown): Record<string, Primitive> | null;
61
+ export interface SubmitMeta {
62
+ pagePath?: string;
63
+ pageUrl?: string;
64
+ originPath?: string;
65
+ originLabel?: string;
66
+ [key: string]: unknown;
67
+ }
68
+ export interface SubmitOutcome {
69
+ ok: boolean;
70
+ hubspotSynced?: boolean;
71
+ missingRequired?: {
72
+ id: string;
73
+ name: string;
74
+ label: string;
75
+ }[];
76
+ }
77
+ export declare function createFormsService(strapi: Core.Strapi, _opts?: {
78
+ sleep?: (ms: number) => Promise<void>;
79
+ }): {
80
+ submit: (form: FormEntry, rawValues: Record<string, unknown>, meta?: SubmitMeta) => Promise<SubmitOutcome>;
81
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The builder's own API — admin routes consumed by the Forms page. CRUD over
3
+ * `plugin::hubspot.form` through the Document Service (drafts, locales,
4
+ * publish), with the structural check and the mapping check applied where the
5
+ * Content Manager middleware can't reach: this content type is hidden there,
6
+ * the builder is its only editor.
7
+ */
8
+ import type { Core } from "@strapi/strapi";
9
+ export declare const FORM_UID = "plugin::hubspot.form";
10
+ export interface Ctx {
11
+ params: {
12
+ documentId?: string;
13
+ };
14
+ query: {
15
+ locale?: string;
16
+ };
17
+ request: {
18
+ body?: Record<string, unknown>;
19
+ };
20
+ body: unknown;
21
+ throw: (status: number, message: string) => never;
22
+ }
23
+ export declare function createFormsAdminController(strapi: Core.Strapi): {
24
+ list(ctx: Ctx): Promise<void>;
25
+ findOne(ctx: Ctx): Promise<void>;
26
+ create(ctx: Ctx): Promise<void>;
27
+ update(ctx: Ctx): Promise<void>;
28
+ publish(ctx: Ctx): Promise<void>;
29
+ unpublish(ctx: Ctx): Promise<void>;
30
+ /** Entries of the configured legacy content type, offered for import. */
31
+ listSources(ctx: Ctx): Promise<void>;
32
+ /**
33
+ * Converts one legacy entry (every locale of it) into a plugin form
34
+ * draft. Same slug: re-importing overwrites the draft, never touches the
35
+ * published version, and never modifies the source.
36
+ */
37
+ runImport(ctx: Ctx): Promise<void>;
38
+ remove(ctx: Ctx): Promise<void>;
39
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Conversion of a host-app form entry (content type + components) into the
3
+ * plugin's definition model — the migration path for forms built before the
4
+ * builder existed. The attribute names default to the shape this plugin's
5
+ * README always documented (steps/fields, hsObject/hsProperty) and every one
6
+ * of them can be remapped for a different host schema.
7
+ */
8
+ import type { FormDefinition } from "./conditions";
9
+ export interface ImportMap {
10
+ steps?: string;
11
+ fields?: string;
12
+ step?: Partial<Record<"title" | "description" | "class", string>>;
13
+ field?: Partial<Record<"label" | "name" | "object" | "property" | "type" | "placeholder" | "required" | "icon" | "options" | "width" | "helpText" | "class" | "persist", string>>;
14
+ }
15
+ export interface ConvertedForm {
16
+ name: string;
17
+ slug: string;
18
+ title?: string | null;
19
+ subtitle?: string | null;
20
+ nextLabel?: string | null;
21
+ submitLabel?: string | null;
22
+ successMessage?: string | null;
23
+ definition: FormDefinition;
24
+ }
25
+ export declare function convertLegacyForm(entry: Record<string, unknown>, map?: ImportMap): ConvertedForm;
@@ -1,4 +1,5 @@
1
1
  import type { Core } from "@strapi/strapi";
2
+ import { type FormEntry, type SubmitMeta } from "./forms";
2
3
  import { type ValidateTarget } from "./validation";
3
4
  declare const _default: {
4
5
  config: {
@@ -6,29 +7,166 @@ declare const _default: {
6
7
  apiKey: string;
7
8
  objects: unknown[];
8
9
  validate: ValidateTarget[];
10
+ forms: {
11
+ companyFromDomain: boolean;
12
+ timelineNote: boolean;
13
+ };
9
14
  };
10
15
  validator(cfg: {
11
16
  validate?: unknown;
12
17
  }): void;
13
18
  };
14
19
  contentTypes: {
20
+ form: {
21
+ schema: {
22
+ kind: string;
23
+ collectionName: string;
24
+ info: {
25
+ singularName: string; /** RBAC action gating the settings screen and its routes. */
26
+ pluralName: string;
27
+ displayName: string;
28
+ description: string;
29
+ };
30
+ options: {
31
+ draftAndPublish: boolean;
32
+ };
33
+ pluginOptions: {
34
+ "content-manager": {
35
+ visible: boolean;
36
+ };
37
+ "content-type-builder": {
38
+ visible: boolean;
39
+ };
40
+ i18n: {
41
+ localized: boolean;
42
+ };
43
+ };
44
+ attributes: {
45
+ name: {
46
+ type: string;
47
+ required: boolean;
48
+ pluginOptions: {
49
+ i18n: {
50
+ localized: boolean;
51
+ };
52
+ };
53
+ };
54
+ slug: {
55
+ type: string;
56
+ targetField: string;
57
+ required: boolean;
58
+ };
59
+ title: {
60
+ type: "string" | "text";
61
+ pluginOptions: {
62
+ i18n: {
63
+ localized: boolean;
64
+ };
65
+ };
66
+ };
67
+ subtitle: {
68
+ type: "string" | "text";
69
+ pluginOptions: {
70
+ i18n: {
71
+ localized: boolean;
72
+ };
73
+ };
74
+ };
75
+ nextLabel: {
76
+ type: "string" | "text";
77
+ pluginOptions: {
78
+ i18n: {
79
+ localized: boolean;
80
+ };
81
+ };
82
+ };
83
+ submitLabel: {
84
+ type: "string" | "text";
85
+ pluginOptions: {
86
+ i18n: {
87
+ localized: boolean;
88
+ };
89
+ };
90
+ };
91
+ successMessage: {
92
+ type: "string" | "text";
93
+ pluginOptions: {
94
+ i18n: {
95
+ localized: boolean;
96
+ };
97
+ };
98
+ };
99
+ definition: {
100
+ type: string;
101
+ required: boolean;
102
+ pluginOptions: {
103
+ i18n: {
104
+ localized: boolean;
105
+ };
106
+ };
107
+ };
108
+ };
109
+ };
110
+ };
111
+ submission: {
112
+ schema: {
113
+ kind: string;
114
+ collectionName: string;
115
+ info: {
116
+ singularName: string;
117
+ pluralName: string;
118
+ displayName: string;
119
+ description: string;
120
+ };
121
+ options: {
122
+ draftAndPublish: boolean;
123
+ };
124
+ pluginOptions: {
125
+ "content-manager": {
126
+ visible: boolean;
127
+ };
128
+ "content-type-builder": {
129
+ visible: boolean;
130
+ };
131
+ };
132
+ attributes: {
133
+ form: {
134
+ type: string;
135
+ required: boolean;
136
+ };
137
+ formTitle: {
138
+ type: string;
139
+ };
140
+ email: {
141
+ type: string;
142
+ };
143
+ values: {
144
+ type: string;
145
+ required: boolean;
146
+ };
147
+ meta: {
148
+ type: string;
149
+ };
150
+ locale: {
151
+ type: string;
152
+ };
153
+ hubspotSynced: {
154
+ type: string;
155
+ default: boolean;
156
+ };
157
+ contactId: {
158
+ type: string;
159
+ };
160
+ companyId: {
161
+ type: string;
162
+ };
163
+ rejected: {
164
+ type: string;
165
+ };
166
+ };
167
+ };
168
+ };
15
169
  failure: {
16
- /**
17
- * Plugin configuration (config/plugins.ts of the host app):
18
- *
19
- * hubspot: {
20
- * enabled: true,
21
- * config: {
22
- * apiKey: env("HUBSPOT_API_KEY"), // optional — can be set from the admin UI
23
- * validate: [ // optional — entries whose mappings are checked on save
24
- * { uid: "api::form.form", objectField: "hsObject", propertyField: "hsProperty" },
25
- * ],
26
- * },
27
- * }
28
- *
29
- * The API key set from the admin UI takes precedence over both.
30
- */
31
- /** RBAC action gating the settings screen and its routes. */
32
170
  schema: {
33
171
  kind: string;
34
172
  collectionName: string;
@@ -103,6 +241,50 @@ declare const _default: {
103
241
  body: unknown;
104
242
  }): Promise<void>;
105
243
  };
244
+ formsAdmin: ({ strapi }: {
245
+ strapi: Core.Strapi;
246
+ }) => {
247
+ list(ctx: import("./formsAdmin").Ctx): Promise<void>;
248
+ findOne(ctx: import("./formsAdmin").Ctx): Promise<void>;
249
+ create(ctx: import("./formsAdmin").Ctx): Promise<void>;
250
+ update(ctx: import("./formsAdmin").Ctx): Promise<void>;
251
+ publish(ctx: import("./formsAdmin").Ctx): Promise<void>;
252
+ unpublish(ctx: import("./formsAdmin").Ctx): Promise<void>;
253
+ listSources(ctx: import("./formsAdmin").Ctx): Promise<void>;
254
+ runImport(ctx: import("./formsAdmin").Ctx): Promise<void>;
255
+ remove(ctx: import("./formsAdmin").Ctx): Promise<void>;
256
+ };
257
+ forms: ({ strapi }: {
258
+ strapi: Core.Strapi;
259
+ }) => {
260
+ /** Published form for the host frontend — CRM mapping stripped. */
261
+ findOne(ctx: {
262
+ params: {
263
+ slug: string;
264
+ };
265
+ query: {
266
+ locale?: string;
267
+ };
268
+ body: unknown;
269
+ throw: (s: number, m: string) => never;
270
+ }): Promise<void>;
271
+ submit(ctx: {
272
+ params: {
273
+ slug: string;
274
+ };
275
+ query: {
276
+ locale?: string;
277
+ };
278
+ request: {
279
+ body?: {
280
+ values?: unknown;
281
+ meta?: Record<string, unknown>;
282
+ };
283
+ };
284
+ body: unknown;
285
+ throw: (s: number, m: string) => never;
286
+ }): Promise<void>;
287
+ };
106
288
  settings: ({ strapi }: {
107
289
  strapi: Core.Strapi;
108
290
  }) => {
@@ -139,6 +321,17 @@ declare const _default: {
139
321
  };
140
322
  }[];
141
323
  };
324
+ "content-api": {
325
+ type: string;
326
+ routes: {
327
+ method: string;
328
+ path: string;
329
+ handler: string;
330
+ config: {
331
+ policies: any[];
332
+ };
333
+ }[];
334
+ };
142
335
  };
143
336
  services: {
144
337
  submit: ({ strapi }: {
@@ -155,6 +348,11 @@ declare const _default: {
155
348
  failed: number;
156
349
  }>;
157
350
  };
351
+ forms: ({ strapi }: {
352
+ strapi: Core.Strapi;
353
+ }) => {
354
+ submit: (form: FormEntry, rawValues: Record<string, unknown>, meta?: SubmitMeta) => Promise<import("./forms").SubmitOutcome>;
355
+ };
158
356
  };
159
357
  register({ strapi }: {
160
358
  strapi: Core.Strapi;