@lowdefy/docs-content 0.0.0-experimental-20260928120643 → 6.1.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 (226) hide show
  1. package/README.md +0 -1
  2. package/content/actions/link.md +0 -17
  3. package/content/actions/login.md +5 -23
  4. package/content/actions/logout.md +5 -5
  5. package/content/actions/pdfmake.md +2 -2
  6. package/content/actions/setdarkmode.md +2 -2
  7. package/content/agents/agent-properties.md +2 -4
  8. package/content/agents/agentchat.md +6 -21
  9. package/content/agents/agentconversations.md +2 -2
  10. package/content/concepts/ai-agent-docs.md +101 -313
  11. package/content/concepts/cli.md +3 -34
  12. package/content/concepts/connections-and-requests.md +0 -402
  13. package/content/concepts/custom-html.md +0 -40
  14. package/content/concepts/custom-styling.md +5 -50
  15. package/content/concepts/events-and-actions.md +2 -64
  16. package/content/concepts/i18n.md +2 -7
  17. package/content/concepts/keyboard-shortcuts.md +2 -2
  18. package/content/concepts/layout-overview.md +1 -1
  19. package/content/concepts/logger.md +0 -81
  20. package/content/concepts/lowdefy-schema.md +1 -4
  21. package/content/concepts/menus.md +7 -7
  22. package/content/concepts/module-authoring.md +2 -2
  23. package/content/connections/anthropic.md +2 -162
  24. package/content/connections/awss3.md +0 -54
  25. package/content/connections/google.md +2 -162
  26. package/content/connections/mongodb.md +3 -121
  27. package/content/connections/openai-connection.md +2 -162
  28. package/content/container-blocks/affix.md +7 -47
  29. package/content/container-blocks/alert.md +24 -76
  30. package/content/container-blocks/badge.md +24 -100
  31. package/content/container-blocks/box.md +9 -9
  32. package/content/container-blocks/card.md +25 -80
  33. package/content/container-blocks/carousel.md +7 -60
  34. package/content/container-blocks/collapse.md +9 -87
  35. package/content/container-blocks/configprovider.md +13 -35
  36. package/content/container-blocks/confirmmodal.md +23 -69
  37. package/content/container-blocks/content.md +98 -62
  38. package/content/container-blocks/descriptions.md +4 -45
  39. package/content/container-blocks/drawer.md +28 -92
  40. package/content/container-blocks/dropdownmenu.md +31 -119
  41. package/content/container-blocks/flex.md +62 -40
  42. package/content/container-blocks/footer.md +11 -15
  43. package/content/container-blocks/googlemapsheatmap.md +1 -1
  44. package/content/container-blocks/googlemapsscript.md +2 -2
  45. package/content/container-blocks/header.md +36 -71
  46. package/content/container-blocks/label.md +7 -34
  47. package/content/container-blocks/layout.md +34 -52
  48. package/content/container-blocks/masonry.md +71 -17
  49. package/content/container-blocks/mobilemenu.md +88 -131
  50. package/content/container-blocks/modal.md +26 -114
  51. package/content/container-blocks/pageheadermenu.md +31 -81
  52. package/content/container-blocks/pagesidebarlayout.md +26 -169
  53. package/content/container-blocks/pagesidermenu.md +42 -95
  54. package/content/container-blocks/popover.md +31 -34
  55. package/content/container-blocks/result.md +21 -32
  56. package/content/container-blocks/sider.md +122 -85
  57. package/content/container-blocks/span.md +7 -7
  58. package/content/container-blocks/spinner.md +3 -3
  59. package/content/container-blocks/splitter.md +68 -150
  60. package/content/container-blocks/tabs.md +12 -64
  61. package/content/container-blocks/tooltip.md +46 -22
  62. package/content/container-blocks/watermark.md +4 -22
  63. package/content/controls/reject.md +2 -4
  64. package/content/controls/throw.md +0 -1
  65. package/content/controls/try.md +2 -3
  66. package/content/deployment/deployment-environments.md +6 -8
  67. package/content/deployment/docker.md +7 -22
  68. package/content/deployment/node-server.md +0 -4
  69. package/content/deployment/vercel.md +6 -13
  70. package/content/display-blocks/aggrid.md +11 -26
  71. package/content/display-blocks/anchor.md +15 -15
  72. package/content/display-blocks/avatar.md +37 -57
  73. package/content/display-blocks/breadcrumb.md +21 -70
  74. package/content/display-blocks/button.md +18 -92
  75. package/content/display-blocks/calendar.md +0 -12
  76. package/content/display-blocks/dangeroushtml.md +1 -1
  77. package/content/display-blocks/difflist.md +1 -1
  78. package/content/display-blocks/difftimeline.md +1 -1
  79. package/content/display-blocks/divider.md +3 -64
  80. package/content/display-blocks/dropdownbutton.md +28 -79
  81. package/content/display-blocks/echart.md +1 -35
  82. package/content/display-blocks/floatbutton.md +42 -129
  83. package/content/display-blocks/html.md +1 -61
  84. package/content/display-blocks/icon.md +67 -250
  85. package/content/display-blocks/menu.md +73 -145
  86. package/content/display-blocks/message.md +124 -38
  87. package/content/display-blocks/notification.md +222 -94
  88. package/content/display-blocks/paragraph.md +9 -59
  89. package/content/display-blocks/progress.md +17 -96
  90. package/content/display-blocks/qrcode.md +4 -19
  91. package/content/display-blocks/s3download.md +1 -1
  92. package/content/display-blocks/search.md +7 -17
  93. package/content/display-blocks/skeletonbutton.md +0 -1
  94. package/content/display-blocks/skeletoninput.md +0 -1
  95. package/content/display-blocks/statistic.md +17 -75
  96. package/content/display-blocks/steps.md +25 -58
  97. package/content/display-blocks/tag.md +17 -102
  98. package/content/display-blocks/title.md +11 -50
  99. package/content/display-blocks/tour.md +23 -33
  100. package/content/input-blocks/autocomplete.md +9 -81
  101. package/content/input-blocks/buttonselector.md +8 -45
  102. package/content/input-blocks/checkboxselector.md +7 -97
  103. package/content/input-blocks/checkboxswitch.md +3 -33
  104. package/content/input-blocks/colorselector.md +14 -63
  105. package/content/input-blocks/daterangeselector.md +45 -165
  106. package/content/input-blocks/dateselector.md +41 -139
  107. package/content/input-blocks/datetimeselector.md +49 -158
  108. package/content/input-blocks/inputgallery.md +3 -3
  109. package/content/input-blocks/monthselector.md +52 -120
  110. package/content/input-blocks/multipleselector.md +39 -150
  111. package/content/input-blocks/numberinput.md +12 -98
  112. package/content/input-blocks/pagination.md +14 -70
  113. package/content/input-blocks/paragraphinput.md +37 -51
  114. package/content/input-blocks/passwordinput.md +6 -60
  115. package/content/input-blocks/phonenumberinput.md +26 -59
  116. package/content/input-blocks/radioselector.md +7 -83
  117. package/content/input-blocks/ratingslider.md +26 -57
  118. package/content/input-blocks/s3uploadbutton.md +24 -24
  119. package/content/input-blocks/s3uploaddragger.md +3 -3
  120. package/content/input-blocks/s3uploadphoto.md +5 -5
  121. package/content/input-blocks/segmentedselector.md +32 -72
  122. package/content/input-blocks/selector.md +21 -109
  123. package/content/input-blocks/switch.md +17 -65
  124. package/content/input-blocks/textarea.md +3 -32
  125. package/content/input-blocks/textinput.md +28 -69
  126. package/content/input-blocks/tiptapmentioninput.md +1 -1
  127. package/content/input-blocks/titleinput.md +12 -39
  128. package/content/input-blocks/treeinput.md +25 -49
  129. package/content/input-blocks/treemultipleselector.md +10 -127
  130. package/content/input-blocks/treeselector.md +9 -97
  131. package/content/input-blocks/upload.md +15 -64
  132. package/content/input-blocks/uploaddragger.md +1 -17
  133. package/content/input-blocks/uploadphoto.md +1 -18
  134. package/content/input-blocks/weekselector.md +55 -120
  135. package/content/list-blocks/controlledlist.md +15 -24
  136. package/content/list-blocks/list.md +11 -11
  137. package/content/list-blocks/masonrylist.md +34 -7
  138. package/content/migration/upgrade-guide.md +0 -1
  139. package/content/operators/_app.md +1 -2
  140. package/content/operators/_error.md +1 -23
  141. package/content/operators/_get.md +6 -6
  142. package/content/operators/_operator.md +3 -17
  143. package/content/operators/_ref.md +0 -258
  144. package/content/operators/_type.md +3 -14
  145. package/content/operators/_user.md +3 -3
  146. package/content/other/introduction.md +1 -1
  147. package/content/plugins/plugins-dev.md +0 -66
  148. package/content/plugins/plugins-introduction.md +1 -27
  149. package/content/testing/e2e-configuration.md +1 -8
  150. package/content/testing/e2e-getting-started.md +1 -1
  151. package/content/testing/e2e-introduction.md +1 -1
  152. package/content/tutorial/tutorial-actions-operators.md +2 -2
  153. package/content/tutorial/tutorial-add-blocks.md +2 -2
  154. package/content/tutorial/tutorial-create-page.md +2 -48
  155. package/content/tutorial/tutorial-display-data-page.md +3 -3
  156. package/content/tutorial/tutorial-requests-sql.md +0 -153
  157. package/content/tutorial/tutorial-start.md +1 -66
  158. package/content/user-authentication/login-and-logout.md +8 -158
  159. package/content/user-authentication/users-introduction.md +0 -8
  160. package/index.json +2 -6065
  161. package/package.json +1 -7
  162. package/scripts/extractAgentDocs.js +4 -36
  163. package/content/actions/emailotpsend.md +0 -58
  164. package/content/actions/emailotpverify.md +0 -77
  165. package/content/actions/getlocalstorage.md +0 -41
  166. package/content/actions/magiclinkverify.md +0 -113
  167. package/content/actions/posthogalias.md +0 -29
  168. package/content/actions/posthogcapture.md +0 -49
  169. package/content/actions/posthogcapturepageleave.md +0 -38
  170. package/content/actions/posthogfeatureflag.md +0 -50
  171. package/content/actions/posthoggroup.md +0 -37
  172. package/content/actions/posthogidentify.md +0 -54
  173. package/content/actions/posthoginit.md +0 -66
  174. package/content/actions/posthogoptin.md +0 -29
  175. package/content/actions/posthogoptout.md +0 -29
  176. package/content/actions/posthogpageview.md +0 -37
  177. package/content/actions/posthogreloadfeatureflags.md +0 -47
  178. package/content/actions/posthogreset.md +0 -28
  179. package/content/actions/posthogsetpersonproperties.md +0 -36
  180. package/content/actions/removelocalstorage.md +0 -26
  181. package/content/actions/setlocalstorage.md +0 -32
  182. package/content/adapter-reference/mongodbauthadapter.md +0 -46
  183. package/content/agents/agents-introduction.md +0 -107
  184. package/content/callback-reference/auth0logoutcallback.md +0 -54
  185. package/content/concepts/blocks.md +0 -150
  186. package/content/concepts/dynamic-page-content.md +0 -304
  187. package/content/concepts/html-attributes.md +0 -285
  188. package/content/concepts/lowdefy-api.md +0 -1110
  189. package/content/concepts/notifications.md +0 -155
  190. package/content/concepts/page-and-app-state.md +0 -244
  191. package/content/concepts/theming.md +0 -582
  192. package/content/connections/aigateway.md +0 -368
  193. package/content/connections/axioshttp.md +0 -181
  194. package/content/controls/while.md +0 -46
  195. package/content/display-blocks/clickablehtml.md +0 -239
  196. package/content/display-blocks/eventlog.md +0 -363
  197. package/content/display-blocks/pollingtimer.md +0 -263
  198. package/content/input-blocks/captcha.md +0 -40
  199. package/content/input-blocks/placesautocomplete.md +0 -319
  200. package/content/input-blocks/tagmultipleselector.md +0 -114
  201. package/content/input-blocks/tagselector.md +0 -114
  202. package/content/migration/auth-upgrade.md +0 -327
  203. package/content/migration/v3-to-v4.md +0 -417
  204. package/content/migration/v6-to-v7.md +0 -222
  205. package/content/operators/_cron.md +0 -292
  206. package/content/other/mongodbadapter.md +0 -3
  207. package/content/plugins/plugins-icon-sets.md +0 -267
  208. package/content/plugins/posthog.md +0 -275
  209. package/content/provider-reference/auth-js-providers.md +0 -107
  210. package/content/provider-reference/openidconnectprovider.md +0 -44
  211. package/content/testing/config-tests.md +0 -278
  212. package/content/tutorial/tutorial-requests-api.md +0 -155
  213. package/content/user-authentication/auth-configuration.md +0 -266
  214. package/content/user-authentication/auth-steps.md +0 -138
  215. package/content/user-authentication/mcp-oauth.md +0 -292
  216. package/content/user-authentication/organizations.md +0 -221
  217. package/content/user-authentication/protected-pages-apis.md +0 -97
  218. package/content/user-authentication/roles.md +0 -49
  219. package/content/user-authentication/two-factor.md +0 -229
  220. package/content/user-authentication/user-object.md +0 -58
  221. package/content/websockets/websocket-publish.md +0 -108
  222. package/content/websockets/websocket-subscriptions.md +0 -100
  223. package/content/websockets/websockets-introduction.md +0 -97
  224. package/hazards.json +0 -44
  225. package/scripts/hashDocSources.js +0 -38
  226. package/scripts/recordSourceHashes.js +0 -88
