@nextlyhq/plugin-form-builder 0.0.2-alpha.7 → 0.0.2-alpha.70

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 (39) hide show
  1. package/README.md +22 -16
  2. package/dist/admin/index.d.ts +251 -454
  3. package/dist/admin/index.js +4782 -3985
  4. package/dist/admin/index.js.map +1 -1
  5. package/dist/field-references-BshlgMcn.js +1048 -0
  6. package/dist/field-references-BshlgMcn.js.map +1 -0
  7. package/dist/index.d.ts +341 -615
  8. package/dist/index.js +3893 -2406
  9. package/dist/index.js.map +1 -1
  10. package/dist/types-BHReIA0j.d.ts +986 -0
  11. package/package.json +40 -39
  12. package/dist/CheckboxFieldEditor-K4T6QX52.js +0 -121
  13. package/dist/CheckboxFieldEditor-K4T6QX52.js.map +0 -1
  14. package/dist/DateFieldEditor-JFJFAVOH.js +0 -187
  15. package/dist/DateFieldEditor-JFJFAVOH.js.map +0 -1
  16. package/dist/EmailFieldEditor-MMOXXL7P.js +0 -138
  17. package/dist/EmailFieldEditor-MMOXXL7P.js.map +0 -1
  18. package/dist/NumberFieldEditor-UISAYR6Z.js +0 -175
  19. package/dist/NumberFieldEditor-UISAYR6Z.js.map +0 -1
  20. package/dist/RadioFieldEditor-6UQFH4WT.js +0 -165
  21. package/dist/RadioFieldEditor-6UQFH4WT.js.map +0 -1
  22. package/dist/SelectFieldEditor-PSO4KHV4.js +0 -213
  23. package/dist/SelectFieldEditor-PSO4KHV4.js.map +0 -1
  24. package/dist/TextFieldEditor-5EU64EA5.js +0 -187
  25. package/dist/TextFieldEditor-5EU64EA5.js.map +0 -1
  26. package/dist/TextareaFieldEditor-773G3LNM.js +0 -190
  27. package/dist/TextareaFieldEditor-773G3LNM.js.map +0 -1
  28. package/dist/admin/index.css +0 -934
  29. package/dist/admin/index.css.map +0 -1
  30. package/dist/chunk-ABNZFTQK.js +0 -586
  31. package/dist/chunk-ABNZFTQK.js.map +0 -1
  32. package/dist/chunk-XTCEPJ7B.js +0 -256
  33. package/dist/chunk-XTCEPJ7B.js.map +0 -1
  34. package/dist/components/index.d.ts +0 -3
  35. package/dist/components/index.js +0 -9
  36. package/dist/components/index.js.map +0 -1
  37. package/dist/index-C0kBvYjm.d.ts +0 -1012
  38. package/dist/styles/form-builder.css +0 -1150
  39. package/dist/styles/submissions-filter.css +0 -75
package/dist/index.d.ts CHANGED
@@ -1,28 +1,15 @@
1
- import * as nextly from 'nextly';
2
- import { PluginDefinition, CollectionConfig, PluginContext } from 'nextly';
3
- import { R as ResolvedFormBuilderConfig, F as FormBuilderPluginOptions, a as FormConfig, b as FormSettings, c as FormNotifications, C as CheckboxFormField, D as DateFormField, E as EmailFormField, d as FileFormField, H as HiddenFormField, N as NumberFormField, P as PhoneFormField, e as RadioFormField, S as SelectFormField, T as TextFormField, f as TextareaFormField, g as TimeFormField, U as UrlFormField, h as ConditionalLogic, i as FormField, j as SubmissionDocument, k as FormDocument, W as WebhookEvent } from './index-C0kBvYjm.js';
4
- export { B as BaseFormField, l as ConditionalLogicCondition, m as EmailConfig, n as FieldBlockConfig, o as FormAccess, p as FormFieldType, q as FormHookContext, r as FormHooks, s as FormSubmission, t as SubmissionDetailProps, u as SubmissionListProps, V as ValidationRules, v as WebhookConfig, w as isCheckboxFormField, x as isEmailFormField, y as isFileFormField, z as isFormField, A as isFormFieldType, G as isSelectFormField, I as isTextFormField } from './index-C0kBvYjm.js';
5
- import { z } from 'zod';
6
- import 'react';
7
-
8
- /**
9
- * Form Builder Plugin
10
- *
11
- * Visual form builder with drag-and-drop UI, submission management,
12
- * email notifications, and spam protection.
13
- *
14
- * @module plugin
15
- * @since 0.1.0
16
- */
17
-
1
+ import { A as RadioFormField, B as isEmailFormField, C as FormNotificationItem, D as HiddenFormField, E as FormSubmission, F as TextareaFormField, G as isSelectFormField, H as isFormField, I as TimeFormField, K as isTextFormField, L as UrlFormField, M as SelectFormField, N as SubmissionDocument, O as NumberFormField, P as TextFormField, R as ValidationRules, S as FormNotification, T as FormSettings, U as isFormFieldType, V as isFileFormField, W as isKnownFormField, _ as FormField, a as ConditionalLogic, b as FormHookContext, c as DateFormField, d as FieldBlockConfig, f as FileFormField, g as FormDocument, h as FormConfig, i as CheckboxFormField, j as ResolvedFormBuilderConfig, k as PhoneFormField, l as EmailConfig, m as FormBuilderPluginOptions, n as BUILT_IN_FORM_FIELD_TYPES, o as ConditionalLogicCondition, p as FormAccess, r as BaseFormField, s as CustomFormField, t as AnyFormField, u as EmailFormField, v as FormFieldType, w as FormNotifications, x as FormHooks, y as FormFieldTypeId, z as isCheckboxFormField } from "./types-BHReIA0j.js";
2
+ import { PluginDefinition } from "@nextlyhq/plugin-sdk";
3
+ import { CollectionConfig, PluginContext } from "nextly";
4
+ import { z } from "zod";
18
5
  type NextlyPlugin = PluginDefinition;
19
6
  interface FormBuilderPluginResult {
20
- /** Plugin definition — pass to `defineConfig({ plugins: [...] })`. */
21
- plugin: NextlyPlugin;
22
- /** Forms & Submissions collections (also auto-added by the plugin). */
23
- collections: CollectionConfig[];
24
- /** Resolved configuration with all defaults applied. */
25
- config: ResolvedFormBuilderConfig;
7
+ /** Plugin definition — pass to `defineConfig({ plugins: [...] })`. */
8
+ plugin: NextlyPlugin;
9
+ /** Forms & Submissions collections (also auto-added by the plugin). */
10
+ collections: CollectionConfig[];
11
+ /** Resolved configuration with all defaults applied. */
12
+ config: ResolvedFormBuilderConfig;
26
13
  }
27
14
  /**
28
15
  * Create a Form Builder plugin instance.
@@ -51,41 +38,16 @@ interface FormBuilderPluginResult {
51
38
  * });
52
39
  * ```
53
40
  */
54
- declare function formBuilder(options?: FormBuilderPluginOptions): FormBuilderPluginResult;
41
+ export declare function formBuilder(options?: FormBuilderPluginOptions): FormBuilderPluginResult;
55
42
  /**
56
43
  * Retrieve the resolved Form Builder config from a Nextly plugin context.
57
44
  */
58
- declare function getFormBuilderConfig(nextly: unknown): ResolvedFormBuilderConfig | undefined;
59
-
60
- /**
61
- * Form Configuration Validator
62
- *
63
- * Provides comprehensive validation for form configurations including:
64
- * - Slug validation (format, reserved names)
65
- * - Field name validation (format, duplicates)
66
- * - Field-specific validation (select/radio options, min/max constraints)
67
- * - Conditional logic validation
68
- * - Nested field validation
69
- *
70
- * @module config/validate-form
71
- * @since 1.0.0
72
- *
73
- * @example
74
- * ```typescript
75
- * import { validateFormConfig } from '@nextly/plugin-form-builder';
76
- *
77
- * const result = validateFormConfig(config);
78
- * if (!result.valid) {
79
- * console.error('Validation errors:', result.errors);
80
- * }
81
- * ```
82
- */
83
-
45
+ export declare function getFormBuilderConfig(nextly: unknown): ResolvedFormBuilderConfig | undefined;
84
46
  /**
85
47
  * Error codes for form validation failures.
86
48
  * Used for programmatic error handling.
87
49
  */
