@lacneu/wix-openclaw 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +161 -74
  3. package/dist/tools/_query.d.ts +117 -0
  4. package/dist/tools/_query.js +240 -0
  5. package/dist/tools/_query.js.map +1 -0
  6. package/dist/tools/blog.d.ts +92 -0
  7. package/dist/tools/blog.js +122 -20
  8. package/dist/tools/blog.js.map +1 -1
  9. package/dist/tools/bookings.d.ts +18 -22
  10. package/dist/tools/bookings.js +28 -19
  11. package/dist/tools/bookings.js.map +1 -1
  12. package/dist/tools/contacts.d.ts +20 -2
  13. package/dist/tools/contacts.js +27 -16
  14. package/dist/tools/contacts.js.map +1 -1
  15. package/dist/tools/data.d.ts +14 -2
  16. package/dist/tools/data.js +22 -35
  17. package/dist/tools/data.js.map +1 -1
  18. package/dist/tools/events.d.ts +44 -4
  19. package/dist/tools/events.js +29 -28
  20. package/dist/tools/events.js.map +1 -1
  21. package/dist/tools/faq.d.ts +12 -0
  22. package/dist/tools/faq.js +15 -9
  23. package/dist/tools/faq.js.map +1 -1
  24. package/dist/tools/forms.d.ts +24 -4
  25. package/dist/tools/forms.js +38 -25
  26. package/dist/tools/forms.js.map +1 -1
  27. package/dist/tools/media.d.ts +4 -0
  28. package/dist/tools/media.js +32 -23
  29. package/dist/tools/media.js.map +1 -1
  30. package/dist/tools/multilingual.d.ts +21 -1
  31. package/dist/tools/multilingual.js +16 -18
  32. package/dist/tools/multilingual.js.map +1 -1
  33. package/dist/tools/reviews.d.ts +22 -2
  34. package/dist/tools/reviews.js +18 -16
  35. package/dist/tools/reviews.js.map +1 -1
  36. package/dist/tools/site.d.ts +20 -0
  37. package/dist/tools/site.js +17 -25
  38. package/dist/tools/site.js.map +1 -1
  39. package/openclaw.plugin.json +1 -1
  40. package/package.json +4 -2