@@ -25,7 +25,7 @@ Dot notation is supported for reading fields of the error, such as `_error: stat
25
25
  Inside a `:catch`, `_error` is an Error rebuilt from the caught error with only these fields:
26
26
 
27
27
  - `name`: The error class name, such as `RequestError`.
28
- - `message`: The real error message, with the values of known secrets (`_secret` values, `CRON_SECRET` and `BETTER_AUTH_SECRET`) replaced by `[REDACTED]`.
28
+ - `message`: The real error message, with the values of known secrets (`_secret` values, `CRON_SECRET` and `AUTH_SECRET`) replaced by `[REDACTED]`.
29
29
  - `code`: The error's `code`, if it has one.
30
30
  - `statusCode`: The error's HTTP status, if it has one.
31
31
  - `handled`: `true` once the server has logged the error.
@@ -60,28 +60,6 @@ error:
60
60
 
61
61
  `code` and `statusCode` follow one rule across connection libraries. `code` is the error's own `code`, such as `ERR_BAD_REQUEST` from AxiosHttp or `11000` from MongoDB. `statusCode` is the first number among the error's `statusCode`, `status` and `response.status`. A request error takes both from the error the connection threw, so `_error: statusCode` reads the HTTP status of a failed `AxiosHttp` request without reading the cause.
62
62
 
63
- ##### Service errors and rate limits
64
-
65
- A request that fails because of the service it calls, not its config, is a `ServiceError`: a network failure, a timeout, a 5xx response, or a rate limit (HTTP 429, including a provider's throttling error). Every other request failure is a `RequestError`. A routine can tell a rate limit from a fault and try again later:
66
-
67
- ```yaml
68
- - :try:
69
- - id: summarize
70
- type: GenerateText
71
- connectionId: claude
72
- properties:
73
- model: claude-haiku-4-5
74
- prompt:
75
- _payload: text
76
- :catch:
77
- - :if:
78
- _eq: [{ _error: statusCode }, 429]
79
- :then:
80
- - :return:
81
- status: busy
82
- - :throw: Summary failed
83
- ```
84
-
85
63
  #### Arguments
86
64
 
87
65
  ###### string
@@ -37,12 +37,12 @@ _get:
37
37
  key:
38
38
  _state: status
39
39
  from:
40
- new: add-circle
41
- escalated: CircleAlert
42
- investigation_started: Wrench
43
- client_contacted: Volume2
44
- awaiting_confirmation: ThumbsUp
45
- closed: Ban
40
+ new: AiTwoTonePlusCircle
41
+ escalated: AiOutlineExclamationCircle
42
+ investigation_started: AiTwoToneTool
43
+ client_contacted: AiTwoToneSound
44
+ awaiting_confirmation: AiOutlineLike
45
+ closed: AiOutlineStop
46
46
  ```