88
- type FormValidationErrorCode = "SLUG_REQUIRED" | "SLUG_INVALID_TYPE" | "SLUG_TOO_SHORT" | "SLUG_TOO_LONG" | "SLUG_INVALID_FORMAT" | "SLUG_RESERVED" | "FIELDS_REQUIRED" | "FIELDS_INVALID_TYPE" | "FIELDS_EMPTY" | "FIELD_NAME_REQUIRED" | "FIELD_NAME_INVALID_FORMAT" | "FIELD_NAME_DUPLICATE" | "FIELD_TYPE_REQUIRED" | "FIELD_TYPE_INVALID" | "FIELD_LABEL_REQUIRED" | "OPTIONS_REQUIRED" | "OPTIONS_EMPTY" | "MIN_GREATER_THAN_MAX" | "MIN_LENGTH_GREATER_THAN_MAX" | "FILE_MAX_SIZE_INVALID" | "CONDITIONS_REQUIRED" | "CONDITION_FIELD_REQUIRED" | "CONDITION_COMPARISON_REQUIRED" | "SETTINGS_INVALID_TYPE" | "REDIRECT_URL_REQUIRED" | "ACCESS_INVALID_TYPE" | "ACCESS_FUNCTION_INVALID";
50
+ type FormValidationErrorCode = "SLUG_REQUIRED" | "SLUG_INVALID_TYPE" | "SLUG_TOO_SHORT" | "SLUG_TOO_LONG" | "SLUG_INVALID_FORMAT" | "SLUG_RESERVED" | "FIELDS_REQUIRED" | "FIELDS_INVALID_TYPE" | "FIELDS_EMPTY" | "FIELD_NAME_REQUIRED" | "FIELD_NAME_INVALID_FORMAT" | "FIELD_NAME_DUPLICATE" | "FIELD_TYPE_REQUIRED" | "FIELD_TYPE_INVALID" | "FIELD_LABEL_REQUIRED" | "OPTIONS_REQUIRED" | "OPTIONS_EMPTY" | "MIN_GREATER_THAN_MAX" | "MIN_LENGTH_GREATER_THAN_MAX" | "FILE_MAX_SIZE_INVALID" | "CONDITIONS_REQUIRED" | "CONDITION_FIELD_REQUIRED" | "CONDITION_COMPARISON_REQUIRED" | "SETTINGS_INVALID_TYPE" | "REDIRECT_URL_REQUIRED" | "REDIRECT_PAGE_REQUIRED" | "ACCESS_INVALID_TYPE" | "ACCESS_FUNCTION_INVALID";
89
51
  /**
90
52
  * A single validation error with path and context.
91
53
  *
@@ -99,38 +61,38 @@ type FormValidationErrorCode = "SLUG_REQUIRED" | "SLUG_INVALID_TYPE" | "SLUG_TOO
99
61
  * ```
100
62
  */
101
63
  interface FormValidationError {
102
- /**
103
- * Dot-notation path to the invalid property.
104
- * @example 'slug', 'fields.0.name', 'fields.email.options'
105
- */
106
- path: string;
107
- /**
108
- * Human-readable error message.
109
- */
110
- message: string;
111
- /**
112
- * Machine-readable error code for programmatic handling.
113
- */
114
- code: FormValidationErrorCode;
64
+ /**
65
+ * Dot-notation path to the invalid property.
66
+ * @example 'slug', 'fields.0.name', 'fields.email.options'
67
+ */
68
+ path: string;
69
+ /**
70
+ * Human-readable error message.
71
+ */
72
+ message: string;
73
+ /**
74
+ * Machine-readable error code for programmatic handling.
75
+ */
76
+ code: FormValidationErrorCode;
115
77
  }
116
78
  /**
117
79
  * Result of form config validation.
118
80
  */
119
81
  interface FormValidationResult {
120
- /**
121
- * Whether the configuration is valid.
122
- */
123
- valid: boolean;
124
- /**
125
- * Array of validation errors (empty if valid).
126
- */
127
- errors: FormValidationError[];
82
+ /**
83
+ * Whether the configuration is valid.
84
+ */
85
+ valid: boolean;
86
+ /**
87
+ * Array of validation errors (empty if valid).
88
+ */
89
+ errors: FormValidationError[];
128
90
  }
129
91
  /**
130
92
  * Reserved form slugs that cannot be used.
131
93
  * These are used by the system or have special meaning.
132
94
  */
133
- declare const RESERVED_FORM_SLUGS: readonly ["api", "submit", "submissions", "export", "admin", "new", "create", "edit", "delete"];
95
+ export declare const RESERVED_FORM_SLUGS: readonly ["api", "submit", "submissions", "export", "admin", "new", "create", "edit", "delete"];
134
96
  /**
135
97
  * Validates a complete form configuration.
136
98
  *
@@ -168,7 +130,7 @@ declare const RESERVED_FORM_SLUGS: readonly ["api", "submit", "submissions", "ex
168
130
  * }
169
131
  * ```
170
132
  */
171
- declare function validateFormConfig(config: FormConfig): FormValidationResult;
133
+ export declare function validateFormConfig(config: FormConfig): FormValidationResult;
172
134
  /**
173
135
  * Throws an error if the form configuration is invalid.
174
136
  *
@@ -186,42 +148,15 @@ declare function validateFormConfig(config: FormConfig): FormValidationResult;
186
148
  * assertValidFormConfig(config);
187
149
  * ```
188
150
  */
189
- declare function assertValidFormConfig(config: FormConfig): void;
190
-
191
- /**
192
- * Form Configuration Defaults
193
- *
194
- * Applies default values to form configurations, ensuring all required
195
- * properties have sensible defaults while preserving user-specified values.
196
- *
197
- * @module config/defaults
198
- * @since 1.0.0
199
- *
200
- * @example
201
- * ```typescript
202
- * import { applyFormDefaults } from '@nextly/plugin-form-builder';
203
- *
204
- * const config = {
205
- * slug: 'contact-form',
206
- * fields: [
207
- * { type: 'text', name: 'name', label: 'Name' },
208
- * { type: 'email', name: 'email', label: 'Email' },
209
- * ],
210
- * };
211
- *
212
- * const configWithDefaults = applyFormDefaults(config);
213
- * // configWithDefaults now has labels, settings, etc. with defaults applied
214
- * ```
215
- */
216
-
151
+ export declare function assertValidFormConfig(config: FormConfig): void;
217
152
  /**
218
153
  * Default form settings.
219
154
  */
220
- declare const DEFAULT_FORM_SETTINGS: Required<Pick<FormSettings, "submitButtonText" | "confirmationType" | "successMessage" | "allowMultipleSubmissions">>;
155
+ export declare const DEFAULT_FORM_SETTINGS: Required<Pick<FormSettings, "submitButtonText" | "confirmationType" | "successMessage" | "allowMultipleSubmissions">>;
221
156
  /**
222
157
  * Default notification settings.
223
158
  */
224
- declare const DEFAULT_NOTIFICATION_SETTINGS: Pick<FormNotifications, "enabled" | "replyTo">;
159
+ export declare const DEFAULT_NOTIFICATION_SETTINGS: Pick<FormNotifications, "enabled" | "replyTo">;
225
160
  /**
226
161
  * Converts a slug to title case.
227
162
  *
@@ -234,7 +169,7 @@ declare const DEFAULT_NOTIFICATION_SETTINGS: Pick<FormNotifications, "enabled" |
234
169
  * toTitleCase('newsletter_signup'); // 'Newsletter Signup'
235
170
  * ```
236
171
  */
237
- declare function toTitleCase(str: string): string;
172
+ export declare function toTitleCase(str: string): string;
238
173
  /**
239
174
  * Generates a plural form from a singular label.
240
175
  * Handles common English pluralization rules.
@@ -249,7 +184,7 @@ declare function toTitleCase(str: string): string;
249
184
  * pluralize('Quiz'); // 'Quizzes'
250
185
  * ```
251
186
  */
252
- declare function pluralize(singular: string): string;
187
+ export declare function pluralize(singular: string): string;
253
188
  /**
254
189
  * Apply default values to form configuration.
255
190
  *
@@ -292,7 +227,7 @@ declare function pluralize(singular: string): string;
292
227
  * // }
293
228
  * ```
294
229
  */
295
- declare function applyFormDefaults(config: FormConfig): FormConfig;
230
+ export declare function applyFormDefaults(config: FormConfig): FormConfig;
296
231
  /**
297
232
  * Apply default values to individual form field.
298
233
  *
@@ -311,11 +246,11 @@ declare function applyFormDefaults(config: FormConfig): FormConfig;
311
246
  * // { type: 'text', name: 'firstName', label: 'First Name', required: false }
312
247
  * ```
313
248
  */