package/CHANGELOG.md CHANGED
@@ -7,6 +7,82 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0] - 2026-04-29
11
+
12
+ ### Added
13
+ - **Wix query envelope passthrough** — every POST `/query` tool now
14
+ accepts the full Wix Query Language envelope (`filter`, `sort`,
15
+ `paging`, `cursorPaging`, `fields`) as plain optional parameters.
16
+ Filters can use any MongoDB-style operator the Wix API supports
17
+ (`$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$exists`,
18
+ `$startsWith`, `$contains`, `$hasSome`, `$hasAll`, `$matches`, `$and`,
19
+ `$or`, `$not`). See https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/data-retrieval/about-the-wix-api-query-language
20
+ - **`wix_blog_list_drafts.status` filter** — new optional parameter
21
+ with values `UNPUBLISHED | PUBLISHED | SCHEDULED | IN_REVIEW | ALL`
22
+ (default `ALL` = previous behaviour, returns drafts with all
23
+ statuses by omitting the parameter).
24
+ - **`wix_blog_list_drafts.sort`** — `EDITING_DATE_ASC` /
25
+ `EDITING_DATE_DESC` (verified live).
26
+ - **`wix_blog_list_drafts.fieldsets`** — response projection,
27
+ e.g. `["URL"]`, `["RICH_CONTENT"]` (verified live).
28
+ - **`wix_blog_list_published`** — added `sort`
29
+ (`PUBLISHED_DATE_*` / `VIEW_COUNT_*` / `LIKE_COUNT_*`),
30
+ `featured`, `language`, `tagIds`, `categoryIds`, `fieldsets`.
31
+ - **`wix_blog_list_categories` / `wix_blog_list_tags`** — added
32
+ `language` and `paging` options.
33
+ - **`wix_media_list.mediaTypes`** — restrict by `IMAGE | VIDEO | AUDIO
34
+ | DOCUMENT | ARCHIVE` and `paging.cursor` for cursor walks
35
+ (verified live).
36
+ - **`wix_data_query_items`** — full Wix query envelope replaces the
37
+ ad-hoc filter/sort/paging fields.
38
+ - **`wix_sites_list`** — full envelope (filter on `metaSiteId`,
39
+ `displayName`, `published`, `domainConnected`).
40
+ - **`wix_forms_list_submissions`** — namespace pinning is now
41
+ `$and`-merged with passthrough filter so shortcuts can never be
42
+ silently overridden by the agent.
43
+ - **`wix_events_list_guests`** — `eventId` is now `$and`-merged with
44
+ passthrough filter (same guarantee).
45
+ - New shared module `src/tools/_query.ts` — single source of truth
46
+ for query envelope mapping (`buildQueryBody`, `mergeFilter`,
47
+ `buildGetPagingQuery`, `compactQuery`).
48
+ - Smoke test now runs **two passes**: endpoint reachability (direct
49
+ `client.request()`) AND tool-execute scenarios
50
+ (`tool.execute(callId, params)`) covering at least one filter / sort
51
+ / paging case per installed-app tool family.
52
+ - New per-family unit tests:
53
+ `test/tools/_query.test.ts` (mapper),
54
+ `test/tools/contacts.test.ts`, `test/tools/bookings.test.ts`,
55
+ `test/tools/forms.test.ts`, `test/tools/data.test.ts`,
56
+ `test/tools/media.test.ts` — assert that
57
+ `tool.execute(...)` lands the right keys in body/query.
58
+
59
+ ### Fixed
60
+ - Manifest version mismatch — `openclaw.plugin.json` was `0.1.0` while
61
+ `package.json` was `0.1.1`. Both bumped to `0.2.0`.
62
+
63
+ ### Notes
64
+ - **`wix_blog_list_drafts.status === "ALL"`** is a client-side
65
+ convention; it maps to "no `status` query param" because Wix returns
66
+ HTTP 400 for any unknown status value. Default behaviour is
67
+ unchanged — drafts with every status are returned.
68
+ - **Multilingual `403`** observed on the smoke-test site is a key
69
+ permission issue (`Multilingual Translation Schema Read` not
70
+ granted), distinct from app-not-installed. Confirm the permission
71
+ on your API key if you need multilingual reads.
72
+ - **Reachability baseline 12/20** matches v0.1.1: the 8 failures are
73
+ legitimate "app not installed on Ataraxis" responses (Events,
74
+ Reviews, FAQ, Multilingual permission, Velo not enabled).
75
+
76
+ ## [0.1.1] - 2026-04-29
77
+
78
+ ### Fixed
79
+ - Move `@sinclair/typebox` from `devDependencies` to `dependencies` so the
80
+ plugin can resolve the import at runtime when installed via
81
+ `openclaw plugins install`. Without this, the plugin failed to load
82
+ with `Cannot find module '@sinclair/typebox'`.
83
+
84
+ ## [0.1.0] - 2026-04-29
85
+
10
86
  ### Changed
11
87
  - `wix_site_url_get` now reads `viewUrl` from the Site List API response
12
88
  rather than calling the legacy `/urls-server/v2/published-site-urls`