47
47
  Returns: The icon corresponding to the status in state.
48
48
 
@@ -1,7 +1,7 @@
1
1
  # _operator
2
2
 
3
3
  ```
4
- (arguments: {name: string, params: any, operators?: string[]}): any
4
+ (arguments: {operator: string, params: any): any
5
5
  ```
6
6
 
7
7
  The `_operator` operator evaluates an operator with the given params. This is useful if the operator needs to be chosen dynamically. The `_operator` cannot evaluate itself.
@@ -11,16 +11,15 @@ The `_operator` operator evaluates an operator with the given params. This is us
11
11
  #### Arguments
12
12
 
13
13
  ###### object
14
- - `name: string`: The name of the operator to evaluate, such as `_sum` or `_number.round`. Names written in `name`, including the names an `_if` returns from `then` and `else` and a `_switch` returns from its branches, are loaded with the page.
14
+ - `operator: string`: The name of the operator to evaluate.
15
15
  - `params: any`: The params to give to the operator.
16
- - `operators: string[]`: The operators the call may evaluate. Required when `name` is read at runtime, from state, a request or a payload: the build fails without it, loads exactly these operators with the page (or the server), and `_operator` refuses any other name. A listed operator (`_number`) allows all its methods; a listed method (`_number.round`) allows only that method.
17
16
 