314
- declare function applyFieldDefaults<T extends {
315
- type: string;
316
- name?: string;
317
- label?: string;
318
- required?: boolean;
249
+ export declare function applyFieldDefaults<T extends {
250
+ type: string;
251
+ name?: string;
252
+ label?: string;
253
+ required?: boolean;
319
254
  }>(field: T): T;
320
255
  /**
321
256
  * Creates a complete form config with minimal input.
@@ -339,51 +274,13 @@ declare function applyFieldDefaults<T extends {
339
274
  * ]);
340
275
  * ```
341
276
  */
342
- declare function createFormConfig(slug: string, fields: FormConfig["fields"], options?: Partial<Omit<FormConfig, "slug" | "fields">>): FormConfig;
343
-
344
- /**
345
- * Form Field Helpers
346
- *
347
- * Convenient factory functions for creating form field configurations.
348
- * These helpers eliminate the need to manually specify the `type` property,
349
- * providing a cleaner, more ergonomic API for form definitions.
350
- *
351
- * @module config/field-helpers
352
- *
353
- * @example
354
- * ```typescript
355
- * import {
356
- * text,
357
- * email,
358
- * select,
359
- * checkbox,
360
- * option,
361
- * } from '@nextly/plugin-form-builder';
362
- *
363
- * const contactFormFields = [
364
- * text({ name: 'firstName', label: 'First Name', required: true }),
365
- * text({ name: 'lastName', label: 'Last Name', required: true }),
366
- * email({ name: 'email', label: 'Email Address', required: true }),
367
- * select({
368
- * name: 'subject',
369
- * label: 'Subject',
370
- * options: [
371
- * option('General Inquiry'),
372
- * option('Support Request'),
373
- * option('Feedback'),
374
- * ],
375
- * }),
376
- * checkbox({ name: 'subscribe', label: 'Subscribe to newsletter' }),
377
- * ];
378
- * ```
379
- */
380
-
277
+ export declare function createFormConfig(slug: string, fields: FormConfig["fields"], options?: Partial<Omit<FormConfig, "slug" | "fields">>): FormConfig;
381
278
  /**
382
279
  * Option for select and radio fields.
383
280
  */
384
281
  interface FormFieldOption {
385
- label: string;
386
- value: string;
282
+ label: string;
283
+ value: string;
387
284
  }
388
285
  /**
389
286
  * Creates an option for select or radio fields.
@@ -415,7 +312,7 @@ interface FormFieldOption {
415
312
  * })
416
313
  * ```
417
314
  */
418
- declare const option: (label: string, value?: string) => FormFieldOption;
315
+ export declare const option: (label: string, value?: string) => FormFieldOption;
419
316
  /**
420
317
  * Creates a text input field configuration.
421
318
  *
@@ -444,7 +341,7 @@ declare const option: (label: string, value?: string) => FormFieldOption;
444
341
  * })
445
342
  * ```
446
343
  */
447
- declare const text: (config: Omit<TextFormField, "type">) => TextFormField;
344
+ export declare const text: (config: Omit<TextFormField, "type">) => TextFormField;
448
345
  /**
449
346
  * Creates an email input field configuration.
450
347
  *
@@ -463,11 +360,11 @@ declare const text: (config: Omit<TextFormField, "type">) => TextFormField;
463
360
  * name: 'workEmail',
464
361
  * label: 'Work Email',
465
362
  * required: true,
466
- * placeholder: 'you@company.com',
363
+ * placeholder: 'you@nextly.local',
467
364
  * })
468
365
  * ```
469
366
  */
470
- declare const email: (config: Omit<EmailFormField, "type">) => EmailFormField;
367
+ export declare const email: (config: Omit<EmailFormField, "type">) => EmailFormField;
471
368
  /**
472
369
  * Creates a phone input field configuration.
473
370
  *
@@ -490,7 +387,7 @@ declare const email: (config: Omit<EmailFormField, "type">) => EmailFormField;
490
387
  * })
491
388
  * ```
492
389
  */
493
- declare const phone: (config: Omit<PhoneFormField, "type">) => PhoneFormField;
390
+ export declare const phone: (config: Omit<PhoneFormField, "type">) => PhoneFormField;
494
391
  /**
495
392
  * Creates a URL input field configuration.
496
393
  *
@@ -512,7 +409,7 @@ declare const phone: (config: Omit<PhoneFormField, "type">) => PhoneFormField;
512
409
  * })
513
410
  * ```
514
411
  */
515
- declare const url: (config: Omit<UrlFormField, "type">) => UrlFormField;
412
+ export declare const url: (config: Omit<UrlFormField, "type">) => UrlFormField;
516
413
  /**
517
414
  * Creates a textarea field configuration.
518
415
  *
@@ -539,7 +436,7 @@ declare const url: (config: Omit<UrlFormField, "type">) => UrlFormField;
539
436
  * })
540
437
  * ```
541
438
  */
542
- declare const textarea: (config: Omit<TextareaFormField, "type">) => TextareaFormField;
439
+ export declare const textarea: (config: Omit<TextareaFormField, "type">) => TextareaFormField;
543
440
  /**
544
441
  * Creates a number input field configuration.
545
442
  *
@@ -567,7 +464,7 @@ declare const textarea: (config: Omit<TextareaFormField, "type">) => TextareaFor
567
464
  * })
568
465
  * ```
569
466
  */
570
- declare const number: (config: Omit<NumberFormField, "type">) => NumberFormField;
467
+ export declare const number: (config: Omit<NumberFormField, "type">) => NumberFormField;
571
468
  /**
572
469
  * Creates a select dropdown field configuration.
573
470
  *
@@ -604,7 +501,7 @@ declare const number: (config: Omit<NumberFormField, "type">) => NumberFormField
604
501
  * })
605
502
  * ```
606
503
  */
607
- declare const select: (config: Omit<SelectFormField, "type">) => SelectFormField;
504
+ export declare const select: (config: Omit<SelectFormField, "type">) => SelectFormField;
608
505
  /**
609
506
  * Creates a single checkbox field configuration.
610
507
  *
@@ -630,7 +527,7 @@ declare const select: (config: Omit<SelectFormField, "type">) => SelectFormField
630
527
  * })
631
528
  * ```
632
529
  */
633
- declare const checkbox: (config: Omit<CheckboxFormField, "type">) => CheckboxFormField;
530
+ export declare const checkbox: (config: Omit<CheckboxFormField, "type">) => CheckboxFormField;
634
531
  /**
635
532
  * Creates a radio group field configuration.
636
533
  *
@@ -654,7 +551,7 @@ declare const checkbox: (config: Omit<CheckboxFormField, "type">) => CheckboxFor
654
551
  * })
655
552
  * ```
656
553
  */
657
- declare const radio: (config: Omit<RadioFormField, "type">) => RadioFormField;
554
+ export declare const radio: (config: Omit<RadioFormField, "type">) => RadioFormField;
658
555
  /**
659
556
  * Creates a file upload field configuration.
660
557
  *
@@ -685,7 +582,7 @@ declare const radio: (config: Omit<RadioFormField, "type">) => RadioFormField;
685
582
  * })
686
583
  * ```
687
584
  */
688
- declare const file: (config: Omit<FileFormField, "type">) => FileFormField;
585
+ export declare const file: (config: Omit<FileFormField, "type">) => FileFormField;
689
586
  /**
690
587
  * Creates a date picker field configuration.
691
588
  *
@@ -709,7 +606,7 @@ declare const file: (config: Omit<FileFormField, "type">) => FileFormField;
709
606
  * })
710
607
  * ```
711
608
  */
712
- declare const date: (config: Omit<DateFormField, "type">) => DateFormField;
609
+ export declare const date: (config: Omit<DateFormField, "type">) => DateFormField;
713
610
  /**
714
611
  * Creates a time picker field configuration.
715
612
  *
@@ -731,7 +628,7 @@ declare const date: (config: Omit<DateFormField, "type">) => DateFormField;
731
628
  * })
732
629
  * ```
733
630
  */
734
- declare const time: (config: Omit<TimeFormField, "type">) => TimeFormField;
631
+ export declare const time: (config: Omit<TimeFormField, "type">) => TimeFormField;
735
632
  /**
736
633
  * Creates a hidden field configuration.
737
634
  *
@@ -751,37 +648,7 @@ declare const time: (config: Omit<TimeFormField, "type">) => TimeFormField;
751
648
  * hidden({ name: 'campaign', label: 'Campaign', defaultValue: 'summer-sale' })
752
649
  * ```
753
650
  */
754
- declare const hidden: (config: Omit<HiddenFormField, "type">) => HiddenFormField;
755
-
756
- /**
757
- * Conditional Logic Evaluator
758
- *
759
- * Evaluates conditional logic rules to determine field visibility in forms.
760
- * Used by the FormRenderer component to show/hide fields based on user input.
761
- *
762
- * @module utils/evaluate-conditions
763
- * @since 1.0.0
764
- *
765
- * @example
766
- * ```typescript
767
- * import { evaluateConditions } from '@nextly/plugin-form-builder';
768
- *
769
- * const conditionalLogic = {
770
- * enabled: true,
771
- * action: 'show',
772
- * operator: 'AND',
773
- * conditions: [
774
- * { field: 'country', comparison: 'equals', value: 'US' },
775
- * { field: 'age', comparison: 'greaterThan', value: 18 },
776
- * ],
777
- * };
778
- *
779
- * const formData = { country: 'US', age: 25 };
780
- * const isVisible = evaluateConditions(conditionalLogic, formData);
781
- * // isVisible = true (all conditions met, action is 'show')
782
- * ```
783
- */
784
-
651
+ export declare const hidden: (config: Omit<HiddenFormField, "type">) => HiddenFormField;
785
652
  /**
786
653
  * Comparison operators supported by the conditional logic system.
787
654
  */
@@ -847,31 +714,20 @@ type ComparisonOperator = "equals" | "notEquals" | "contains" | "isEmpty" | "isN
847
714
  * evaluateConditions(orLogic, { role: 'viewer' }); // false
848
715
  * ```
849
716
  */
850
- declare function evaluateConditions(logic: ConditionalLogic | undefined, formData: Record<string, unknown>): boolean;
717
+ export declare function evaluateConditions(logic: ConditionalLogic | undefined, formData: Record<string, unknown>): boolean;
851
718
  /**
852
719
  * Checks if a comparison operator is valid.
853
720
  *
854
721
  * @param operator - The operator to check
855
722
  * @returns Whether the operator is valid
856
723
  */
857
- declare function isValidComparisonOperator(operator: string): operator is ComparisonOperator;
724
+ export declare function isValidComparisonOperator(operator: string): operator is ComparisonOperator;
858
725
  /**
859
726
  * Gets the list of supported comparison operators.
860
727
  *
861
728
  * @returns Array of supported operator names
862
729
  */
863
- declare function getSupportedComparisonOperators(): ComparisonOperator[];
864
-
865
- /**
866
- * Dynamic Zod Schema Generator
867
- *
868
- * Converts FormField[] configuration to Zod validation schemas.
869
- * Supports all form field types with proper validation rules.
870
- *
871
- * @module utils/generate-schema
872
- * @since 0.1.0
873
- */
874
-
730
+ export declare function getSupportedComparisonOperators(): ComparisonOperator[];
875
731
  /**
876
732
  * Generate a Zod validation schema from form field configuration.
877
733
  *
@@ -893,7 +749,7 @@ declare function getSupportedComparisonOperators(): ComparisonOperator[];
893
749
  * const result = schema.safeParse({ firstName: 'John', email: 'john@example.com', age: 25 });
894
750
  * ```
895
751
  */
896
- declare function generateZodSchema(fields: FormField[]): z.ZodObject<Record<string, z.ZodTypeAny>>;
752
+ export declare function generateZodSchema(fields: AnyFormField[]): z.ZodObject<Record<string, z.ZodTypeAny>>;
897
753
  /**
898
754
  * Transform form data before validation.
899
755
  *
@@ -907,7 +763,7 @@ declare function generateZodSchema(fields: FormField[]): z.ZodObject<Record<stri
907
763
  * @param fields - Form field configurations
908
764
  * @returns Transformed data ready for validation
909
765
  */
910
- declare function transformFormData(data: Record<string, unknown>, fields: FormField[]): Record<string, unknown>;
766
+ export declare function transformFormData(data: Record<string, unknown>, fields: AnyFormField[]): Record<string, unknown>;
911
767
  /**
912
768
  * Validate form data against a form's field configuration.
913
769
  *
@@ -928,92 +784,94 @@ declare function transformFormData(data: Record<string, unknown>, fields: FormFi
928
784
  * }
929
785
  * ```
930
786
  */
931
- declare function validateFormData(data: Record<string, unknown>, fields: FormField[]): z.SafeParseReturnType<Record<string, unknown>, Record<string, unknown>>;
787
+ export declare function validateFormData(data: Record<string, unknown>, fields: AnyFormField[]): z.ZodSafeParseResult<Record<string, unknown>>;
932
788
  /**
933
789
  * Get validation errors as a flat object.
934
790
  *
935
791
  * @param result - Zod safe parse result
936
792
  * @returns Object mapping field names to error messages
937
793
  */
938
- declare function getValidationErrors(result: z.SafeParseReturnType<unknown, unknown>): Record<string, string>;
939
-
794
+ /** A field that failed, with the machine code a wire error reports. */
795
+ interface ValidationIssue {
796
+ path: string;
797
+ /** `REQUIRED` for an answer that is missing or empty, else `INVALID`. */
798
+ code: "REQUIRED" | "INVALID";
799
+ message: string;
800
+ }
940
801
  /**
941
- * Export Formats Utilities
942
- *
943
- * Pure utility functions for exporting form submissions to CSV and JSON formats.
944
- * These functions generate formatted strings that can be used for file downloads
945
- * or API responses.
802
+ * The same failures as a field-to-message map.
946
803
  *
947
- * @module utils/export-formats
948
- * @since 0.1.0
804
+ * Derived from {@link getValidationIssues} rather than walking the issues a
805
+ * second time, so the two cannot disagree about which message belongs to a
806
+ * field or which failure won when one field had several.
949
807
  */
950
-
808
+ export declare function getValidationErrors(result: z.ZodSafeParseResult<unknown>): Record<string, string>;
951
809
  /**
952
810
  * Options for CSV export.
953
811
  */
954
812
  interface CSVExportOptions {
955
- /**
956
- * Whether to include metadata columns (_id, _status, _submittedAt, etc.).
957
- * @default true
958
- */
959
- includeMetadata?: boolean;
960
- /**
961
- * Delimiter character for CSV.
962
- * @default ","
963
- */
964
- delimiter?: string;
965
- /**
966
- * Whether to include UTF-8 BOM for Excel compatibility.
967
- * @default true
968
- */
969
- includeBOM?: boolean;
970
- /**
971
- * Date format for timestamps.
972
- * @default "iso" (ISO 8601)
973
- */
974
- dateFormat?: "iso" | "locale";
813
+ /**
814
+ * Whether to include metadata columns (_id, _status, _submittedAt, etc.).
815
+ * @default true
816
+ */
817
+ includeMetadata?: boolean;
818
+ /**
819
+ * Delimiter character for CSV.
820
+ * @default ","
821
+ */
822
+ delimiter?: string;
823
+ /**
824
+ * Whether to include UTF-8 BOM for Excel compatibility.
825
+ * @default true
826
+ */
827
+ includeBOM?: boolean;
828
+ /**
829
+ * Date format for timestamps.
830
+ * @default "iso" (ISO 8601)
831
+ */
832
+ dateFormat?: "iso" | "locale";
975
833
  }
976
834
  /**
977
835
  * Options for JSON export.
978
836
  */
979
837
  interface JSONExportOptions {
980
- /**
981
- * Whether to include metadata in each submission.
982
- * @default true
983
- */
984
- includeMetadata?: boolean;
985
- /**
986
- * Whether to include form definition in the export.
987
- * @default true
988
- */
989
- includeFormDefinition?: boolean;
990
- /**
991
- * Number of spaces for indentation (0 for minified).
992
- * @default 2
993
- */
994
- indent?: number;
838
+ /**
839
+ * Whether to include metadata in each submission.
840
+ * @default true
841
+ */
842
+ includeMetadata?: boolean;
843
+ /**
844
+ * Whether to include form definition in the export.
845
+ * @default true
846
+ */
847
+ includeFormDefinition?: boolean;
848
+ /**
849
+ * Number of spaces for indentation (0 for minified).
850
+ * @default 2
851
+ */
852
+ indent?: number;
995
853
  }
996
854
  /**
997
855
  * Exported JSON structure.
998
856
  */
999
857
  interface ExportedJSON {
1000
- /** Export metadata */
1001
- exportedAt: string;
1002
- /** Form information (if includeFormDefinition is true) */
1003
- form?: {
1004
- id: string;
1005
- name: string;
1006
- slug: string;
1007
- fields: Array<{
1008
- name: string;
1009
- label: string;
1010
- type: string;
1011
- }>;
1012
- };
1013
- /** Total number of submissions in export */
1014
- totalSubmissions: number;
1015
- /** Array of submission data */
1016
- submissions: Array<Record<string, unknown>>;
858
+ /** Export metadata */
859
+ exportedAt: string;
860
+ /** Form information (if includeFormDefinition is true) */
861
+ form?: {
862
+ id: string;
863
+ name: string;
864
+ slug: string;
865
+ fields: Array<{
866
+ name: string;
867
+ label: string;
868
+ type: string;
869
+ }>;
870
+ };
871
+ /** Total number of submissions in export */
872
+ totalSubmissions: number;
873
+ /** Array of submission data */
874
+ submissions: Array<Record<string, unknown>>;
1017
875
  }
1018
876
  /**
1019
877
  * Format a field value for export based on field type.
@@ -1029,7 +887,7 @@ interface ExportedJSON {
1029
887
  * formatExportValue(new Date(), { type: 'date' }); // "2024-01-15"
1030
888
  * ```
1031
889
  */
1032
- declare function formatExportValue(value: unknown, field?: FormField): string;
890
+ export declare function formatExportValue(value: unknown, field?: AnyFormField): string;
1033
891
  /**
1034
892
  * Export submissions to CSV format.
1035
893
  *
@@ -1055,7 +913,7 @@ declare function formatExportValue(value: unknown, field?: FormField): string;
1055
913
  * downloadFile(csv, 'submissions.csv', 'text/csv;charset=utf-8');
1056
914
  * ```
1057
915
  */
1058
- declare function exportToCSV(submissions: SubmissionDocument[], form: FormDocument, options?: CSVExportOptions): string;
916
+ export declare function exportToCSV(submissions: SubmissionDocument[], form: FormDocument, options?: CSVExportOptions): string;
1059
917
  /**
1060
918
  * Export submissions to JSON format.
1061
919
  *
@@ -1082,7 +940,7 @@ declare function exportToCSV(submissions: SubmissionDocument[], form: FormDocume
1082
940
  * downloadFile(json, 'submissions.json', 'application/json');
1083
941
  * ```
1084
942
  */
1085
- declare function exportToJSON(submissions: SubmissionDocument[], form: FormDocument, options?: JSONExportOptions): string;
943
+ export declare function exportToJSON(submissions: SubmissionDocument[], form: FormDocument, options?: JSONExportOptions): string;
1086
944
  /**
1087
945
  * Trigger a file download in the browser.
1088
946
  *
@@ -1102,7 +960,7 @@ declare function exportToJSON(submissions: SubmissionDocument[], form: FormDocum
1102
960
  * downloadFile(json, 'submissions.json', 'application/json');
1103
961
  * ```
1104
962
  */
1105
- declare function downloadFile(content: string, filename: string, mimeType: string): void;
963
+ export declare function downloadFile(content: string, filename: string, mimeType: string): void;
1106
964
  /**
1107
965
  * Generate a filename for export.
1108
966
  *
@@ -1118,7 +976,7 @@ declare function downloadFile(content: string, filename: string, mimeType: strin
1118
976
  * // Returns: "contact-form-submissions-2024-01-15.csv"
1119
977
  * ```
1120
978
  */
1121
- declare function generateExportFilename(formSlug: string, format: "csv" | "json"): string;
979
+ export declare function generateExportFilename(formSlug: string, format: "csv" | "json"): string;
1122
980
  /**
1123
981
  * Export submissions and trigger browser download.
1124
982
  *
@@ -1138,57 +996,151 @@ declare function generateExportFilename(formSlug: string, format: "csv" | "json"
1138
996
  * };
1139
997
  * ```
1140
998
  */
1141
- declare function exportAndDownload(submissions: SubmissionDocument[], form: FormDocument, format: "csv" | "json", options?: CSVExportOptions | JSONExportOptions): void;
1142
-
999
+ export declare function exportAndDownload(submissions: SubmissionDocument[], form: FormDocument, format: "csv" | "json", options?: CSVExportOptions | JSONExportOptions): void;
1000
+ /**
1001
+ * Options for submitting a form.
1002
+ */
1003
+ interface SubmitFormOptions {
1004
+ /** Form slug (URL-friendly identifier) */
1005
+ formSlug: string;
1006
+ /** Form submission data */
1007
+ data: Record<string, unknown>;
1008
+ /** Optional metadata about the submission */
1009
+ metadata?: {
1010
+ /** Submitter's IP address */
1011
+ ipAddress?: string;
1012
+ /** Submitter's user agent string */
1013
+ userAgent?: string;
1014
+ };
1015
+ /**
1016
+ * The HTTP request this submission arrived on.
1017
+ *
1018
+ * A route calling this helper is its own route, outside everything Nextly
1019
+ * pins a request around, so nothing else can supply it. Without it the write
1020
+ * reaches the submissions hooks looking like a seed or a job, and every rule
1021
+ * scoped to a visitor stands down: the rate limit above all.
1022
+ *
1023
+ * The request rather than an address, because the core resolves the client
1024
+ * from it under this deployment's proxy-trust settings. `metadata.ipAddress`
1025
+ * is a string the caller chose, which is the right shape for the audit column
1026
+ * it fills and the wrong shape for deciding who to throttle.
1027
+ */
1028
+ request?: Request;
1029
+ /**
1030
+ * Whose permissions the reads and the write are judged against.
1031
+ *
1032
+ * Defaults to `system`, so every existing caller behaves as before.
1033
+ */
1034
+ access?: SubmissionAccess;
1035
+ /**
1036
+ * The language the visitor submitted in.
1037
+ *
1038
+ * Decides which translation a picked redirect page is read in, and so which
1039
+ * URL the visitor is sent to: a page whose slug is `thanks` in English and
1040
+ * `merci` in French answered `/thanks` to everyone, because the target was
1041
+ * read with no locale and the default answered. The built-in route takes it
1042
+ * from `?locale=` on the submit URL, the same way core's own routes take a
1043
+ * locale on the wire; a host route passes whatever it resolved for the page
1044
+ * the form was on.
1045
+ *
1046
+ * A code that is not a configured locale reads as the default rather than
1047
+ * failing the submission, which the collection services decide. Absent means
1048
+ * the default, as it always has. The read wildcards (`all`, `*`) are not a
1049
+ * language a visitor can have submitted in and are treated as absent: a read
1050
+ * in "every language" answers a localized URL field with one value per
1051
+ * language, which no URL pattern can be filled from.
1052
+ */
1053
+ locale?: string;
1054
+ }
1143
1055
  /**
1144
- * Form Submission Handler
1056
+ * How this submission reaches the collections it touches.
1145
1057
  *
1146
- * Processes form submissions including validation, spam detection,
1147
- * storage, and notification triggering.
1058
+ * `system` is the default and is right for host code: the caller already
1059
+ * decided, and there is no visitor whose permissions could be consulted.
1148
1060
  *
1149
- * @module handlers/submit-form
1150
- * @since 0.1.0
1061
+ * `public` is for a route serving an anonymous visitor. It keeps the
1062
+ * collection's configured `access` rules in force, so a host that closed
1063
+ * submissions or restricted reading forms is obeyed rather than bypassed. The
1064
+ * former core endpoint ran this way, and elevating a public route to `system`
1065
+ * silently overrode that configuration.
1151
1066
  */
1152
-
1067
+ type SubmissionAccess = {
1068
+ as: "system";
1069
+ } | {
1070
+ as: "public";
1071
+ };
1153
1072
  /**
1154
- * Options for submitting a form.
1073
+ * Why a submission ended the way it did.
1074
+ *
1075
+ * `success` alone cannot carry this. An HTTP route has to answer 404 for a slug
1076
+ * nobody used, 409 for a form its author closed and 400 for data that did not
1077
+ * validate, and a boolean plus a human sentence cannot tell those apart without
1078
+ * matching on the sentence.
1079
+ *
1080
+ * `accepted` covers every ending a visitor is told succeeded, INCLUDING the two
1081
+ * that are deliberately indistinguishable from success: a submission the
1082
+ * honeypot flagged, and one the rate limiter refused. A caller must not try to
1083
+ * separate them, which is why they do not appear here as their own names.
1155
1084
  */
1156
- interface SubmitFormOptions {
1157
- /** Form slug (URL-friendly identifier) */
1158
- formSlug: string;
1159
- /** Form submission data */
1160
- data: Record<string, unknown>;
1161
- /** Optional metadata about the submission */
1162
- metadata?: {
1163
- /** Submitter's IP address */
1164
- ipAddress?: string;
1165
- /** Submitter's user agent string */
1166
- userAgent?: string;
1167
- };
1168
- }
1085
+ type SubmitFormOutcome = "accepted" | "no-such-form" | "closed" | "invalid" | "duplicate" | "failed";
1169
1086
  /**
1170
1087
  * Result of form submission.
1171
1088
  */
1172
1089
  interface SubmitFormResult {
1173
- /** Whether the submission was successful */
1174
- success: boolean;
1175
- /** The created submission document (on success) */
1176
- submission?: SubmissionDocument;
1177
- /** Error message (on failure) */
1178
- error?: string;
1179
- /** Field-level validation errors */
1180
- validationErrors?: Record<string, string>;
1181
- /** Redirect URL (if form configured for redirect on success) */
1182
- redirect?: string;
1090
+ /** Whether the submission was successful */
1091
+ success: boolean;
1092
+ /**
1093
+ * Which ending this was, for a caller that has to map it to a status code.
1094
+ *
1095
+ * Required rather than optional, so a return path added later cannot omit it
1096
+ * and leave the HTTP route guessing from the message text.
1097
+ */
1098
+ outcome: SubmitFormOutcome;
1099
+ /** The created submission document (on success) */
1100
+ submission?: SubmissionDocument;
1101
+ /** Error message (on failure) */
1102
+ error?: string;
1103
+ /** Field-level validation errors */
1104
+ validationErrors?: Record<string, string>;
1105
+ /**
1106
+ * The same failures with their machine codes, for a caller building an HTTP
1107
+ * error. `validationErrors` above cannot carry one, so a route reading only
1108
+ * that has to invent a code and reports every blank answer as `INVALID`.
1109
+ */
1110
+ validationIssues?: ValidationIssue[];
1111
+ /** Redirect URL (if form configured for redirect on success) */
1112
+ redirect?: string;
1113
+ /**
1114
+ * The error that ended a `failed` submission, kept rather than flattened.
1115
+ *
1116
+ * A collection can refuse a write for reasons its host chose: a
1117
+ * `beforeValidate` hook throwing `NextlyError.validation`, a uniqueness
1118
+ * conflict. Those carry their own status and field detail, and reporting them
1119
+ * all as one internal error tells a visitor the server broke when in fact
1120
+ * their submission was answered deliberately.
1121
+ */
1122
+ cause?: unknown;
1123
+ /**
1124
+ * The toast the form's author wrote for a successful submission.
1125
+ *
1126
+ * Carried on the result rather than read from the form again by whoever
1127
+ * presents it: the HTTP route would otherwise have to fetch the form a second
1128
+ * time purely to learn a string this function already had in hand, and a
1129
+ * second read is a second chance to disagree about which form was submitted.
1130
+ *
1131
+ * Present on every `accepted` ending, including the ones a bot caused, so the
1132
+ * message cannot be used to tell an accepted submission from a flagged one.
1133
+ */
1134
+ successMessage?: string;
1183
1135
  }
1184
1136
  /**
1185
1137
  * Context for the submission handler.
1186
1138
  */
1187
1139
  interface SubmitFormContext {
1188
- /** Plugin context with access to services */
1189
- pluginContext: PluginContext;
1190
- /** Resolved plugin configuration */
1191
- pluginConfig: ResolvedFormBuilderConfig;
1140
+ /** Plugin context with access to services */
1141
+ pluginContext: PluginContext;
1142
+ /** Resolved plugin configuration */
1143
+ pluginConfig: ResolvedFormBuilderConfig;
1192
1144
  }
1193
1145
  /**
1194
1146
  * Process a form submission.
@@ -1231,7 +1183,7 @@ interface SubmitFormContext {
1231
1183
  * }
1232
1184
  * ```
1233
1185
  */
1234
- declare function submitForm(options: SubmitFormOptions, context: SubmitFormContext): Promise<SubmitFormResult>;
1186
+ export declare function submitForm(options: SubmitFormOptions, context: SubmitFormContext): Promise<SubmitFormResult>;
1235
1187
  /**
1236
1188
  * Validate form data without creating a submission.
1237
1189
  *
@@ -1255,9 +1207,9 @@ declare function submitForm(options: SubmitFormOptions, context: SubmitFormConte
1255
1207
  * }
1256
1208
  * ```
1257
1209
  */
1258
- declare function validateSubmission(formSlug: string, data: Record<string, unknown>, context: SubmitFormContext): Promise<{
1259
- valid: boolean;
1260
- errors?: Record<string, string>;
1210
+ export declare function validateSubmission(formSlug: string, data: Record<string, unknown>, context: SubmitFormContext): Promise<{
1211
+ valid: boolean;
1212
+ errors?: Record<string, string>;
1261
1213
  }>;
1262
1214
  /**
1263
1215
  * Check if a form is accepting submissions.
@@ -1266,7 +1218,7 @@ declare function validateSubmission(formSlug: string, data: Record<string, unkno
1266
1218
  * @param context - Handler context
1267
1219
  * @returns Whether the form accepts submissions
1268
1220
  */
1269
- declare function isFormAcceptingSubmissions(formSlug: string, context: SubmitFormContext): Promise<boolean>;
1221
+ export declare function isFormAcceptingSubmissions(formSlug: string, context: SubmitFormContext): Promise<boolean>;
1270
1222
  /**
1271
1223
  * Get submission statistics for a form.
1272
1224
  *
@@ -1278,72 +1230,62 @@ declare function isFormAcceptingSubmissions(formSlug: string, context: SubmitFor
1278
1230
  * @param context - Handler context
1279
1231
  * @returns Submission statistics
1280
1232
  */
1281
- declare function getFormSubmissionStats(formSlug: string, context: SubmitFormContext): Promise<{
1282
- total: number;
1283
- new: number;
1284
- read: number;
1285
- archived: number;
1233
+ export declare function getFormSubmissionStats(formSlug: string, context: SubmitFormContext): Promise<{
1234
+ total: number;
1235
+ new: number;
1236
+ read: number;
1237
+ archived: number;
1286
1238
  } | null>;
1287
-
1288
- /**
1289
- * Spam Detection
1290
- *
1291
- * Implements honeypot and rate limiting spam protection for form submissions.
1292
- * Provides a pluggable approach to spam detection that can be extended.
1293
- *
1294
- * @module handlers/spam-detection
1295
- * @since 0.1.0
1296
- */
1297
1239
  /**
1298
1240
  * Configuration for spam detection.
1299
1241
  */
1300
1242
  interface SpamCheckConfig {
1301
- /**
1302
- * Enable honeypot field detection.
1303
- * When enabled, submissions with filled honeypot fields are marked as spam.
1304
- */
1305
- honeypot?: boolean;
1306
- /**
1307
- * Rate limiting configuration.
1308
- */
1309
- rateLimit?: {
1310
- /** Maximum submissions allowed per window */
1311
- maxSubmissions: number;
1312
- /** Time window in milliseconds */
1313
- windowMs: number;
1314
- };
1315
- /**
1316
- * reCAPTCHA configuration (for future implementation).
1317
- */
1318
- recaptcha?: {
1319
- enabled: boolean;
1320
- secretKey?: string;
1321
- scoreThreshold?: number;
1322
- };
1243
+ /**
1244
+ * Enable honeypot field detection.
1245
+ * When enabled, submissions with filled honeypot fields are marked as spam.
1246
+ */
1247
+ honeypot?: boolean;
1248
+ /**
1249
+ * Rate limiting configuration.
1250
+ */
1251
+ rateLimit?: {
1252
+ /** Maximum submissions allowed per window */
1253
+ maxSubmissions: number;
1254
+ /** Time window in milliseconds */
1255
+ windowMs: number;
1256
+ };
1257
+ /**
1258
+ * reCAPTCHA configuration (for future implementation).
1259
+ */
1260
+ recaptcha?: {
1261
+ enabled: boolean;
1262
+ secretKey?: string;
1263
+ scoreThreshold?: number;
1264
+ };
1323
1265
  }
1324
1266
  /**
1325
1267
  * Options for spam check.
1326
1268
  */
1327
1269
  interface SpamCheckOptions {
1328
- /** Form submission data */
1329
- data: Record<string, unknown>;
1330
- /** Submitter's IP address */
1331
- ipAddress?: string;
1332
- /** Form slug for rate limiting key */
1333
- formSlug: string;
1334
- /** Spam protection configuration */
1335
- config: SpamCheckConfig;
1270
+ /** Form submission data */
1271
+ data: Record<string, unknown>;
1272
+ /** Submitter's IP address */
1273
+ ipAddress?: string;
1274
+ /** Form slug for rate limiting key */
1275
+ formSlug: string;
1276
+ /** Spam protection configuration */
1277
+ config: SpamCheckConfig;
1336
1278
  }
1337
1279
  /**
1338
1280
  * Result of spam check.
1339
1281
  */
1340
1282
  interface SpamCheckResult {
1341
- /** Whether the submission is detected as spam */
1342
- isSpam: boolean;
1343
- /** Reason for spam detection (for logging, not exposed to user) */
1344
- reason?: "honeypot" | "rate_limit" | "recaptcha";
1345
- /** Additional details (for logging) */
1346
- details?: string;
1283
+ /** Whether the submission is detected as spam */
1284
+ isSpam: boolean;
1285
+ /** Reason for spam detection (for logging, not exposed to user) */
1286
+ reason?: "honeypot" | "rate_limit" | "recaptcha";
1287
+ /** Additional details (for logging) */
1288
+ details?: string;
1347
1289
  }
1348
1290
  /**
1349
1291
  * Check a form submission for spam indicators.
@@ -1374,196 +1316,7 @@ interface SpamCheckResult {
1374
1316
  * }
1375
1317
  * ```
1376
1318
  */
1377
- declare function checkSpam(options: SpamCheckOptions): Promise<SpamCheckResult>;
1378
- /**
1379
- * Clean up expired rate limit entries.
1380
- *
1381
- * Call this periodically (e.g., every 5 minutes) to prevent
1382
- * memory leaks from accumulated rate limit entries.
1383
- *
1384
- * @param maxAgeMs - Maximum age of entries to keep (default: 5 minutes)
1385
- * @returns Number of entries removed
1386
- *
1387
- * @example
1388
- * ```typescript
1389
- * // Set up periodic cleanup
1390
- * setInterval(() => {
1391
- * const removed = cleanupRateLimitStore();
1392
- * console.log(`Cleaned up ${removed} expired rate limit entries`);
1393
- * }, 5 * 60 * 1000); // Every 5 minutes
1394
- * ```
1395
- */
1396
- declare function cleanupRateLimitStore(maxAgeMs?: number): number;
1397
- /**
1398
- * Get the current size of the rate limit store.
1399
- *
1400
- * Useful for monitoring and debugging.
1401
- *
1402
- * @returns Number of entries in the store
1403
- */
1404
- declare function getRateLimitStoreSize(): number;
1405
- /**
1406
- * Clear all rate limit entries.
1407
- *
1408
- * Useful for testing or resetting state.
1409
- */
1410
- declare function clearRateLimitStore(): void;
1411
- /**
1412
- * Check if a specific IP/form is currently rate limited.
1413
- *
1414
- * @param ipAddress - IP address to check
1415
- * @param formSlug - Form slug
1416
- * @param config - Rate limit configuration
1417
- * @returns Whether the IP is currently rate limited
1418
- */
1419
- declare function isRateLimited(ipAddress: string, formSlug: string, config: {
1420
- maxSubmissions: number;
1421
- windowMs: number;
1422
- }): boolean;
1423
-
1424
- /**
1425
- * Webhook Handler
1426
- *
1427
- * Triggers webhook notifications for form events.
1428
- * Webhooks are fired asynchronously and do not block form submission.
1429
- *
1430
- * @module handlers/webhooks
1431
- * @since 0.1.0
1432
- */
1433
-
1434
- /**
1435
- * Webhook payload sent to configured endpoints.
1436
- */
1437
- interface WebhookPayload {
1438
- /** Event type that triggered the webhook */
1439
- event: WebhookEvent;
1440
- /** ISO 8601 timestamp when the event occurred */
1441
- timestamp: string;
1442
- /** Form information */
1443
- form: {
1444
- id: string;
1445
- slug: string;
1446
- name: string;
1447
- };
1448
- /** Submission information (full data or minimal based on config) */
1449
- submission: SubmissionDocument | {
1450
- id: string;
1451
- submittedAt: Date;
1452
- };
1453
- }
1454
- /**
1455
- * Options for triggering webhooks.
1456
- */
1457
- interface TriggerWebhooksOptions {
1458
- /** Event type */
1459
- event: WebhookEvent;
1460
- /** Form document */
1461
- form: FormDocument;
1462
- /** Submission document */
1463
- submission: SubmissionDocument;
1464
- }
1465
- /**
1466
- * Result of a single webhook delivery attempt.
1467
- */
1468
- interface WebhookDeliveryResult {
1469
- /** Webhook URL */
1470
- url: string;
1471
- /** Whether the delivery was successful */
1472
- success: boolean;
1473
- /** HTTP status code (if request completed) */
1474
- statusCode?: number;
1475
- /** Error message (if delivery failed) */
1476
- error?: string;
1477
- /** Time taken in milliseconds */
1478
- durationMs: number;
1479
- }
1480
- /**
1481
- * Result of triggering webhooks for an event.
1482
- */
1483
- interface TriggerWebhooksResult {
1484
- /** Number of webhooks triggered */
1485
- triggered: number;
1486
- /** Number of successful deliveries */
1487
- successful: number;
1488
- /** Number of failed deliveries */
1489
- failed: number;
1490
- /** Individual delivery results */
1491
- results: WebhookDeliveryResult[];
1492
- }
1493
- /**
1494
- * Trigger webhooks for a form event.
1495
- *
1496
- * This function fires all matching webhooks asynchronously and does not
1497
- * block form submission. Failed webhooks are logged but do not cause
1498
- * submission failures.
1499
- *
1500
- * @param options - Trigger options
1501
- * @returns Result of webhook triggering
1502
- *
1503
- * @example
1504
- * ```typescript
1505
- * // After creating a submission
1506
- * const result = await triggerWebhooks({
1507
- * event: 'submission.created',
1508
- * form,
1509
- * submission,
1510
- * });
1511
- *
1512
- * console.log(`Triggered ${result.triggered} webhooks`);
1513
- * console.log(`Successful: ${result.successful}, Failed: ${result.failed}`);
1514
- * ```
1515
- */
1516
- declare function triggerWebhooks(options: TriggerWebhooksOptions): Promise<TriggerWebhooksResult>;
1517
- /**
1518
- * Trigger webhooks without waiting for completion.
1519
- *
1520
- * This is the recommended way to call webhooks from submission handlers
1521
- * as it doesn't block the response. Errors are logged but not thrown.
1522
- *
1523
- * @param options - Trigger options
1524
- * @param logger - Optional logger for error reporting
1525
- *
1526
- * @example
1527
- * ```typescript
1528
- * // In submission handler - fire and forget
1529
- * fireWebhooks(
1530
- * { event: 'submission.created', form, submission },
1531
- * pluginContext.infra.logger
1532
- * );
1533
- *
1534
- * // Continue with response immediately
1535
- * return { success: true, submission };
1536
- * ```
1537
- */
1538
- declare function fireWebhooks(options: TriggerWebhooksOptions, logger?: {
1539
- info?: (message: string, data?: Record<string, unknown>) => void;
1540
- warn?: (message: string, data?: Record<string, unknown>) => void;
1541
- error?: (message: string, data?: Record<string, unknown>) => void;
1542
- }): void;
1543
- /**
1544
- * Validate a webhook URL.
1545
- *
1546
- * @param url - URL to validate
1547
- * @returns Whether the URL is valid for webhooks
1548
- */
1549
- declare function isValidWebhookUrl(url: string): boolean;
1550
- /**
1551
- * Get the list of supported webhook events.
1552
- *
1553
- * @returns Array of supported event types
1554
- */
1555
- declare function getSupportedWebhookEvents(): WebhookEvent[];
1556
-
1557
- /**
1558
- * Forms Collection
1559
- *
1560
- * Stores form definitions created via Code-First or Schema Builder.
1561
- * Each form contains field definitions, settings, notifications, and access control.
1562
- *
1563
- * @module collections/forms
1564
- * @since 0.1.0
1565
- */
1566
-
1319
+ export declare function checkSpam(options: SpamCheckOptions): Promise<SpamCheckResult>;
1567
1320
  /**
1568
1321
  * Component path string format.
1569
1322
  * Format: `"package-name/path#ExportName"`
@@ -1573,69 +1326,43 @@ type ComponentPath = string;
1573
1326
  * Custom view configuration for replacing default admin views.
1574
1327
  */
1575
1328
  interface CollectionAdminViewConfig {
1576
- /** Component path to the custom view component */
1577
- Component: ComponentPath;
1329
+ /** Component path to the custom view component */
1330
+ Component: ComponentPath;
1578
1331
  }
1579
1332
  /**
1580
1333
  * Custom components configuration for collection admin UI.
1581
1334
  */
1582
1335
  interface CollectionAdminComponents {
1583
- views?: {
1584
- Edit?: CollectionAdminViewConfig;
1585
- List?: CollectionAdminViewConfig;
1586
- };
1587
- BeforeListTable?: ComponentPath;
1588
- AfterListTable?: ComponentPath;
1589
- BeforeEdit?: ComponentPath;
1590
- AfterEdit?: ComponentPath;
1336
+ views?: {
1337
+ Edit?: CollectionAdminViewConfig;
1338
+ List?: CollectionAdminViewConfig;
1339
+ };
1340
+ BeforeListTable?: ComponentPath;
1341
+ AfterListTable?: ComponentPath;
1342
+ BeforeEdit?: ComponentPath;
1343
+ AfterEdit?: ComponentPath;
1591
1344
  }
1592
1345
  /**
1593
1346
  * Extended CollectionConfig with custom admin components support.
1594
1347
  * This extends the base CollectionConfig to include the components property.
1595
1348
  */
1596
1349
  interface ExtendedCollectionConfig$1 extends Omit<CollectionConfig, "admin"> {
1597
- admin?: CollectionConfig["admin"] & {
1598
- /** Whether this collection is provided by a plugin */
1599
- isPlugin?: boolean;
1600
- components?: CollectionAdminComponents;
1601
- };
1350
+ admin?: CollectionConfig["admin"] & {
1351
+ /** Whether this collection is provided by a plugin */
1352
+ isPlugin?: boolean;
1353
+ components?: CollectionAdminComponents;
1354
+ };
1602
1355
  }
1603
- /**
1604
- * Generate the Forms collection configuration.
1605
- *
1606
- * Creates a collection for storing form definitions with fields,
1607
- * settings, notifications, and access control.
1608
- *
1609
- * @param pluginConfig - Resolved plugin configuration
1610
- * @returns ExtendedCollectionConfig for the Forms collection (with custom admin components)
1611
- *
1612
- * @example
1613
- * ```typescript
1614
- * const formsCol = formsCollection(resolvedConfig);
1615
- * // Returns a collection with slug "forms" (or custom slug from config)
1616
- * ```
1617
- */
1618
- declare function formsCollection(pluginConfig: ResolvedFormBuilderConfig): ExtendedCollectionConfig$1;
1619
-
1620
- /**
1621
- * Form Submissions Collection
1622
- *
1623
- * Stores form submission data from user-submitted forms.
1624
- * Each submission contains the submitted data, metadata, and status.
1625
- *
1626
- * @module collections/submissions
1627
- * @since 0.1.0
1628
- */
1629
-
1356
+ export declare function formsCollection(pluginConfig: ResolvedFormBuilderConfig): ExtendedCollectionConfig$1;
1630
1357
  /**
1631
1358
  * Extended CollectionConfig with isPlugin support.
1632
1359
  * This extends the base CollectionConfig to include the isPlugin property.
1633
1360
  */
1634
1361
  interface ExtendedCollectionConfig extends Omit<CollectionConfig, "admin"> {
1635
- admin?: CollectionConfig["admin"] & {
1636
- /** Whether this collection is provided by a plugin */
1637
- isPlugin?: boolean;
1638
- };
1362
+ admin?: CollectionConfig["admin"] & {
1363
+ /** Whether this collection is provided by a plugin */
1364
+ isPlugin?: boolean;
1365
+ };
1639
1366
  }
1640
1367
  /**
1641
1368
  * Generate the Form Submissions collection configuration.
@@ -1656,8 +1383,7 @@ interface ExtendedCollectionConfig extends Omit<CollectionConfig, "admin"> {
1656
1383
  * // Returns a collection with slug "form-submissions" (or custom slug from config)
1657
1384
  * ```
1658
1385
  */
1659
- declare function submissionsCollection(pluginConfig: ResolvedFormBuilderConfig): ExtendedCollectionConfig;
1660
-
1661
- declare const formBuilderPlugin: nextly.PluginDefinition;
1662
-
1663
- export { type CSVExportOptions, CheckboxFormField, type ComparisonOperator, ConditionalLogic, DEFAULT_FORM_SETTINGS, DEFAULT_NOTIFICATION_SETTINGS, DateFormField, EmailFormField, type ExportedJSON, FileFormField, FormBuilderPluginOptions, type FormBuilderPluginResult, FormConfig, FormDocument, FormField, type FormFieldOption, FormNotifications, FormSettings, type FormValidationError, type FormValidationErrorCode, type FormValidationResult, HiddenFormField, type JSONExportOptions, type NextlyPlugin, NumberFormField, PhoneFormField, RESERVED_FORM_SLUGS, RadioFormField, ResolvedFormBuilderConfig, SelectFormField, type SpamCheckConfig, type SpamCheckOptions, type SpamCheckResult, SubmissionDocument, type SubmitFormContext, type SubmitFormOptions, type SubmitFormResult, TextFormField, TextareaFormField, TimeFormField, type TriggerWebhooksOptions, type TriggerWebhooksResult, UrlFormField, type WebhookDeliveryResult, WebhookEvent, type WebhookPayload, applyFieldDefaults, applyFormDefaults, assertValidFormConfig, checkSpam, checkbox, cleanupRateLimitStore, clearRateLimitStore, createFormConfig, date, downloadFile, email, evaluateConditions, exportAndDownload, exportToCSV, exportToJSON, file, fireWebhooks, formBuilder, formBuilderPlugin, formatExportValue, formsCollection, generateExportFilename, generateZodSchema, getFormBuilderConfig, getFormSubmissionStats, getRateLimitStoreSize, getSupportedComparisonOperators, getSupportedWebhookEvents, getValidationErrors, hidden, isFormAcceptingSubmissions, isRateLimited, isValidComparisonOperator, isValidWebhookUrl, number, option, phone, pluralize, radio, select, submissionsCollection, submitForm, text, textarea, time, toTitleCase, transformFormData, triggerWebhooks, url, validateFormConfig, validateFormData, validateSubmission };
1386
+ export declare function submissionsCollection(pluginConfig: ResolvedFormBuilderConfig): ExtendedCollectionConfig;
1387
+ export declare const formBuilderPlugin: ReturnType<typeof formBuilder>["plugin"];
1388
+ export { type AnyFormField, BUILT_IN_FORM_FIELD_TYPES, type BaseFormField, type CSVExportOptions, type CheckboxFormField, type ComparisonOperator, type ConditionalLogic, type ConditionalLogicCondition, type CustomFormField, type DateFormField, type EmailConfig, type EmailFormField, type ExportedJSON, type FieldBlockConfig, type FileFormField, type FormAccess, type FormBuilderPluginOptions, type FormBuilderPluginResult, type FormConfig, type FormDocument, type FormField, type FormFieldOption, type FormFieldType, type FormFieldTypeId, type FormHookContext, type FormHooks, type FormNotification, type FormNotificationItem, type FormNotifications, type FormSettings, type FormSubmission, type FormValidationError, type FormValidationErrorCode, type FormValidationResult, type HiddenFormField, type JSONExportOptions, type NextlyPlugin, type NumberFormField, type PhoneFormField, type RadioFormField, type ResolvedFormBuilderConfig, type SelectFormField, type SpamCheckConfig, type SpamCheckOptions, type SpamCheckResult, type SubmissionDocument, type SubmitFormContext, type SubmitFormOptions, type SubmitFormResult, type TextFormField, type TextareaFormField, type TimeFormField, type UrlFormField, type ValidationRules, isCheckboxFormField, isEmailFormField, isFileFormField, isFormField, isFormFieldType, isKnownFormField, isSelectFormField, isTextFormField };
1389
+ //# sourceMappingURL=index.d.ts.map