package/README.md CHANGED
@@ -8,6 +8,7 @@
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
9
9
  [![OpenClaw](https://img.shields.io/badge/OpenClaw-%E2%89%A5v2026.4.0-blue)](https://github.com/openclaw/openclaw)
10
10
  [![npm version](https://img.shields.io/npm/v/@lacneu/wix-openclaw.svg)](https://www.npmjs.com/package/@lacneu/wix-openclaw)
11
+ [![Plugin version](https://img.shields.io/badge/version-0.2.0-blue)](CHANGELOG.md)
11
12
 
12
13
  ---
13
14
 
@@ -266,30 +267,101 @@ flushes the previous credential.
266
267
 
267
268
  ---
268
269
 
270
+ ## Wix query envelope
271
+
272
+ Every POST `/query` tool (`wix_contacts_query`, `wix_bookings_*_list`,
273
+ `wix_forms_list_submissions`, `wix_events_*`, `wix_reviews_list`,
274
+ `wix_multilingual_list_languages`, `wix_sites_list`,
275
+ `wix_data_query_items`) accepts the standard Wix Query Language
276
+ envelope as plain optional parameters:
277
+
278
+ ```jsonc
279
+ {
280
+ // Optional — MongoDB-style filter, e.g.
281
+ // { "status": { "$in": ["ACTIVE", "PENDING"] } }
282
+ // { "$and": [{ "createdDate": { "$gt": "2026-01-01T00:00:00Z" } },
283
+ // { "info.emails.email": { "$contains": "acme" } }] }
284
+ "filter": { /* ... */ },
285
+
286
+ // Optional — sort entries applied in order
287
+ "sort": [{ "fieldName": "createdDate", "order": "DESC" }],
288
+
289
+ // Optional — offset paging (most endpoints)
290
+ "paging": { "limit": 50, "offset": 0 },
291
+
292
+ // Optional — cursor paging (Site Media, some Bookings, ...)
293
+ "cursorPaging": { "limit": 50, "cursor": "<opaque>" },
294
+
295
+ // Optional — projection
296
+ "fields": ["id", "info.name"]
297
+ }
298
+ ```
299
+
300
+ Supported operators (per the [Wix Query Language docs](https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/data-retrieval/about-the-wix-api-query-language)):
301
+ `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`,
302
+ `$exists`, `$startsWith`, `$contains`, `$hasSome`, `$hasAll`,
303
+ `$matches`, `$and`, `$or`, `$not`.
304
+
305
+ > **Live verification scope**
306
+ > The plugin's smoke test currently exercises `$eq`, `$in`, `$exists`,
307
+ > field equality, sort entries, offset paging, and free-text `search`
308
+ > against the Ataraxis site. Other operators (`$ne`, `$gt`, `$gte`,
309
+ > `$lt`, `$lte`, `$nin`, `$startsWith`, `$contains`, `$hasSome`,
310
+ > `$hasAll`, `$matches`, `$or`, `$not`) and `cursorPaging` /
311
+ > `fields` projection are exposed structurally and routed to the body
312
+ > by the mapper, but per-operator live coverage on every endpoint is
313
+ > not in v0.2.0's scope. Each Wix endpoint individually decides which
314
+ > fields are filterable and which operators are accepted — Wix returns
315
+ > a clean `400 UNSUPPORTED_QUERY_FILTER` when it disagrees, surfaced
316
+ > as a tool failure to the model.
317
+
318
+ Tools that have ergonomic shortcuts (e.g. `wix_blog_list_drafts.status`,
319
+ `wix_forms_list_submissions.namespace`) **always merge** the shortcut
320
+ into the filter via `$and`, so the agent can never silently override the
321
+ shortcut by passing a competing `filter`.
322
+
323
+ Flat GET endpoints (`wix_blog_list_drafts`, `wix_blog_list_published`,
324
+ `wix_blog_list_categories`, `wix_blog_list_tags`,
325
+ `wix_data_list_collections`, `wix_faq_list_*`, `wix_media_list`,
326
+ `wix_multilingual_list_schemas`) accept named query string params plus
327
+ `paging.{limit,offset,cursor}` — they do NOT support the operator
328
+ passthrough above. Each tool's parameters are documented in its
329
+ description.
330
+
331
+ ---
332
+
269
333
  ## Tools
270
334
 
335
+ The `Validated` column reflects v0.2.0 verification on the Ataraxis
336
+ Coaching site: `live` means hit by the smoke-test against a real Wix
337
+ site; `app-not-installed` and `velo-not-enabled` mean the tool's
338
+ endpoint exists but its backing Wix product is not active on the
339
+ smoke-test site (the request still reaches Wix and the path/headers
340
+ are correct); `docs` means write/destructive endpoints that we do not
341
+ exercise live.
342
+
271
343
  ### Blog
272
344
 
273
- | Tool | What it does | Approval |
274
- |---|---|---|
275
- | `wix_blog_list_drafts` | List draft posts | — |
276
- | `wix_blog_get_draft` | Fetch a draft by id | — |
277
- | `wix_blog_create_draft` | Create a new draft | — |
278
- | `wix_blog_update_draft` | Patch a draft | — |
279
- | `wix_blog_publish_draft` | Publish a draft | required |
280
- | `wix_blog_list_published` | List published posts | — |
281
- | `wix_blog_get_post` | Fetch a published post | — |
282
- | `wix_blog_unpublish` | Move post to trash (reversible) | required |
283
- | `wix_blog_delete_draft` | Permanently delete a draft | required |
284
- | `wix_blog_list_categories` | List blog categories | — |
285
- | `wix_blog_list_tags` | List blog tags | — |
345
+ | Tool | What it does | Approval | Validated |
346
+ |---|---|---|---|
347
+ | `wix_blog_list_drafts` | List drafts; supports `status` (`UNPUBLISHED \| PUBLISHED \| SCHEDULED \| IN_REVIEW \| ALL`), `sort`, `fieldsets`, `paging` | — | live |
348
+ | `wix_blog_get_draft` | Fetch a draft by id; supports `fieldsets` | — | live |
349
+ | `wix_blog_create_draft` | Create a new draft | — | docs |
350
+ | `wix_blog_update_draft` | Patch a draft | — | docs |
351
+ | `wix_blog_publish_draft` | Publish a draft | required | docs |
352
+ | `wix_blog_list_published` | List published posts; supports `sort`, `featured`, `language`, `tagIds`, `categoryIds`, `fieldsets`, `paging` | — | live |
353
+ | `wix_blog_get_post` | Fetch a published post; supports `fieldsets` | — | live |
354
+ | `wix_blog_unpublish` | Move post to trash (reversible) | required | docs |
355
+ | `wix_blog_delete_draft` | Permanently delete a draft | required | docs |
356
+ | `wix_blog_list_categories` | List blog categories; supports `language`, `paging` | — | live |
357
+ | `wix_blog_list_tags` | List blog tags; supports `language`, `paging` | — | live |
286
358
 
287
359
  ### Media
288
360
 
289
- | Tool | What it does | Approval |
290
- |---|---|---|
291
- | `wix_media_upload` | Import image into Site Media by URL | — |
292
- | `wix_media_list` | List files in the media library | — |
361
+ | Tool | What it does | Approval | Validated |
362
+ |---|---|---|---|
363
+ | `wix_media_upload` | Import image into Site Media by URL | — | docs |
364
+ | `wix_media_list` | List files; supports `parentFolderId`, `mediaTypes` (IMAGE/VIDEO/AUDIO/DOCUMENT/ARCHIVE), cursor paging via `paging.cursor` | — | live |
293
365
 
294
366
  The `wix_media_upload` tool returns the Wix file metadata, including the
295
367
  `id`. Pass that id back into `wix_blog_create_draft` as
@@ -298,90 +370,105 @@ the tool description for the contract the LLM should follow.
298
370
 
299
371
  ### Site
300
372
 
301
- | Tool | What it does | Approval |
302
- |---|---|---|
303
- | `wix_sites_list` | List sites under the account (account-scoped) | — |
304
- | `wix_site_url_get` | Get published URL of a site | — |
305
- | `wix_business_info_get` | Read business info (name, address, hours) | — |
373
+ | Tool | What it does | Approval | Validated |
374
+ |---|---|---|---|
375
+ | `wix_sites_list` | List sites under the account (account-scoped); accepts the standard Wix query envelope | — | live |
376
+ | `wix_site_url_get` | Get published URL of a site | — | live |
377
+ | `wix_business_info_get` | Read business info (name, address, hours) | — | live |
306
378
 
307
379
  ### CMS Data
308
380
 
309
- | Tool | What it does | Approval |
310
- |---|---|---|
311
- | `wix_data_list_collections` | List CMS collections + schemas | — |
312
- | `wix_data_query_items` | Mongo-style filter on a collection | — |
313
- | `wix_data_get_item` | Fetch one item by id | |
314
- | `wix_data_insert_item` | Insert a new item | — |
315
- | `wix_data_update_item` | Update an item | — |
316
- | `wix_data_remove_item` | Delete an item | required |
381
+ Requires Velo / Wix Code to be enabled on the target site (Wix Editor →
382
+ Velo → Enable Code). Without it, calls return HTTP 400 `WDE0110: Wix
383
+ Code not enabled`.
384
+
385
+ | Tool | What it does | Approval | Validated |
386
+ |---|---|---|---|
387
+ | `wix_data_list_collections` | List CMS collections + schemas | — | velo-not-enabled |
388
+ | `wix_data_query_items` | Full Wix query envelope on a collection | | velo-not-enabled |
389
+ | `wix_data_get_item` | Fetch one item by id | — | velo-not-enabled |
390
+ | `wix_data_insert_item` | Insert a new item | — | docs |
391
+ | `wix_data_update_item` | Update an item | — | docs |
392
+ | `wix_data_remove_item` | Delete an item | required | docs |
317
393
 
318
394
  ### Forms
319
395
 
320
- | Tool | What it does | Approval |
321
- |---|---|---|
322
- | `wix_forms_list_submissions` | List submissions / leads | — |
323
- | `wix_forms_get_submission` | Fetch a single submission | — |
396
+ | Tool | What it does | Approval | Validated |
397
+ |---|---|---|---|
398
+ | `wix_forms_list_submissions` | Full Wix query envelope; `namespace` defaults to `wix.form_app.form` and is always `$and`-merged with passthrough filter | — | live |
399
+ | `wix_forms_get_submission` | Fetch a single submission | — | docs |
324
400
 
325
401
  ### Contacts
326
402
 
327
- | Tool | What it does | Approval |
328
- |---|---|---|
329
- | `wix_contacts_query` | Search contacts | — |
330
- | `wix_contacts_get` | Get one contact | — |
331
- | `wix_contacts_create` | Create a contact | — |
332
- | `wix_contacts_update` | Update a contact | — |
333
- | `wix_contacts_label_add` | Add labels to a contact | — |
334
- | `wix_contacts_delete` | Delete a contact | required |
403
+ | Tool | What it does | Approval | Validated |
404
+ |---|---|---|---|
405
+ | `wix_contacts_query` | Full Wix query envelope + free-text `search` | — | live |
406
+ | `wix_contacts_get` | Get one contact | — | docs |
407
+ | `wix_contacts_create` | Create a contact | — | docs |
408
+ | `wix_contacts_update` | Update a contact | — | docs |
409
+ | `wix_contacts_label_add` | Add labels to a contact | — | docs |
410
+ | `wix_contacts_delete` | Delete a contact | required | docs |
335
411
 
336
412
  ### Bookings
337
413
 
338
- | Tool | What it does | Approval |
339
- |---|---|---|
340
- | `wix_bookings_services_list` | List bookable services | — |
341
- | `wix_bookings_query_bookings` | Query existing bookings | — |
342
- | `wix_bookings_get_booking` | Fetch one booking | — |
343
- | `wix_bookings_create` | Create a booking | — |
344
- | `wix_bookings_reschedule` | Move to a different slot | required |
345
- | `wix_bookings_cancel` | Cancel a booking | required |
414
+ | Tool | What it does | Approval | Validated |
415
+ |---|---|---|---|
416
+ | `wix_bookings_services_list` | List bookable services; standard query envelope | — | live |
417
+ | `wix_bookings_query_bookings` | Query bookings with operators (e.g. `status: { $in: [...] }`); standard query envelope | — | live |
418
+ | `wix_bookings_get_booking` | Fetch one booking | — | docs |
419
+ | `wix_bookings_create` | Create a booking | — | docs |
420
+ | `wix_bookings_reschedule` | Move to a different slot | required | docs |
421
+ | `wix_bookings_cancel` | Cancel a booking | required | docs |
346
422
 
347
423
  ### Events
348
424
 
349
- | Tool | What it does | Approval |
350
- |---|---|---|
351
- | `wix_events_list` | List events | — |
352
- | `wix_events_get` | Fetch one event | |
353
- | `wix_events_list_guests` | List guests / RSVPs / orders | — |
425
+ Requires the Wix Events app (returns `428 WIX_EVENTS_APP_NOT_INSTALLED`
426
+ otherwise).
427
+
428
+ | Tool | What it does | Approval | Validated |
429
+ |---|---|---|---|
430
+ | `wix_events_list` | List events; standard query envelope | — | app-not-installed |
431
+ | `wix_events_get` | Fetch one event | — | app-not-installed |
432
+ | `wix_events_list_guests` | List guests / RSVPs; `eventId` is `$and`-merged with passthrough filter | — | app-not-installed |
354
433
 
355
434
  ### Reviews
356
435
 
357
- | Tool | What it does | Approval |
358
- |---|---|---|
359
- | `wix_reviews_list` | List reviews | |
360
- | `wix_reviews_get` | Fetch one review | — |
361
- | `wix_reviews_moderate` | Approve / reject a pending review | required |
436
+ Requires the Wix Reviews app (returns `428 APP_NOT_INSTALLED` otherwise).
437
+
438
+ | Tool | What it does | Approval | Validated |
439
+ |---|---|---|---|
440
+ | `wix_reviews_list` | List reviews; standard query envelope | | app-not-installed |
441
+ | `wix_reviews_get` | Fetch one review | — | docs |
442
+ | `wix_reviews_moderate` | Approve / reject a pending review | required | docs |
362
443
 
363
444
  ### FAQ
364
445
 
365
- | Tool | What it does | Approval |
366
- |---|---|---|
367
- | `wix_faq_list_categories` | List FAQ categories | |
368
- | `wix_faq_list_questions` | List questions (filterable by category) | — |
369
- | `wix_faq_create_question` | Create a question | — |
370
- | `wix_faq_update_question` | Update a question | — |
371
- | `wix_faq_delete_question` | Delete a question | required |
446
+ Requires the Wix FAQ app (returns `400 App is not installed` otherwise).
447
+
448
+ | Tool | What it does | Approval | Validated |
449
+ |---|---|---|---|
450
+ | `wix_faq_list_categories` | List FAQ categories | — | app-not-installed |
451
+ | `wix_faq_list_questions` | List questions (filterable by category) | — | app-not-installed |
452
+ | `wix_faq_create_question` | Create a question | | docs |
453
+ | `wix_faq_update_question` | Update a question | — | docs |
454
+ | `wix_faq_delete_question` | Delete a question | required | docs |
372
455
 
373
456
  ### Multilingual (read-only in V1)
374
457
 
375
- | Tool | What it does | Approval |
376
- |---|---|---|
377
- | `wix_multilingual_list_languages` | List configured languages | — |
378
- | `wix_multilingual_get_translation` | Read a translation by key | — |
458
+ Returns `403` on the Ataraxis smoke-test site likely missing the
459
+ `Multilingual Translation Schema Read` permission on the API key
460
+ rather than an app-not-installed condition.
461
+
462
+ | Tool | What it does | Approval | Validated |
463
+ |---|---|---|---|
464
+ | `wix_multilingual_list_languages` | List configured languages; standard query envelope | — | 403-permission |
465
+ | `wix_multilingual_list_schemas` | List translation schemas | — | 403-permission |
379
466
 
380
467
  ### Design
381
468
 
382
- | Tool | What it does | Approval |
383
- |---|---|---|
384
- | `wix_design_brief` | Turn a loose textual brief into a structured markdown artefact (palette, typography, sections, image-gen prompts). **Does NOT call the Wix API.** | — |
469
+ | Tool | What it does | Approval | Validated |
470
+ |---|---|---|---|
471
+ | `wix_design_brief` | Turn a loose textual brief into a structured markdown artefact (palette, typography, sections, image-gen prompts). **Does NOT call the Wix API.** | — | n/a |
385
472
 
386
473
  ---
387
474
 
@@ -0,0 +1,117 @@
1
+ import type { Static } from "@sinclair/typebox";
2
+ /**
3
+ * Sort entry — `fieldName` is the dotted path (e.g.
4
+ * `info.emails.email`), `order` is `ASC` (default) or `DESC`. Maps 1:1
5
+ * to the Wix sort entry shape.
6
+ */
7
+ export declare const WixSortEntrySchema: import("@sinclair/typebox").TObject<{
8
+ fieldName: import("@sinclair/typebox").TString;
9
+ order: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"ASC">, import("@sinclair/typebox").TLiteral<"DESC">]>>;
10
+ }>;
11
+ /**
12
+ * Offset paging — preferred form for POST /query endpoints that don't
13
+ * stream very large result sets. `limit` defaults to 50 server-side.
14
+ */
15
+ export declare const WixOffsetPagingSchema: import("@sinclair/typebox").TObject<{
16
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
17
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
18
+ }>;
19
+ /**
20
+ * Cursor paging — used by endpoints that need stable iteration over
21
+ * large or fast-changing collections (e.g. Site Media, some Bookings
22
+ * queries). Pass back the `cursor` returned in `pagingMetadata.cursors.next`.
23
+ */
24
+ export declare const WixCursorPagingSchema: import("@sinclair/typebox").TObject<{
25
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
26
+ cursor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
27
+ }>;
28
+ /**
29
+ * Generic query body envelope shared by every POST /query tool.
30
+ *
31
+ * The `filter` is intentionally typed as `Type.Unknown()` — Wix accepts
32
+ * arbitrarily nested MongoDB-style operator trees that we don't try to
33
+ * model in TypeBox. The agent gets full operator richness; tools layer
34
+ * ergonomic shortcuts on top by merging into this filter.
35
+ *
36
+ * Per-tool ergonomic shortcuts (e.g. `wix_blog_list_drafts.status`)
37
+ * compose with `filter` via {@link mergeFilter}.
38
+ */
39
+ export declare const WixQueryBodyEnvelopeSchema: import("@sinclair/typebox").TObject<{
40
+ filter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
41
+ sort: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
42
+ fieldName: import("@sinclair/typebox").TString;
43
+ order: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"ASC">, import("@sinclair/typebox").TLiteral<"DESC">]>>;
44
+ }>>>;
45
+ paging: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
46
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
47
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
48
+ }>>;
49
+ cursorPaging: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
50
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
51
+ cursor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
52
+ }>>;
53
+ fields: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
54
+ }>;
55
+ export type WixQueryBodyEnvelope = Static<typeof WixQueryBodyEnvelopeSchema>;
56
+ /**
57
+ * Build the JSON body for a POST /query call.
58
+ *
59
+ * Returns `{ query: { ... } }` with only the populated keys — Wix
60
+ * rejects empty `paging: {}` and friends on some endpoints.
61
+ *
62
+ * `extraFilter` is merged into `envelope.filter` via {@link mergeFilter}.
63
+ * Use it when a tool layers ergonomic shortcuts on top of the raw
64
+ * passthrough (e.g. `wix_forms_list_submissions` always pins
65
+ * `namespace`).
66
+ */
67
+ export declare function buildQueryBody(envelope: WixQueryBodyEnvelope | undefined, extraFilter?: Record<string, unknown>): {
68
+ query: Record<string, unknown>;
69
+ };
70
+ /**
71
+ * Merge a tool-level shortcut filter (`extra`) with a user-provided
72
+ * passthrough filter (`base`).
73
+ *
74
+ * Precedence rule: the SHORTCUT WINS on field-level collision.
75
+ *
76
+ * Why: shortcuts encode constraints Wix REQUIRES (e.g.
77
+ * `wix_forms_list_submissions.namespace` — Wix rejects the call without
78
+ * a namespace filter). If the agent's passthrough were to override a
79
+ * pinned namespace, the call would fail with "namespace required".
80
+ *
81
+ * Implementation:
82
+ * - If only one side defines a key, that key is kept verbatim.
83
+ * - If both sides define the SAME top-level key, the shortcut wins
84
+ * and the passthrough's value for that key is dropped (logged
85
+ * conceptually, but we don't have a logger here).
86
+ * - Non-conflicting keys from both sides are combined with `$and`
87
+ * when needed, otherwise spread into a flat object.
88
+ *
89
+ * - Both undefined → undefined (caller decides whether to omit the key)
90
+ * - Only one defined → returned as-is
91
+ */
92
+ export declare function mergeFilter(base: unknown, extra: Record<string, unknown> | undefined): unknown;
93
+ /**
94
+ * Paging shape for flat GET endpoints. Some Wix endpoints support
95
+ * offset paging (`paging.limit`/`paging.offset`), others use cursor
96
+ * paging (`paging.limit`/`paging.cursor`). We expose both — tools pick
97
+ * the right pair when calling {@link buildGetPagingQuery}.
98
+ */
99
+ export declare const WixGetPagingEnvelopeSchema: import("@sinclair/typebox").TObject<{
100
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
101
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
102
+ cursor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
103
+ }>;
104
+ export type WixGetPagingEnvelope = Static<typeof WixGetPagingEnvelopeSchema>;
105
+ /**
106
+ * Map a `paging` envelope to flat `paging.limit` / `paging.offset` /
107
+ * `paging.cursor` query string keys (Wix's documented convention).
108
+ *
109
+ * Returns a partial query object the caller can spread into
110
+ * `client.request({ query: { ...buildGetPagingQuery(p), other: x } })`.
111
+ */
112
+ export declare function buildGetPagingQuery(paging: WixGetPagingEnvelope | undefined): Record<string, string | number | boolean | undefined>;
113
+ /**
114
+ * Drop `undefined`, `null`, and empty-string entries from a query
115
+ * record so they don't end up as `?key=undefined` after serialisation.
116
+ */
117
+ export declare function compactQuery(q: Record<string, string | number | boolean | undefined | null>): Record<string, string | number | boolean | undefined>;