18
17
  #### Examples
19
18
 
20
19
  ###### Get a value from `urlQuery` if specified, else use the value in `state`:
21
20
  ```yaml
22
21
  _operator:
23
- name:
22
+ operator:
24
23
  _if:
25
24
  test:
26
25
  _eq:
@@ -32,16 +31,3 @@ _operator:
32
31
  key: field_to_get
33
32
  ```
34
33
  Returns: Value from `urlQuery` if `location_selector == url_query`, else the value from `state`.
35
-
36
- ###### Apply an aggregation chosen by the user:
37
- ```yaml
38
- _operator:
39
- name:
40
- _state: aggregation # _sum or _product
41
- operators:
42
- - _sum
43
- - _product
44
- params:
45
- _state: values
46
- ```
47
- Returns: The sum or product of `values`. Any other name in `aggregation` is refused.
@@ -78,261 +78,3 @@ The file path to the referenced file, from the root of the project directory.
78
78
  > Within module content, the `module` field can reference a declared dependency name (from the module's `dependencies` in `module.lowdefy.yaml`). The build resolves abstract names to concrete entry IDs via the dependency wiring. From app-level config, `module` is always a concrete entry ID.
79
79
 
80
80
  #### Examples
81
-
82
- ###### Reference pages:
83
- ```yaml
84
- # lowdefy.yaml
85
- lowdefy: 6.0.0
86
- pages:
87
- - _ref: pages/page1.yaml
88
- - _ref: pages/page2.yaml
89
- ```
90
- ```yaml
91
- # pages/page1.yaml
92
- id: page1
93
- type: PageHeaderMenu
94
- blocks:
95
- # ...
96
- ```
97
- ```yaml
98
- # pages/page2.yaml
99
- id: page2
100
- type: PageHeaderMenu
101
- blocks:
102
- # ...
103
- ```
104
- Returns:
105
- ```
106
- lowdefy: 6.0.0
107
- pages:
108
- - id: page1
109
- type: PageHeaderMenu
110
- blocks:
111
- # ...
112
- - id: page2
113
- type: PageHeaderMenu
114
- blocks:
115
- # ...
116
- ```
117
-
118
- ###### Using a standardized input label template:
119
- ```yaml
120
- blocks:
121
- - id: name
122
- type: TextInput
123
- properties:
124
- label:
125
- _ref:
126
- path: label.yaml
127
- vars:
128
- title: Name
129
- description: Your name and surname.
130
- - id: age
131
- type: NumberInput
132
- properties:
133
- label:
134
- _ref:
135
- path: label.yaml
136
- vars:
137
- title: Age
138
- description: Your age.
139
- ```
140
- ```yaml
141
- # label.yaml
142
- title:
143
- _var: title
144
- extra:
145
- _var: description
146
- span: 8
147
- colon: false
148
- extraStyle:
149
- color: '#546358'
150
- ```
151
- Returns:
152
- ```yaml
153
- blocks:
154
- - id: name
155
- type: TextInput
156
- properties:
157
- label:
158
- title: Name
159
- extra: Your name and surname.
160
- span: 8
161
- colon: false
162
- extraStyle:
163
- color: '#546358'
164
- - id: age
165
- type: NumberInput
166
- properties:
167
- label:
168
- title: Age
169
- extra: Your age.
170
- span: 8
171
- colon: false
172
- extraStyle:
173
- color: '#546358'
174
- ```
175
-
176
- ###### Use key:
177
- ```yaml
178
- # lowdefy.yaml
179
- lowdefy: 6.0.0
180
- version:
181
- _ref:
182
- path: package.json
183
- field: version
184
- ```
185
- ```json
186
- // package.json
187
- {
188
- "version": "1.0.0"
189
- }
190
- ```
191
- Returns:
192
- ```
193
- lowdefy: 6.0.0
194
- version: 1.0.0
195
- ```
196
-
197
- ###### Local or shared resolver:
198
-
199
- This resolver function will first look for the configuration file in the current working directory, but if the file is not found it will be read from an adjacent "shared" directory. This pattern can be used to build apps that mostly use a shared configuration, with a few components that are customised per app.
200
-
201
- ```js
202
- // resolvers/useLocalOrSharedConfig.js
203
- const fs = require('fs');
204
- const path = require('path');
205
- const { promisify } = require('util');
206
-
207
- const readFilePromise = promisify(fs.readFile);
208
-
209
- async function useLocalOrSharedConfig(refPath, vars, context) {
210
- let fileContent
211
- try {
212
- fileContent = await readFilePromise(path.resolve(refPath), 'utf8');
213
- return fileContent;
214
- } catch (error) {
215
- if (error.code === 'ENOENT') {
216
- fileContent = readFilePromise(path.resolve('../shared', refPath), 'utf8');
217
- return fileContent;
218
- }
219
- throw error;
220
- }
221
-
222
-
223
- }
224
-
225
- module.exports = useLocalOrSharedConfig;
226
- ```
227
-
228
- ```yaml
229
- // lowdefy.yaml
230
- lowdefy: 6.0.0
231
-
232
- cli:
233
- refResolver: resolvers/useLocalOrSharedConfig.js
234
-
235
- pages:
236
- - _ref: pages/local-page.yaml
237
- - _ref: pages/shared-page.yaml
238
- ```
239
-
240
- ###### This transformer adds a standard footer to each page:
241
-
242
- ```js
243
- // transformers/addFooter.js
244
-
245
- function addFooter(page, vars) {
246
- const footer = {
247
- // ...
248
- };
249
- page.areas.footer = footer;
250
- return page;
251
- }
252
- module.exports = addFooter;
253
- ```
254
- ```yaml
255
- // lowdefy.yaml
256
- lowdefy: 6.0.0
257
-
258
- pages:
259
- - _ref:
260
- path: pages/page1.yaml
261
- transformer: transformers/addFooter.js
262
- ```
263
- ###### Reference a module component:
264
- ```yaml
265
- blocks:
266
- - _ref:
267
- module: notifications
268
- component: notification-badge
269
- vars:
270
- position: top-right
271
- ```
272
-
273
- ###### Data export with key extraction:
274
- ```yaml
275
- icon:
276
- _ref:
277
- module: events
278
- component: event_types
279
- key: login.icon
280
- ```
281
-
282
- ###### Cross-module component ref within a module:
283
- ```yaml
284
- # contacts module embedding companies' selector
285
- blocks:
286
- - _ref:
287
- module: companies # abstract dependency name
288
- component: company-selector
289
- vars:
290
- field_id: company_id
291
- ```
292
-
293
- ###### Module menu inside a MenuGroup:
294
- ```yaml
295
- menus:
296
- - id: main
297
- links:
298
- - id: home
299
- type: MenuLink
300
- pageId: home
301
- - id: team-admin
302
- type: MenuGroup
303
- properties:
304
- title: Team Admin
305
- links:
306
- _ref:
307
- module: team-users
308
- menu: default
309
- ```
310
-
311
- ###### Using ES Modules with `.mjs` file extension:
312
-
313
- ```js
314
- // resolvers/useLocalOrSharedConfig.mjs
315
- import fs from 'fs';
316
- import path from 'path';
317
- import { promisify } from 'util';
318
-
319
- const readFilePromise = promisify(fs.readFile);
320
-
321
- async function useLocalOrSharedConfig(refPath, vars, context) {
322
- let fileContent
323
- try {
324
- fileContent = await readFilePromise(path.resolve(refPath), 'utf8');
325
- return fileContent;
326
- } catch (error) {
327
- if (error.code === 'ENOENT') {
328
- fileContent = readFilePromise(path.resolve('../shared', refPath), 'utf8');
329
- return fileContent;
330
- }
331
- throw error;
332
- }
333
-
334
-
335
- }
336
-
337
- export default useLocalOrSharedConfig;
338
- ```
@@ -29,7 +29,6 @@ The regex operator has shorthand argument definitions that can be used on web cl
29
29
  - `null`
30
30
  - `undefined`
31
31
  - `none` (`null` or `undefined`)
32
- - `empty` (`null`, `undefined`, `''`, or `[]` - note that `0`, `false` and `{}` are not empty)
33
32
  - `primitive` (`undefined`, `null`, `string`, `number`, `boolean`, or `date`)
34
33
  - `on: any`: The value to test. One of `on` or `key` must be specified unless the operator is used in an input block.
35
34
  - `key: string`: The key of a value in `state` to test. One of `on` or `key` must be specified unless the operator is used in an input block.
@@ -61,23 +60,13 @@ Returns: `true` if a number.
61
60
  id: input
62
61
  type: TextInput
63
62
  validate:
64
- - message: This field is required.
63
+ - message: This field id required.
65
64
  status: error
66
65
  pass:
67
66
  _not:
68
- _type: empty
67
+ _type: none
69
68
  ```
70
- Returns: `true` if the input has a value. This is the test the `required` block field applies.
71
-
72
- ###### Check if a value is empty:
73
- ```yaml
74
- _type:
75
- type: empty
76
- on:
77
- _state: selected_tags
78
- ```
79
- Returns: `true` if `selected_tags` is `null`, `undefined`, `''` or `[]`, and `false` for any
80
- other value, including `0`, `false` and `{}`.
69
+ Returns: `true` if the input is none.
81
70
 
82
71
  ###### Test if an id in the `urlQuery` is undefined or null:
83
72
  ```yaml
@@ -10,7 +10,7 @@
10
10
  }): any
