lynkow 1.32.0 → 1.32.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -290,24 +290,33 @@ declare class CategoriesService extends BaseService {
290
290
  * @example
291
291
  * ```typescript
292
292
  * const lynkow = createClient({ siteId: '...' })
293
- * const { data } = await lynkow.tags.list()
293
+ * const { data, meta } = await lynkow.tags.list({ limit: 50 })
294
294
  * ```
295
295
  */
296
296
  declare class TagsService extends BaseService {
297
297
  /**
298
- * Retrieves the complete list of tags available on the site.
299
- * Returns all tags (no pagination). Cached for 5 minutes per locale.
298
+ * Retrieves a paginated list of tags available on the site.
300
299
  *
300
+ * Cached for 5 minutes per (locale + pagination) combination. The cache
301
+ * key splits on `page` and `limit` so adjacent pages do not collide.
302
+ *
303
+ * @param filters - Pagination filters: `page` (1-based), `limit` (1-100), `perPage` (deprecated alias)
301
304
  * @param options - Request options; use `locale` to fetch localized tag names
302
- * @returns An object containing `data` (array of `Tag` with id, name, slug, and locale)
305
+ * @returns `{ data: Tag[], meta: PaginationMeta }`. Server defaults to 20 items per page (ADR-0022 D3); pass `{ limit: 100 }` to recover pre-1.32.2 behavior.
303
306
  *
304
307
  * @example
305
308
  * ```typescript
306
- * const { data } = await lynkow.tags.list()
307
- * data.forEach(tag => console.log(tag.name)) // "Featured", "Tutorial", etc.
309
+ * // Default: first 20 tags.
310
+ * const { data, meta } = await lynkow.tags.list()
311
+ *
312
+ * // Page through everything.
313
+ * for (let page = 1; page <= meta.lastPage; page++) {
314
+ * const { data } = await lynkow.tags.list({ page, limit: 50 })
315
+ * data.forEach(t => console.log(t.name))
316
+ * }
308
317
  * ```
309
318
  */
310
- list(options?: BaseRequestOptions): Promise<TagsListResponse>;
319
+ list(filters?: TagsListFilters, options?: BaseRequestOptions): Promise<TagsListResponse>;
311
320
  /**
312
321
  * Invalidate every cached tag response (lists, tag-filtered contents).
313
322
  * Call after an admin mutation or on receipt of a `tag.*` webhook so
@@ -566,15 +575,15 @@ declare class BlocksService extends BaseService {
566
575
  * ```typescript
567
576
  * const lynkow = createClient({ siteId: '...' })
568
577
  *
569
- * // Fetch form schema to render the form
578
+ * // Fetch the form schema to render the form
570
579
  * const form = await lynkow.forms.getBySlug('contact')
571
580
  *
572
- * // Submit form data
573
- * await lynkow.forms.submit('contact', {
574
- * name: 'Jane',
575
- * email: 'jane@example.com',
576
- * message: 'Hello!'
577
- * })
581
+ * // Build the submission payload using each field's auto-generated id
582
+ * const data = Object.fromEntries(
583
+ * form.schema.fields.map(field => [field.id, readUserValue(field)])
584
+ * )
585
+ *
586
+ * await lynkow.forms.submit('contact', data)
578
587
  * ```
579
588
  */
580
589
  declare class FormsService extends BaseService {
@@ -586,22 +595,31 @@ declare class FormsService extends BaseService {
586
595
  constructor(config: InternalConfig);
587
596
  /**
588
597
  * Retrieves a form definition by its slug, including the field schema,
589
- * validation rules, settings (submit label, success message), and spam
590
- * protection configuration (honeypot/reCAPTCHA). Cached for 10 minutes.
598
+ * behavior settings (submit label, success message), and spam protection
599
+ * configuration (honeypot/reCAPTCHA). Cached for 10 minutes.
591
600
  *
592
601
  * @param slug - The unique slug of the form (e.g. `'contact'`, `'newsletter'`, `'feedback'`)
593
- * @returns The `Form` object with `schema` (array of `FormField` with type, label,
594
- * required, validation, options), `settings` (submitLabel, successMessage, redirectUrl),
595
- * and spam protection flags (honeypotEnabled, recaptchaEnabled, recaptchaSiteKey)
602
+ * @returns The `Form` object. The `schema` property is a `FormSchema`
603
+ * object with `fields` (the ordered list of `FormField`), `settings`
604
+ * (submitLabel, successMessage, redirectUrl, etc.), `conditions`
605
+ * (cross-field rules), and an optional `pages` array for multi-page forms.
606
+ * Spam protection flags live at the top level (`honeypotEnabled`,
607
+ * `recaptchaEnabled`, `recaptchaSiteKey`).
596
608
  * @throws {LynkowError} With code `'NOT_FOUND'` if no active form matches the slug
597
609
  *
598
610
  * @example
599
611
  * ```typescript
600
612
  * const form = await lynkow.forms.getBySlug('contact')
601
- * // Iterate fields to render the form dynamically
602
- * form.schema.forEach(field => {
603
- * console.log(field.name, field.type, field.required)
613
+ *
614
+ * // Render fields in order. Each field's `id` is the key you use later
615
+ * // when submitting, not its label or any semantic name.
616
+ * form.schema.fields.forEach(field => {
617
+ * console.log(field.id, field.type, field.label, field.required)
604
618
  * })
619
+ *
620
+ * // Use schema.settings to wire the submit button and success message
621
+ * console.log(form.schema.settings.submitLabel)
622
+ *
605
623
  * // Check spam protection config
606
624
  * if (form.recaptchaEnabled) {
607
625
  * // Render reCAPTCHA widget using form.recaptchaSiteKey
@@ -611,15 +629,18 @@ declare class FormsService extends BaseService {
611
629
  getBySlug(slug: string): Promise<Form>;
612
630
  /**
613
631
  * Submits form data to the API. Anti-spam honeypot fields (`_hp`, `_ts`) are
614
- * injected automatically by the SDK -- you do not need to add them yourself.
632
+ * injected automatically by the SDK; you do not need to add them yourself.
615
633
  * If the form has reCAPTCHA enabled, pass the token via `options.recaptchaToken`.
616
634
  *
617
635
  * @param slug - The slug of the form to submit to (e.g. `'contact'`)
618
- * @param data - Key-value pairs matching the form's field names.
619
- * Values can be `string`, `number`, `boolean`, or `File`.
636
+ * @param data - Key-value pairs keyed by `FormField.id` (auto-generated by
637
+ * the admin, e.g. `'field_1764776796820'`) from the schema returned by
638
+ * `getBySlug()`. Do not use semantic names like `'name'` or `'email'`
639
+ * unless those happen to be the actual field ids; field ids are not
640
+ * human-readable. Values can be `string`, `number`, `boolean`, or `File`.
620
641
  * @param options - Optional submission options:
621
- * - `recaptchaToken` the reCAPTCHA v3 token (required if reCAPTCHA is enabled on the form)
622
- * - `fetchOptions` custom fetch options (e.g. AbortSignal)
642
+ * - `recaptchaToken`: the reCAPTCHA v3 token (required if reCAPTCHA is enabled on the form)
643
+ * - `fetchOptions`: custom fetch options (e.g. AbortSignal)
623
644
  * @returns A `FormSubmitResponse` with `message` (confirmation text), `status`
624
645
  * (`'success'` for immediate acceptance, `'pending'` if double opt-in is enabled),
625
646
  * and optionally `submissionId`
@@ -629,11 +650,16 @@ declare class FormsService extends BaseService {
629
650
  *
630
651
  * @example
631
652
  * ```typescript
632
- * const result = await lynkow.forms.submit('contact', {
633
- * name: 'John Doe',
634
- * email: 'john@example.com',
635
- * message: 'Hello!'
636
- * })
653
+ * const form = await lynkow.forms.getBySlug('contact')
654
+ *
655
+ * // Build the payload with field.id as key. The SDK does not transform
656
+ * // semantic names into ids; you must do that yourself based on the schema.
657
+ * const data: Record<string, string> = {}
658
+ * for (const field of form.schema.fields) {
659
+ * data[field.id] = readValueForField(field) // your UI binding
660
+ * }
661
+ *
662
+ * const result = await lynkow.forms.submit('contact', data)
637
663
  *
638
664
  * if (result.status === 'pending') {
639
665
  * // Show "check your email" confirmation
@@ -3324,13 +3350,14 @@ interface GlobalBlock {
3324
3350
  *
3325
3351
  * Maps to standard HTML input types, with a few additions:
3326
3352
  * - `'textarea'`: multi-line text input (`<textarea>`)
3327
- * - `'select'`: dropdown menu (`<select>`) requires `options`
3328
- * - `'radio'`: radio button group requires `options`
3329
- * - `'checkbox'`: checkbox or checkbox group uses `options` if present, otherwise single boolean
3330
- * - `'file'`: file upload input accepts files via multipart form submission
3331
- * - `'hidden'`: hidden input — not displayed to users, useful for tracking parameters
3353
+ * - `'select'`: dropdown menu (`<select>`); requires `options`
3354
+ * - `'radio'`: radio button group; requires `options`
3355
+ * - `'checkbox'`: checkbox or checkbox group; uses `options` if present, otherwise single boolean
3356
+ * - `'file'`: file upload input; accepts files via multipart form submission
3357
+ * - `'rating'`: star/score rating input
3358
+ * - `'hidden'`: hidden input; not displayed to users, useful for tracking parameters
3332
3359
  */
3333
- type FormFieldType = 'text' | 'email' | 'tel' | 'url' | 'textarea' | 'number' | 'date' | 'datetime' | 'time' | 'select' | 'radio' | 'checkbox' | 'file' | 'hidden';
3360
+ type FormFieldType = 'text' | 'email' | 'tel' | 'url' | 'textarea' | 'number' | 'date' | 'datetime' | 'time' | 'select' | 'radio' | 'checkbox' | 'file' | 'rating' | 'hidden';
3334
3361
  /**
3335
3362
  * A selectable option for `select`, `radio`, and `checkbox` field types.
3336
3363
  */
@@ -3354,7 +3381,8 @@ interface FormFieldOption {
3354
3381
  * Which rules are relevant depends on the field type:
3355
3382
  * - `minLength`/`maxLength`: text-based fields (`text`, `email`, `textarea`, `url`, `tel`)
3356
3383
  * - `min`/`max`: `number` fields only
3357
- * - `pattern`: any text-based field validated as a JavaScript RegExp
3384
+ * - `pattern`: any text-based field; validated as a JavaScript RegExp
3385
+ * - `accept`/`maxSize`: `file` field only
3358
3386
  */
3359
3387
  interface FormFieldValidation {
3360
3388
  /**
@@ -3372,13 +3400,13 @@ interface FormFieldValidation {
3372
3400
  /**
3373
3401
  * Minimum numeric value (inclusive).
3374
3402
  * Only applicable to `number` field type.
3375
- * Ignored for text fields use `minLength` instead.
3403
+ * Ignored for text fields. Use `minLength` instead.
3376
3404
  */
3377
3405
  min?: number;
3378
3406
  /**
3379
3407
  * Maximum numeric value (inclusive).
3380
3408
  * Only applicable to `number` field type.
3381
- * Ignored for text fields use `maxLength` instead.
3409
+ * Ignored for text fields. Use `maxLength` instead.
3382
3410
  */
3383
3411
  max?: number;
3384
3412
  /**
@@ -3387,6 +3415,16 @@ interface FormFieldValidation {
3387
3415
  * Applicable to any text-based field type.
3388
3416
  */
3389
3417
  pattern?: string;
3418
+ /**
3419
+ * Accepted MIME types or extensions for `file` fields (e.g. `'image/*,.pdf'`).
3420
+ * Mirrors the HTML `accept` attribute. Ignored for non-`file` fields.
3421
+ */
3422
+ accept?: string;
3423
+ /**
3424
+ * Maximum file size in bytes for `file` fields.
3425
+ * Ignored for non-`file` fields.
3426
+ */
3427
+ maxSize?: number;
3390
3428
  /**
3391
3429
  * Custom error message displayed when validation fails.
3392
3430
  * `undefined` means the browser/framework default message is used.
@@ -3394,6 +3432,56 @@ interface FormFieldValidation {
3394
3432
  */
3395
3433
  message?: string;
3396
3434
  }
3435
+ /**
3436
+ * Conditional logic rule applied to a form field.
3437
+ *
3438
+ * When the referenced `field` matches the operator/value combination, the
3439
+ * `action` is applied (show, hide, require, or skip to a target page).
3440
+ * Used for dynamic forms where some fields appear conditionally based on
3441
+ * earlier answers.
3442
+ */
3443
+ interface FormCondition {
3444
+ /**
3445
+ * The `FormField.id` of the field whose value triggers this condition.
3446
+ */
3447
+ field: string;
3448
+ /**
3449
+ * Comparison operator applied to the referenced field's current value.
3450
+ */
3451
+ operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'greater_than' | 'less_than' | 'is_empty' | 'is_not_empty';
3452
+ /**
3453
+ * Value compared against the referenced field. Type depends on the field
3454
+ * type: string for text fields, number for number fields, boolean for
3455
+ * checkboxes. `undefined` for `is_empty` / `is_not_empty`.
3456
+ */
3457
+ value?: unknown;
3458
+ /**
3459
+ * Effect applied when the condition matches:
3460
+ * - `'show'` / `'hide'`: toggle visibility of the target field
3461
+ * - `'require'`: mark the target field required
3462
+ * - `'skip_to_page'`: jump to the page identified by `targetPage`
3463
+ */
3464
+ action: 'show' | 'hide' | 'require' | 'skip_to_page';
3465
+ /**
3466
+ * Target page index for `skip_to_page` actions.
3467
+ * Ignored for other actions.
3468
+ */
3469
+ targetPage?: number;
3470
+ }
3471
+ /**
3472
+ * Phone field configuration.
3473
+ * Only relevant for fields of type `'tel'`.
3474
+ */
3475
+ interface FormFieldPhoneOptions {
3476
+ /**
3477
+ * Whether the country-code selector is rendered next to the phone input.
3478
+ */
3479
+ showCountryCode: boolean;
3480
+ /**
3481
+ * Default country code (e.g. `'+33'`, `'+1'`).
3482
+ */
3483
+ defaultCountryCode: string;
3484
+ }
3397
3485
  /**
3398
3486
  * A single field definition in a form schema.
3399
3487
  * Describes the input type, label, validation, and layout for one form field.
@@ -3403,11 +3491,11 @@ interface FormFieldValidation {
3403
3491
  interface FormField {
3404
3492
  /**
3405
3493
  * Field identifier, used as the key in submission data.
3406
- * Unique within the form. Lowercase, alphanumeric with underscores or hyphens
3407
- * (e.g. `'first_name'`, `'email'`). Max 100 characters.
3408
- * This is the key you use in `FormSubmitData` when submitting.
3494
+ * Auto-generated by the admin (e.g. `'field_1764776796820'`), unique within
3495
+ * the form. This is the key you must use in `FormSubmitData` when calling
3496
+ * `forms.submit()`.
3409
3497
  */
3410
- name: string;
3498
+ id: string;
3411
3499
  /**
3412
3500
  * HTML input type for this field.
3413
3501
  * Determines the rendered input element and applicable validation rules.
@@ -3417,7 +3505,7 @@ interface FormField {
3417
3505
  type: FormFieldType;
3418
3506
  /**
3419
3507
  * Human-readable label displayed above or beside the input.
3420
- * Max 255 characters. Always present use this as the `<label>` text.
3508
+ * Max 255 characters. Always present. Use this as the `<label>` text.
3421
3509
  */
3422
3510
  label: string;
3423
3511
  /**
@@ -3426,12 +3514,19 @@ interface FormField {
3426
3514
  * Use as the HTML `placeholder` attribute.
3427
3515
  */
3428
3516
  placeholder?: string;
3517
+ /**
3518
+ * Help text displayed below the input to guide the user.
3519
+ * Max 500 characters. `undefined` if not configured.
3520
+ * Render as a small description below the field (e.g. `<small>` or `aria-describedby`).
3521
+ */
3522
+ description?: string;
3429
3523
  /**
3430
3524
  * Whether this field must be filled before submission.
3431
3525
  * When `true`, the server will reject submissions with this field empty.
3432
3526
  * Render a required indicator (e.g. `*`) and set the HTML `required` attribute.
3527
+ * `undefined` is treated as `false`.
3433
3528
  */
3434
- required: boolean;
3529
+ required?: boolean;
3435
3530
  /**
3436
3531
  * Selectable options for `select`, `radio`, and `checkbox` field types.
3437
3532
  * `undefined` for field types that don't use options (text, email, number, etc.).
@@ -3444,7 +3539,7 @@ interface FormField {
3444
3539
  /**
3445
3540
  * Validation rules applied to this field's value.
3446
3541
  * `undefined` if no extra validation beyond `required` is configured.
3447
- * Rules are enforced server-side client-side validation is optional but recommended for UX.
3542
+ * Rules are enforced server-side; client-side validation is optional but recommended for UX.
3448
3543
  *
3449
3544
  * @see {@link FormFieldValidation}
3450
3545
  */
@@ -3453,72 +3548,157 @@ interface FormField {
3453
3548
  * Pre-filled default value for the field.
3454
3549
  * Type depends on the field type: `string` for text fields, `number` for number fields,
3455
3550
  * `boolean` for checkbox (single toggle mode).
3456
- * `undefined` if no default is set the field starts empty.
3551
+ * `undefined` if no default is set. The field starts empty.
3457
3552
  */
3458
3553
  defaultValue?: string | number | boolean;
3459
- /**
3460
- * Help text displayed below the input to guide the user.
3461
- * Max 500 characters. `undefined` if not configured.
3462
- * Render as a small description below the field (e.g. `<small>` or `aria-describedby`).
3463
- */
3464
- helpText?: string;
3465
3554
  /**
3466
3555
  * Layout width hint for responsive form layouts:
3467
3556
  * - `'full'`: spans the entire form width (100%)
3468
- * - `'half'`: spans half the form width (50%) place two `half` fields side by side
3469
- * - `'third'`: spans one third of the form width (33%) place three `third` fields in a row
3557
+ * - `'half'`: spans half the form width (50%); place two `half` fields side by side
3558
+ * - `'third'`: spans one third of the form width (33%); place three `third` fields in a row
3470
3559
  *
3471
3560
  * `undefined` defaults to `'full'`.
3472
3561
  */
3473
3562
  width?: 'full' | 'half' | 'third';
3563
+ /**
3564
+ * Per-field conditional logic. When present, the field is only rendered or
3565
+ * required based on the values of earlier fields. Conditions defined here
3566
+ * are scoped to this field; cross-field rules live in `FormSchema.conditions`.
3567
+ *
3568
+ * @see {@link FormCondition}
3569
+ */
3570
+ conditions?: FormCondition[];
3571
+ /**
3572
+ * Configuration for `tel` (phone) fields.
3573
+ * `undefined` for non-phone field types.
3574
+ */
3575
+ phoneOptions?: FormFieldPhoneOptions;
3474
3576
  }
3475
3577
  /**
3476
- * Form behavior settings controlling what happens after submission.
3578
+ * Form behavior settings nested under `FormSchema.settings`.
3579
+ * Controls submit button text, success message, redirect, and progress UI.
3477
3580
  */
3478
- interface FormSettings {
3581
+ interface FormSchemaSettings {
3479
3582
  /**
3480
- * Text displayed on the submit button (e.g. `'Send'`, `'Subscribe'`, `'Submit'`).
3481
- * Max 100 characters. Always present.
3583
+ * Text displayed on the submit button (e.g. `'Send'`, `'Subscribe'`).
3584
+ * `undefined` falls back to a default label rendered by the host application.
3482
3585
  */
3483
- submitLabel: string;
3586
+ submitLabel?: string;
3484
3587
  /**
3485
3588
  * Success message displayed after a successful submission.
3486
- * Max 1000 characters. Shown inline on the page.
3487
- *
3488
- * Ignored if `redirectUrl` is set — the user is redirected instead of seeing this message.
3589
+ * Shown inline on the page. Ignored if `redirectUrl` is set.
3590
+ * `undefined` falls back to a default message.
3489
3591
  */
3490
- successMessage: string;
3592
+ successMessage?: string;
3491
3593
  /**
3492
3594
  * URL to redirect the user to after successful submission.
3493
- * Max 500 characters. Must be a valid URL (e.g. `'https://example.com/thank-you'`).
3494
- * When set, takes precedence over `successMessage` — the user is navigated away immediately.
3595
+ * Must be a valid URL. When set, takes precedence over `successMessage`.
3495
3596
  * `undefined` means show `successMessage` inline instead.
3496
3597
  */
3497
3598
  redirectUrl?: string;
3498
3599
  /**
3499
- * Whether double opt-in email confirmation is enabled.
3500
- * When `true`, the form sends a confirmation email to the user before
3501
- * recording the submission as confirmed. Useful for newsletter signups.
3502
- * `undefined` or `false` means submissions are recorded immediately.
3600
+ * Whether the form requires the visitor to be authenticated.
3601
+ * Enforced server-side. `undefined` is treated as `false`.
3503
3602
  */
3504
- doubleOptIn?: boolean;
3603
+ requireAuth?: boolean;
3604
+ /**
3605
+ * Message displayed when the form is closed (no longer accepting submissions).
3606
+ * `undefined` falls back to a default message.
3607
+ */
3608
+ closedMessage?: string;
3609
+ /**
3610
+ * Whether to render a progress bar for multi-page forms.
3611
+ * `undefined` is treated as `false`.
3612
+ */
3613
+ showProgressBar?: boolean;
3614
+ }
3615
+ /**
3616
+ * Backwards-compatible alias for {@link FormSchemaSettings}.
3617
+ *
3618
+ * @deprecated Use `FormSchemaSettings` directly. The old root-level
3619
+ * `Form.settings` property has been removed in 1.32.1; settings now live
3620
+ * under `Form.schema.settings`. This alias will be removed in a future
3621
+ * major version.
3622
+ */
3623
+ type FormSettings = FormSchemaSettings;
3624
+ /**
3625
+ * Page definition for multi-page forms.
3626
+ *
3627
+ * Multi-page forms split fields across pages, identified by `fields` (a list
3628
+ * of `FormField.id` values that belong to the page). Single-page forms have
3629
+ * no `pages` entry on the schema.
3630
+ */
3631
+ interface FormPage {
3632
+ /**
3633
+ * Page title displayed at the top of the page.
3634
+ * `undefined` if not configured.
3635
+ */
3636
+ title?: string;
3637
+ /**
3638
+ * Page description displayed below the title.
3639
+ * `undefined` if not configured.
3640
+ */
3641
+ description?: string;
3642
+ /**
3643
+ * Ordered list of `FormField.id` values that belong to this page.
3644
+ * Each id must reference a field in `FormSchema.fields`.
3645
+ */
3646
+ fields: string[];
3647
+ }
3648
+ /**
3649
+ * Full schema describing a form's fields, layout, behavior, and conditional logic.
3650
+ *
3651
+ * Returned as the `schema` property of {@link Form} by `forms.getBySlug()`.
3652
+ * Render `fields` in order to build the form UI dynamically. Use `settings`
3653
+ * to wire the submit button and post-submission behavior. Use `conditions`
3654
+ * for cross-field rules (e.g. show field B when field A equals X).
3655
+ */
3656
+ interface FormSchema {
3657
+ /**
3658
+ * Ordered array of field definitions that make up the form.
3659
+ * Render in order to build the form UI.
3660
+ *
3661
+ * @see {@link FormField}
3662
+ */
3663
+ fields: FormField[];
3664
+ /**
3665
+ * Page definitions for multi-page forms.
3666
+ * `undefined` for single-page forms.
3667
+ *
3668
+ * @see {@link FormPage}
3669
+ */
3670
+ pages?: FormPage[];
3671
+ /**
3672
+ * Behavior settings (submit label, success message, redirect, progress bar).
3673
+ *
3674
+ * @see {@link FormSchemaSettings}
3675
+ */
3676
+ settings: FormSchemaSettings;
3677
+ /**
3678
+ * Cross-field conditional logic rules. Each rule references a field by id,
3679
+ * compares its value, and applies an action (show/hide/require/skip).
3680
+ *
3681
+ * @see {@link FormCondition}
3682
+ */
3683
+ conditions: FormCondition[];
3505
3684
  }
3506
3685
  /**
3507
3686
  * A public form available for submission.
3508
- * Returned by `GET /public/forms/:slug`.
3687
+ * Returned by `GET /public/{siteId}/forms/{slug}` and unwrapped from the
3688
+ * `{ data }` envelope by `forms.getBySlug()`.
3509
3689
  *
3510
- * Use `schema` to dynamically render the form fields, `settings` to configure
3511
- * the submit button and post-submission behavior, and the spam protection fields
3512
- * to set up honeypot or reCAPTCHA if enabled.
3690
+ * Use `schema.fields` to dynamically render the form fields, `schema.settings`
3691
+ * to configure the submit button and post-submission behavior, and the spam
3692
+ * protection flags to set up honeypot or reCAPTCHA if enabled.
3513
3693
  *
3514
3694
  * Only forms with `status: 'active'` are returned by the public API.
3515
3695
  * Draft, closed, and archived forms are never returned.
3516
3696
  */
3517
3697
  interface Form {
3518
3698
  /**
3519
- * Unique numeric form ID. Auto-incremented.
3699
+ * Unique form identifier (UUID v4).
3520
3700
  */
3521
- id: number;
3701
+ id: string;
3522
3702
  /**
3523
3703
  * Form display name (e.g. `'Contact Us'`, `'Newsletter Signup'`). Max 255 characters.
3524
3704
  */
@@ -3526,8 +3706,8 @@ interface Form {
3526
3706
  /**
3527
3707
  * URL-friendly slug, unique within the site.
3528
3708
  * Lowercase, hyphenated (e.g. `'contact-us'`). Max 255 characters.
3529
- * Used to fetch the form: `GET /public/forms/:slug`.
3530
- * Also used as the submission endpoint: `POST /public/forms/:slug/submit`.
3709
+ * Used to fetch the form: `GET /public/{siteId}/forms/{slug}`.
3710
+ * Also used as the submission endpoint: `POST /public/{siteId}/forms/{slug}/submit`.
3531
3711
  */
3532
3712
  slug: string;
3533
3713
  /**
@@ -3537,18 +3717,12 @@ interface Form {
3537
3717
  */
3538
3718
  description: string | null;
3539
3719
  /**
3540
- * Ordered array of field definitions that make up the form.
3541
- * Render these in order to build the form UI dynamically.
3542
- *
3543
- * @see {@link FormField}
3544
- */
3545
- schema: FormField[];
3546
- /**
3547
- * Form behavior settings (submit button text, success message, redirect).
3720
+ * Schema describing the form's fields, layout, behavior settings, and
3721
+ * conditional logic. Iterate `schema.fields` to render the form.
3548
3722
  *
3549
- * @see {@link FormSettings}
3723
+ * @see {@link FormSchema}
3550
3724
  */
3551
- settings: FormSettings;
3725
+ schema: FormSchema;
3552
3726
  /**
3553
3727
  * Form status. Always `'active'` via the public API.
3554
3728
  * Draft, closed, and archived forms are never returned by public endpoints.
@@ -3579,7 +3753,7 @@ interface Form {
3579
3753
  * 3. Include the reCAPTCHA token in the submission payload
3580
3754
  *
3581
3755
  * The SDK handles this automatically if you use `lynkow.forms.submit()`.
3582
- * Cannot be combined with honeypot only one spam protection method is active.
3756
+ * Cannot be combined with honeypot; only one spam protection method is active.
3583
3757
  *
3584
3758
  * `undefined` or `false` means reCAPTCHA is not active.
3585
3759
  */
@@ -3590,17 +3764,21 @@ interface Form {
3590
3764
  * `null` or `undefined` when reCAPTCHA is not configured.
3591
3765
  *
3592
3766
  * Pass this to `grecaptcha.render()` or the `sitekey` parameter in the reCAPTCHA script URL.
3593
- * The secret key is never exposed it stays server-side.
3767
+ * The secret key is never exposed; it stays server-side.
3594
3768
  */
3595
3769
  recaptchaSiteKey?: string | null;
3596
3770
  }
3597
3771
  /**
3598
3772
  * Data payload for submitting a form.
3599
3773
  *
3600
- * Keys correspond to `FormField.name` values from the form's `schema`.
3774
+ * Keys correspond to `FormField.id` values from the form's `schema.fields`.
3775
+ * IDs are auto-generated by the admin (e.g. `'field_1764776796820'`),
3776
+ * not human-readable names. Always derive the keys from the schema returned
3777
+ * by `forms.getBySlug()`; do not hard-code semantic names.
3778
+ *
3601
3779
  * Value types depend on the field type:
3602
3780
  * - Text fields (`text`, `email`, `textarea`, `url`, `tel`): `string`
3603
- * - Number fields: `number`
3781
+ * - Number fields (`number`, `rating`): `number`
3604
3782
  * - Checkbox (single): `boolean`
3605
3783
  * - File fields: `File` (browser File object)
3606
3784
  * - Select/radio/checkbox (with options): `string` (the selected option's `value`)
@@ -3610,13 +3788,15 @@ interface Form {
3610
3788
  *
3611
3789
  * @example
3612
3790
  * ```typescript
3613
- * const data: FormSubmitData = {
3614
- * name: 'Jane Doe',
3615
- * email: 'jane@example.com',
3616
- * message: 'Hello!',
3617
- * newsletter: true,
3791
+ * const form = await lynkow.forms.getBySlug('contact')
3792
+ *
3793
+ * // Build the payload keyed by field.id (the auto-generated identifier)
3794
+ * const data: FormSubmitData = {}
3795
+ * for (const field of form.schema.fields) {
3796
+ * data[field.id] = readValueForField(field) // your UI binding
3618
3797
  * }
3619
- * await lynkow.forms.submit('contact-us', data)
3798
+ *
3799
+ * await lynkow.forms.submit('contact', data)
3620
3800
  * ```
3621
3801
  */
3622
3802
  type FormSubmitData = Record<string, string | number | boolean | File>;
@@ -4594,14 +4774,21 @@ interface CategoryDetailResponse {
4594
4774
  }
4595
4775
  /**
4596
4776
  * Response from `tags.list()`.
4597
- * Returns all tags in a single non-paginated response.
4777
+ * Paginated since SDK 1.32.2 (the wire was already returning `meta`; the SDK
4778
+ * type now exposes it). Server-side default is 20 items per page on
4779
+ * `/v1/tags` and `/public/.../tags`, with `maxLimit=100` (ADR-0022 D3).
4598
4780
  */
4599
4781
  interface TagsListResponse {
4600
4782
  /**
4601
- * Flat array of all tags for the current locale.
4602
- * Not paginated -- all tags are returned at once.
4783
+ * Tags for the current page in the current locale.
4784
+ * Empty array when no tags match (or when paging past the last page).
4603
4785
  */
4604
4786
  data: Tag[];
4787
+ /**
4788
+ * Pagination metadata describing total count, page position, and navigation
4789
+ * flags. See {@link PaginationMeta}.
4790
+ */
4791
+ meta: PaginationMeta;
4605
4792
  }
4606
4793
  /**
4607
4794
  * Response from `pages.list()`.
@@ -4878,7 +5065,11 @@ interface BaseRequestOptions {
4878
5065
  }
4879
5066
  /**
4880
5067
  * Pagination options for list endpoints.
4881
- * All values are 1-based integers. The API defaults to page 1 with 15 items per page.
5068
+ *
5069
+ * All values are 1-based integers. The server default is 20 items per page
5070
+ * on public-tier endpoints (`/public`, `/v1`) and 50 on admin-tier
5071
+ * endpoints (`/api`, `/admin`), per ADR-0022 D3. Documented exceptions:
5072
+ * SSG endpoints like `/public/.../categories/:slug` default to 500.
4882
5073
  */
4883
5074
  interface PaginationOptions {
4884
5075
  /**
@@ -4889,8 +5080,10 @@ interface PaginationOptions {
4889
5080
  page?: number;
4890
5081
  /**
4891
5082
  * Maximum number of items per page.
4892
- * Defaults to 15. Maximum allowed value is 100.
4893
- * Values above 100 are silently capped by the API.
5083
+ * Server default is 20 on public-tier endpoints (`/public`, `/v1`).
5084
+ * Maximum allowed value is 100 (except documented SSG exceptions like
5085
+ * `/public/.../categories/:slug` which permit up to 500).
5086
+ * Values above the per-endpoint maximum are silently capped by the API.
4894
5087
  */
4895
5088
  limit?: number;
4896
5089
  /**
@@ -4977,6 +5170,25 @@ interface CategoryOptions extends PaginationOptions {
4977
5170
  */
4978
5171
  locale?: string;
4979
5172
  }
5173
+ /**
5174
+ * Filters for the `tags.list()` endpoint.
5175
+ *
5176
+ * Pagination + locale. The public `/v1/tags` endpoint does not expose
5177
+ * search or sort on its public surface. `limit` defaults to 20 server-side
5178
+ * on the public-tier mounts (`/public/.../tags`, `/v1/tags`) per
5179
+ * ADR-0022 D3, with `maxLimit=100`.
5180
+ */
5181
+ interface TagsListFilters extends PaginationOptions {
5182
+ /**
5183
+ * Locale override for this request.
5184
+ * When omitted, uses the client's default locale or the site's default locale.
5185
+ * If both `filters.locale` and `options.locale` are passed, `options.locale`
5186
+ * wins (mirrors `contents.list()` precedence).
5187
+ *
5188
+ * @example 'fr'
5189
+ */
5190
+ locale?: string;
5191
+ }
4980
5192
  /**
4981
5193
  * Filters for the `reviews.list()` endpoint.
4982
5194
  * Only approved reviews are returned; these filters further narrow the result set.
@@ -6670,4 +6882,4 @@ declare function renderJsonLdGraph(nodes: object[] | null | undefined): string;
6670
6882
  */
6671
6883
  declare function mergeIntoGraph(server: object[] | null | undefined, custom: object[] | null | undefined): object[];
6672
6884
 
6673
- export { type Alternate, AnalyticsService, type ApiErrorDetail, type Author, type BaseRequestOptions, BlocksService, BrandingService, type CategoriesListResponse, CategoriesService, type Category, type CategoryDetail, type CategoryDetailResponse, type CategoryOptions, type CategoryResolveResponse, type CategoryTreeNode, type CategoryTreeResponse, type CategoryWithCount, type Client, type ClientConfig, type ConsentCategories, type ConsentLogResponse, ConsentService, type Content, type ContentBody, type ContentResolveResponse, type ContentSchema, type ContentSummary, type ContentsFilters, type ContentsListResponse, ContentsService, type CookieCategory, type CookieConfig, type CookiePreferences, type CookieTexts, CookiesService, type EnhancementsInitOptions, EnhancementsService, type ErrorCode, type EventData, type EventName, type Form, type FormField, type FormFieldOption, type FormFieldType, type FormFieldValidation, type FormSettings, type FormSubmitData, type FormSubmitResponse, FormsService, type GlobalBlock, type GlobalBlockResponse, type ImageVariants, type JsonLdGraphConfig, type JsonLdNode, type JsonLdNodeSource, type LegalDocument, LegalService, type LynkowClient, type LynkowConfig, LynkowError, type LynkowEvents, MediaHelperService, type Page, type PageSeo, type PageSummary, type PagesListResponse, PagesService, type PageviewData, type PaginatedResponse, type PaginationMeta, type PaginationOptions, type Path, type PathsListResponse, PathsService, type Redirect, type ResolveResponse, type Review, type ReviewResponse, type ReviewSettings, type ReviewSubmitData, type ReviewSubmitResponse, type ReviewsFilters, type ReviewsListResponse, ReviewsService, type SchemaField, type SchemaFieldOption, type SchemaFieldType, type SchemaFieldValidation, type SearchConfig, type SearchHit, type SearchOptions, type SearchProfilePublic, type SearchResponse, SearchService, SeoService, type SiteConfig, type SiteConfigResponse, SiteService, type SortOptions, type SrcsetOptions, type SubmitOptions, type Tag, type TagsListResponse, TagsService, type TipTapMark, type TipTapNode, type TransformOptions, browserOnly, browserOnlyAsync, createClient, createLynkowClient, detectSiteTheme, isBrowser, isCategoryResolve, isContentResolve, isLynkowError, isServer, mergeIntoGraph, onSiteThemeChange, renderJsonLdGraph };
6885
+ export { type Alternate, AnalyticsService, type ApiErrorDetail, type Author, type BaseRequestOptions, BlocksService, BrandingService, type CategoriesListResponse, CategoriesService, type Category, type CategoryDetail, type CategoryDetailResponse, type CategoryOptions, type CategoryResolveResponse, type CategoryTreeNode, type CategoryTreeResponse, type CategoryWithCount, type Client, type ClientConfig, type ConsentCategories, type ConsentLogResponse, ConsentService, type Content, type ContentBody, type ContentResolveResponse, type ContentSchema, type ContentSummary, type ContentsFilters, type ContentsListResponse, ContentsService, type CookieCategory, type CookieConfig, type CookiePreferences, type CookieTexts, CookiesService, type EnhancementsInitOptions, EnhancementsService, type ErrorCode, type EventData, type EventName, type Form, type FormCondition, type FormField, type FormFieldOption, type FormFieldPhoneOptions, type FormFieldType, type FormFieldValidation, type FormPage, type FormSchema, type FormSchemaSettings, type FormSettings, type FormSubmitData, type FormSubmitResponse, FormsService, type GlobalBlock, type GlobalBlockResponse, type ImageVariants, type JsonLdGraphConfig, type JsonLdNode, type JsonLdNodeSource, type LegalDocument, LegalService, type LynkowClient, type LynkowConfig, LynkowError, type LynkowEvents, MediaHelperService, type Page, type PageSeo, type PageSummary, type PagesListResponse, PagesService, type PageviewData, type PaginatedResponse, type PaginationMeta, type PaginationOptions, type Path, type PathsListResponse, PathsService, type Redirect, type ResolveResponse, type Review, type ReviewResponse, type ReviewSettings, type ReviewSubmitData, type ReviewSubmitResponse, type ReviewsFilters, type ReviewsListResponse, ReviewsService, type SchemaField, type SchemaFieldOption, type SchemaFieldType, type SchemaFieldValidation, type SearchConfig, type SearchHit, type SearchOptions, type SearchProfilePublic, type SearchResponse, SearchService, SeoService, type SiteConfig, type SiteConfigResponse, SiteService, type SortOptions, type SrcsetOptions, type SubmitOptions, type Tag, type TagsListFilters, type TagsListResponse, TagsService, type TipTapMark, type TipTapNode, type TransformOptions, browserOnly, browserOnlyAsync, createClient, createLynkowClient, detectSiteTheme, isBrowser, isCategoryResolve, isContentResolve, isLynkowError, isServer, mergeIntoGraph, onSiteThemeChange, renderJsonLdGraph };