11
11
  ```
12
12
 
13
- The `_user` operator gets a value from the [`user`](/user-object) object — the caller Lowdefy resolves for the signed-in user in their active organization. It has a [fixed shape](/user-object); see that page for the available fields.
13
+ The `_user` operator gets a value from the [`user`](/user-object) object. The `user` object contains the data in the user idToken if OpenID Connect authentication is configured and a user is logged in.
14
14
 
15
15
  #### Arguments
16
16
 
@@ -50,7 +50,7 @@ Returns: The entire `user` object.
50
50
  ###### Dot notation:
51
51
  Assuming user:
52
52
  ```yaml
53
- id: abc123
53
+ sub: abc123
54
54
  name: User Name
55
55
  my_object:
56
56
  subfield: 'Value'
@@ -76,7 +76,7 @@ Returns: The value of `might_not_exist`, or `"Default value"`.
76
76
  ###### Block list indices:
77
77
  Assuming `user`:
78
78
  ```yaml
79
- id: abc123
79
+ sub: abc123
80
80
  name: User Name
81
81
  my_array:
82
82
  - value: 0
@@ -14,7 +14,7 @@ pnpx lowdefy@5 init && pnpx lowdefy@5 dev
14
14
 
15
15
  This will create a file called `lowdefy.yaml` in the current working directory that contains the configuration for a Lowdefy app (as well as a `.gitignore`) and launch a local development server at http://localhost:3000. Make changes in the `lowdefy.yaml` file to see them reflect in the app.
16
16
 
17
- > You need Node v24 or newer and pnpm installed to run Lowdefy. For more details see [the tutorial](/tutorial-start).
17
+ > You need Node v22 or newer and pnpm installed to run Lowdefy. For more details see [the tutorial](/tutorial-start).
18
18
 
19
19
  ## Why create web apps using a YAML schema?
20
20
 
@@ -31,7 +31,6 @@ Lowdefy uses the [`exports`](https://nodejs.org/api/packages.html#exports) packa
31
31
  "./auth/providers": "./src/auth/providers.js",
32
32
  "./blocks": "./src/blocks.js",
33
33
  "./connections": "./src/connections.js",
34
- "./iconSets": "./src/iconSets.js",
35
34
  "./metas": "./src/metas.js",
36
35
  "./operators/client": "./src/operators/client.js",
37
36
  "./operators/server": "./src/operators/server.js",
@@ -68,7 +67,6 @@ export default {
68
67
  },
69
68
  blocks: ['Block'],
70
69
  connections: ['Connection'],
71
- iconSets: ['my-icons'],
72
70
  requests: ['Request'],
73
71
  operators: {
74
72
  build: ['_build_operator', '_shared_operator'],
@@ -78,8 +76,6 @@ export default {
78
76
  };
79
77
  ```
80
78
 
81
- `iconSets` declares icon sets, which the `./iconSets` entry point exports as data. See [Icon Sets](/plugins-icon-sets).
82
-
83
79
  The type names do not need to be hard coded, and can be generated by importing the plugin types.
84
80
 
85
81
  ###### Example `types.js` for connections
@@ -115,20 +111,6 @@ export default extractBlockTypes(metas);
115
111
 
116
112
  The `extractBlockTypes` function returns `{ blocks, icons, blockMetas }` which the build pipeline uses to resolve plugin types without loading React components or heavy dependencies.
117
113
 
118
- A block that runs actions itself, through events it registers with `methods.registerEvent`, lists those action types in `meta.actions` and the operators their params use in `meta.operators`. Each page loads only the plugin code it uses, so the build adds these types to every page that uses the block:
119
-
120
- ```js
121
- // src/blocks/MyUpload/meta.js
122
- export default {
123
- category: 'input',
124
- icons: [],
125
- // Registers { id: 'policy', type: 'Request', params: { _event: 'requestId' } }
126
- actions: ['Request'],
127
- operators: ['_event'],
128
- // ...events, properties
129
- };
130
- ```
131
-
132
114
  See the [default Lowdefy block packages](https://github.com/lowdefy/lowdefy/tree/main/packages/plugins/blocks) for full examples.
133
115
 
134
116
  ### Named export files
@@ -151,54 +133,6 @@ Most types are written as standard Javascript functions, and blocks are written
151
133
 
152
134
  Lowdefy uses object [destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to provide parameters to the type functions. These parameters include the parameters or properties defined by the user in the Lowdefy configuration. Any operators used in the configuration will be evaluated before it is passed to the type function. Other relevant metadata and helper functions are also passed to the plugin function.
153
135
 
154
- ### Lazy loading heavy blocks
155
-
156
- A page loads the code of every block type it uses before it renders. A block that pulls in a large library, such as a chat, a chart engine or a rich text editor, can make that code much bigger, even when the block sits in a closed drawer, an unopened tab or a modal. `createLazyBlock` from `@lowdefy/block-utils` loads such a block's implementation only when the block first mounts.
157
-
158
- Make a block lazy when it adds more than about 100 kB gzip to the page, **and** it is commonly off-screen at first paint or the page shows useful content without it. Otherwise keep it eager: a lazy block that is visible at first paint appears a moment later.
159
-
160
- Move the block's component into a file named `*.lazy.js`, and export a wrapper in its place:
161
-
162
- ```js
163
- // src/blocks/MyChart/MyChart.js - exported from blocks.js as before
164
- import { createLazyBlock } from '@lowdefy/block-utils';
165
- import meta from './meta.js';
166
- import MyChartFallback from './MyChartFallback.js';
167
-
168
- export default createLazyBlock({
169
- load: () => import('./MyChart.lazy.js'),
170
- meta,
171
- Fallback: MyChartFallback, // optional
172
- });
173
- ```
174
-
175
- - `load` returns `import()` of the implementation, whose default export is the block component. Do not import the `*.lazy.js` file statically anywhere else, or it is bundled with the page again.
176
- - `meta` is the block's `meta.js` object. The wrapper copies it to `.meta`.
177
- - `Fallback` is optional. It renders while the implementation loads and receives the same props as the block. Use it to keep the block's size, or to show the part users see first, such as a launcher button. Without it the block renders nothing until it has loaded.
178
-
179
- The wrapper also has a `preload()` function, which starts the load and returns its promise. A `Fallback` can call it on hover.
180
-
181
- The `.lazy.js` name matters. In production, the Lowdefy server prefetches the `*.lazy.js` chunks of the blocks on a page, so the code is often in the browser cache by the time the block mounts. Other dynamic imports are never prefetched.
182
-
183
- ###### Block methods
184
-
185
- Declare every method the block registers with `methods.registerMethod` in `meta.methods`:
186
-
187
- ```js
188
- // src/blocks/MyChart/meta.js
189
- export default {
190
- category: 'display',
191
- methods: {
192
- reset: 'Reset the zoom.',
193
- download: 'Download the chart as an image.',
194
- },
195
- };
196
- ```
197
-
198
- The wrapper registers these methods as soon as the block mounts, so `CallMethod` works before the implementation has loaded. Calls made before then wait in order and run once the implementation has registered its methods. After that, calls go straight to the block, as for any other block. A waiting call fails if the block never registers that method, if the load fails, or if the block is removed first. A method that is not declared in `meta.methods` cannot be called before the block loads, and the dev server logs a warning when the block registers it.
199
-
200
- Do not spread the `methods` prop (`{ ...methods }`) in a lazy block's implementation; pass it on as it is.
201
-
202
136
  ### Localizing plugin strings
203
137
 
204
138
  Plugins can ship locale-keyed default messages so consumers see translated strings out-of-the-box, and translate strings at runtime via `methods.translate(key, values)` in block / action code. See [i18n](/i18n) for the full plugin-author contract — `./messages` export shape, `package.json` `exports` registration, namespacing convention, and merge precedence.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Lowdefy plugins provides an interface to extend the platform functionality with custom javascript code. Plugins are installed into the Lowdefy app during the Lowdefy build process, and as a result are included as part of the Vite client build output. This enables plugin developers to use any npm packages when building Lowdefy plugins.
4
4
 
5
- Lowdefy plugins can be used to create custom blocks, connections, requests, action, operators and auth providers, adapters, callbacks and events. [Icon-set plugins](/plugins-icon-sets) add icons as data. These plugins are written as standard [npm modules](https://docs.npmjs.com/about-packages-and-modules#about-modules), so community plugins can be published to npm, and the workspace and git protocols can be used for project specific or private plugins. Since plugins are npm packages most Javascript features and third-party npm packages can be used in plugins.
5
+ Lowdefy plugins can be used to create custom blocks, connections, requests, action, operators and auth providers, adapters, callbacks and events. These plugins are written as standard [npm modules](https://docs.npmjs.com/about-packages-and-modules#about-modules), so community plugins can be published to npm, and the workspace and git protocols can be used for project specific or private plugins. Since plugins are npm packages most Javascript features and third-party npm packages can be used in plugins.
6
6
 
7
7
  ## Using a plugin
8
8
 
@@ -27,29 +27,3 @@ plugins:
27
27
  version: 1.0.0
28
28
  typePrefix: Other
29
29
  ```
30
-
31
- ## Plugin meta
32
-
33
- Every plugin type can describe itself to the build and to AI coding agents through a `meta` object. For blocks it is the `meta.js` next to the block (`category`, `valueType`, `initValue`, `cssKeys`, `events`, `properties`, ...), for requests it is the `meta` property on the request function (`checkRead`, `checkWrite`), and for operators a package may export a `./metas` module with one object per operator, mirroring `./schemas`.
34
-
35
- All three accept `meta.hazards`: a list of behaviours of the type that its schema cannot express, which the dev server's docs and MCP endpoint return to agents alongside the schema (see [AI agent docs](/ai-agent-docs)). Each hazard is:
36
-
37
- ```yaml
38
- hazards:
39
- - id: html-style-stripped # kebab-case, unique within the type
40
- message: Content is sanitised with DOMPurify, so <style>, <script> and inline event handlers are removed. Use DangerousHtml for a trusted <style> block.
41
- see: display-blocks/html # a docs slug, or null
42
- ```
43
-
44
- The `message` is one or two plain sentences saying what happens and what to do instead. Only add a hazard for a behaviour that is verified in the plugin's code — an agent will rely on it.
45
-
46
- A block marks each property that holds a URL with `urlKind` in its `properties` schema: `url` for a link the engine opens (a colon-less value is read as `https://`), `href` for a link the browser opens, `src` for a resource the block loads, and `srcSet` for a list of sources. A [dynamic blocks policy](/dynamic-page-content#dynamic-blocks-policies) checks marked properties against its pages and origins whatever they are called. Every other property is judged by its name (`url`, `href`, `src`, `image`, ...), so a property whose name looks like a URL key but holds something else, such as a field name, is marked `urlKind: false`.
47
-
48
- ```js
49
- properties: {
50
- type: 'object',
51
- properties: {
52
- indexUrl: { type: 'string', urlKind: 'src', description: 'URL of the search index.' },
53
- },
54
- },
55
- ```
@@ -14,7 +14,7 @@ export default createConfig();
14
14
 
15
15
  This will:
16
16
  - Look for your Lowdefy app in the current directory
17
- - Build and start the app's e2e server on port 3000, or reuse it if it is already running there
17
+ - Build and start on port 3000
18
18
  - Run tests from the `e2e/` directory matching `**/*.spec.js`
19
19
  - Take screenshots only on failure
20
20
 
@@ -42,10 +42,6 @@ export default createConfig({
42
42
  });
43
43
  ```
44
44
 
45
- ## Reusing a running server
46
-
47
- Playwright reuses a server that is already listening on the configured port, so starting it once with `pnpm e2e:server` in another terminal skips the build on later runs. Before any test runs, the config asks that server which build it serves. Any other server on the port, such as `lowdefy dev`, a production build, or the e2e server of another app or git worktree, stops the run with an error that names the port, instead of the tests running against it. Stop that server, or give each app or worktree its own `port`.
48
-
49
45
  ## Multi-app configuration
50
46
 
51
47
  If your project has multiple Lowdefy apps (for example, in a monorepo), use `createMultiAppConfig`:
@@ -85,8 +81,6 @@ export default {
85
81
  };
86
82
  ```
87
83
 
88
- Keep `globalSetup` from the base configuration (spreading `base` does), since it runs the server check. To add your own global setup, pass both: `globalSetup: [base.globalSetup, './global-setup.js']`.
89
-
90
84
  ## Environment variables
91
85
 
92
86
  The configuration sets these environment variables automatically:
@@ -95,7 +89,6 @@ The configuration sets these environment variables automatically:
95
89
  |----------|---------|
96
90
  | `LOWDEFY_BUILD_DIR` | Absolute path to build artifacts — used by test fixtures to generate the block manifest |
97
91
  | `LOWDEFY_E2E_MOCKS_FILE` | Absolute path to `mocks.yaml` — used by test fixtures to load static mocks |
98
- | `LOWDEFY_E2E_SERVERS` | Port and build directory of each app server — used by the global setup to check a reused server |
99
92
 
100
93
  ## Assertion timeouts
101
94
 
@@ -40,7 +40,7 @@ Run tests with the Playwright UI (useful for debugging):
40
40
  pnpm e2e:ui
41
41
  ```
42
42
 
43
- > The first run will take longer because Playwright needs to build and start your Lowdefy app. Later runs reuse the app's e2e server if it is still running (for example after `pnpm e2e:server`). If another server holds the port, such as `lowdefy dev`, the run stops with an error that names the port.
43
+ > The first run will take longer because Playwright needs to build and start your Lowdefy app. Subsequent runs reuse the server if it is still running.
44
44
 
45
45
  ## Your first test
46
46
 
@@ -24,7 +24,7 @@ The e2e server build exposes internal state on `window.lowdefy`, so your tests c
24
24
 
25
25
  ## Prerequisites
26
26
 
27
- - **Node.js 24+**
27
+ - **Node.js 22+**
28
28
  - A working Lowdefy app (your app must build successfully)
29
29
  - **Playwright** (installed automatically during setup)
30
30
 
@@ -29,7 +29,7 @@ blocks:
29
29
  properties:
30
30
  title: Reset
31
31
  block: true
32
- icon: Eraser
32
+ icon: AiOutlineClear
33
33
  ################ -------- Copy from here -------- ################
34
34
  events:
35
35
  onClick:
@@ -92,7 +92,7 @@ blocks:
92
92
  block: true
93
93
  color: primary
94
94
  variant: solid
95
- icon: save
95
+ icon: AiOutlineSave
96
96
  ################ -------- Copy from here -------- ################
97
97
  events:
98
98
  onClick:
@@ -50,7 +50,7 @@ blocks:
50
50
  title: Reset
51
51
  block: true # Make the button fill all the space available to it
52
52
  type: default # Make the button a plain button
53
- icon: Eraser
53
+ icon: AiOutlineClear
54
54
  - id: submit_button
55
55
  type: Button
56
56
  layout:
@@ -59,7 +59,7 @@ blocks:
59
59
  title: Submit
60
60
  block: true
61
61
  type: primary # Make the button a primary button with color
62
- icon: save
62
+ icon: AiOutlineSave
63
63
  ################ -------- Copy to here ---------- ################
64
64
  ```
65
65