@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.
- package/README.md +0 -1
- package/content/actions/link.md +0 -17
- package/content/actions/login.md +5 -23
- package/content/actions/logout.md +5 -5
- package/content/actions/pdfmake.md +2 -2
- package/content/actions/setdarkmode.md +2 -2
- package/content/agents/agent-properties.md +2 -4
- package/content/agents/agentchat.md +6 -21
- package/content/agents/agentconversations.md +2 -2
- package/content/concepts/ai-agent-docs.md +101 -313
- package/content/concepts/cli.md +3 -34
- package/content/concepts/connections-and-requests.md +0 -402
- package/content/concepts/custom-html.md +0 -40
- package/content/concepts/custom-styling.md +5 -50
- package/content/concepts/events-and-actions.md +2 -64
- package/content/concepts/i18n.md +2 -7
- package/content/concepts/keyboard-shortcuts.md +2 -2
- package/content/concepts/layout-overview.md +1 -1
- package/content/concepts/logger.md +0 -81
- package/content/concepts/lowdefy-schema.md +1 -4
- package/content/concepts/menus.md +7 -7
- package/content/concepts/module-authoring.md +2 -2
- package/content/connections/anthropic.md +2 -162
- package/content/connections/awss3.md +0 -54
- package/content/connections/google.md +2 -162
- package/content/connections/mongodb.md +3 -121
- package/content/connections/openai-connection.md +2 -162
- package/content/container-blocks/affix.md +7 -47
- package/content/container-blocks/alert.md +24 -76
- package/content/container-blocks/badge.md +24 -100
- package/content/container-blocks/box.md +9 -9
- package/content/container-blocks/card.md +25 -80
- package/content/container-blocks/carousel.md +7 -60
- package/content/container-blocks/collapse.md +9 -87
- package/content/container-blocks/configprovider.md +13 -35
- package/content/container-blocks/confirmmodal.md +23 -69
- package/content/container-blocks/content.md +98 -62
- package/content/container-blocks/descriptions.md +4 -45
- package/content/container-blocks/drawer.md +28 -92
- package/content/container-blocks/dropdownmenu.md +31 -119
- package/content/container-blocks/flex.md +62 -40
- package/content/container-blocks/footer.md +11 -15
- package/content/container-blocks/googlemapsheatmap.md +1 -1
- package/content/container-blocks/googlemapsscript.md +2 -2
- package/content/container-blocks/header.md +36 -71
- package/content/container-blocks/label.md +7 -34
- package/content/container-blocks/layout.md +34 -52
- package/content/container-blocks/masonry.md +71 -17
- package/content/container-blocks/mobilemenu.md +88 -131
- package/content/container-blocks/modal.md +26 -114
- package/content/container-blocks/pageheadermenu.md +31 -81
- package/content/container-blocks/pagesidebarlayout.md +26 -169
- package/content/container-blocks/pagesidermenu.md +42 -95
- package/content/container-blocks/popover.md +31 -34
- package/content/container-blocks/result.md +21 -32
- package/content/container-blocks/sider.md +122 -85
- package/content/container-blocks/span.md +7 -7
- package/content/container-blocks/spinner.md +3 -3
- package/content/container-blocks/splitter.md +68 -150
- package/content/container-blocks/tabs.md +12 -64
- package/content/container-blocks/tooltip.md +46 -22
- package/content/container-blocks/watermark.md +4 -22
- package/content/controls/reject.md +2 -4
- package/content/controls/throw.md +0 -1
- package/content/controls/try.md +2 -3
- package/content/deployment/deployment-environments.md +6 -8
- package/content/deployment/docker.md +7 -22
- package/content/deployment/node-server.md +0 -4
- package/content/deployment/vercel.md +6 -13
- package/content/display-blocks/aggrid.md +11 -26
- package/content/display-blocks/anchor.md +15 -15
- package/content/display-blocks/avatar.md +37 -57
- package/content/display-blocks/breadcrumb.md +21 -70
- package/content/display-blocks/button.md +18 -92
- package/content/display-blocks/calendar.md +0 -12
- package/content/display-blocks/dangeroushtml.md +1 -1
- package/content/display-blocks/difflist.md +1 -1
- package/content/display-blocks/difftimeline.md +1 -1
- package/content/display-blocks/divider.md +3 -64
- package/content/display-blocks/dropdownbutton.md +28 -79
- package/content/display-blocks/echart.md +1 -35
- package/content/display-blocks/floatbutton.md +42 -129
- package/content/display-blocks/html.md +1 -61
- package/content/display-blocks/icon.md +67 -250
- package/content/display-blocks/menu.md +73 -145
- package/content/display-blocks/message.md +124 -38
- package/content/display-blocks/notification.md +222 -94
- package/content/display-blocks/paragraph.md +9 -59
- package/content/display-blocks/progress.md +17 -96
- package/content/display-blocks/qrcode.md +4 -19
- package/content/display-blocks/s3download.md +1 -1
- package/content/display-blocks/search.md +7 -17
- package/content/display-blocks/skeletonbutton.md +0 -1
- package/content/display-blocks/skeletoninput.md +0 -1
- package/content/display-blocks/statistic.md +17 -75
- package/content/display-blocks/steps.md +25 -58
- package/content/display-blocks/tag.md +17 -102
- package/content/display-blocks/title.md +11 -50
- package/content/display-blocks/tour.md +23 -33
- package/content/input-blocks/autocomplete.md +9 -81
- package/content/input-blocks/buttonselector.md +8 -45
- package/content/input-blocks/checkboxselector.md +7 -97
- package/content/input-blocks/checkboxswitch.md +3 -33
- package/content/input-blocks/colorselector.md +14 -63
- package/content/input-blocks/daterangeselector.md +45 -165
- package/content/input-blocks/dateselector.md +41 -139
- package/content/input-blocks/datetimeselector.md +49 -158
- package/content/input-blocks/inputgallery.md +3 -3
- package/content/input-blocks/monthselector.md +52 -120
- package/content/input-blocks/multipleselector.md +39 -150
- package/content/input-blocks/numberinput.md +12 -98
- package/content/input-blocks/pagination.md +14 -70
- package/content/input-blocks/paragraphinput.md +37 -51
- package/content/input-blocks/passwordinput.md +6 -60
- package/content/input-blocks/phonenumberinput.md +26 -59
- package/content/input-blocks/radioselector.md +7 -83
- package/content/input-blocks/ratingslider.md +26 -57
- package/content/input-blocks/s3uploadbutton.md +24 -24
- package/content/input-blocks/s3uploaddragger.md +3 -3
- package/content/input-blocks/s3uploadphoto.md +5 -5
- package/content/input-blocks/segmentedselector.md +32 -72
- package/content/input-blocks/selector.md +21 -109
- package/content/input-blocks/switch.md +17 -65
- package/content/input-blocks/textarea.md +3 -32
- package/content/input-blocks/textinput.md +28 -69
- package/content/input-blocks/tiptapmentioninput.md +1 -1
- package/content/input-blocks/titleinput.md +12 -39
- package/content/input-blocks/treeinput.md +25 -49
- package/content/input-blocks/treemultipleselector.md +10 -127
- package/content/input-blocks/treeselector.md +9 -97
- package/content/input-blocks/upload.md +15 -64
- package/content/input-blocks/uploaddragger.md +1 -17
- package/content/input-blocks/uploadphoto.md +1 -18
- package/content/input-blocks/weekselector.md +55 -120
- package/content/list-blocks/controlledlist.md +15 -24
- package/content/list-blocks/list.md +11 -11
- package/content/list-blocks/masonrylist.md +34 -7
- package/content/migration/upgrade-guide.md +0 -1
- package/content/operators/_app.md +1 -2
- package/content/operators/_error.md +1 -23
- package/content/operators/_get.md +6 -6
- package/content/operators/_operator.md +3 -17
- package/content/operators/_ref.md +0 -258
- package/content/operators/_type.md +3 -14
- package/content/operators/_user.md +3 -3
- package/content/other/introduction.md +1 -1
- package/content/plugins/plugins-dev.md +0 -66
- package/content/plugins/plugins-introduction.md +1 -27
- package/content/testing/e2e-configuration.md +1 -8
- package/content/testing/e2e-getting-started.md +1 -1
- package/content/testing/e2e-introduction.md +1 -1
- package/content/tutorial/tutorial-actions-operators.md +2 -2
- package/content/tutorial/tutorial-add-blocks.md +2 -2
- package/content/tutorial/tutorial-create-page.md +2 -48
- package/content/tutorial/tutorial-display-data-page.md +3 -3
- package/content/tutorial/tutorial-requests-sql.md +0 -153
- package/content/tutorial/tutorial-start.md +1 -66
- package/content/user-authentication/login-and-logout.md +8 -158
- package/content/user-authentication/users-introduction.md +0 -8
- package/index.json +2 -6065
- package/package.json +1 -7
- package/scripts/extractAgentDocs.js +4 -36
- package/content/actions/emailotpsend.md +0 -58
- package/content/actions/emailotpverify.md +0 -77
- package/content/actions/getlocalstorage.md +0 -41
- package/content/actions/magiclinkverify.md +0 -113
- package/content/actions/posthogalias.md +0 -29
- package/content/actions/posthogcapture.md +0 -49
- package/content/actions/posthogcapturepageleave.md +0 -38
- package/content/actions/posthogfeatureflag.md +0 -50
- package/content/actions/posthoggroup.md +0 -37
- package/content/actions/posthogidentify.md +0 -54
- package/content/actions/posthoginit.md +0 -66
- package/content/actions/posthogoptin.md +0 -29
- package/content/actions/posthogoptout.md +0 -29
- package/content/actions/posthogpageview.md +0 -37
- package/content/actions/posthogreloadfeatureflags.md +0 -47
- package/content/actions/posthogreset.md +0 -28
- package/content/actions/posthogsetpersonproperties.md +0 -36
- package/content/actions/removelocalstorage.md +0 -26
- package/content/actions/setlocalstorage.md +0 -32
- package/content/adapter-reference/mongodbauthadapter.md +0 -46
- package/content/agents/agents-introduction.md +0 -107
- package/content/callback-reference/auth0logoutcallback.md +0 -54
- package/content/concepts/blocks.md +0 -150
- package/content/concepts/dynamic-page-content.md +0 -304
- package/content/concepts/html-attributes.md +0 -285
- package/content/concepts/lowdefy-api.md +0 -1110
- package/content/concepts/notifications.md +0 -155
- package/content/concepts/page-and-app-state.md +0 -244
- package/content/concepts/theming.md +0 -582
- package/content/connections/aigateway.md +0 -368
- package/content/connections/axioshttp.md +0 -181
- package/content/controls/while.md +0 -46
- package/content/display-blocks/clickablehtml.md +0 -239
- package/content/display-blocks/eventlog.md +0 -363
- package/content/display-blocks/pollingtimer.md +0 -263
- package/content/input-blocks/captcha.md +0 -40
- package/content/input-blocks/placesautocomplete.md +0 -319
- package/content/input-blocks/tagmultipleselector.md +0 -114
- package/content/input-blocks/tagselector.md +0 -114
- package/content/migration/auth-upgrade.md +0 -327
- package/content/migration/v3-to-v4.md +0 -417
- package/content/migration/v6-to-v7.md +0 -222
- package/content/operators/_cron.md +0 -292
- package/content/other/mongodbadapter.md +0 -3
- package/content/plugins/plugins-icon-sets.md +0 -267
- package/content/plugins/posthog.md +0 -275
- package/content/provider-reference/auth-js-providers.md +0 -107
- package/content/provider-reference/openidconnectprovider.md +0 -44
- package/content/testing/config-tests.md +0 -278
- package/content/tutorial/tutorial-requests-api.md +0 -155
- package/content/user-authentication/auth-configuration.md +0 -266
- package/content/user-authentication/auth-steps.md +0 -138
- package/content/user-authentication/mcp-oauth.md +0 -292
- package/content/user-authentication/organizations.md +0 -221
- package/content/user-authentication/protected-pages-apis.md +0 -97
- package/content/user-authentication/roles.md +0 -49
- package/content/user-authentication/two-factor.md +0 -229
- package/content/user-authentication/user-object.md +0 -58
- package/content/websockets/websocket-publish.md +0 -108
- package/content/websockets/websocket-subscriptions.md +0 -100
- package/content/websockets/websockets-introduction.md +0 -97
- package/hazards.json +0 -44
- package/scripts/hashDocSources.js +0 -38
- package/scripts/recordSourceHashes.js +0 -88
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/docs-content",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Lowdefy documentation extracted as markdown for AI coding agents.",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -20,20 +20,14 @@
|
|
|
20
20
|
"type": "module",
|
|
21
21
|
"exports": {
|
|
22
22
|
"./index.json": "./index.json",
|
|
23
|
-
"./hazards.json": "./hazards.json",
|
|
24
23
|
"./scripts/extractAgentDocs.js": "./scripts/extractAgentDocs.js",
|
|
25
|
-
"./scripts/hashDocSources.js": "./scripts/hashDocSources.js",
|
|
26
24
|
"./content/*": "./content/*"
|
|
27
25
|
},
|
|
28
26
|
"files": [
|
|
29
27
|
"content/**",
|
|
30
|
-
"hazards.json",
|
|
31
28
|
"index.json",
|
|
32
29
|
"scripts/*"
|
|
33
30
|
],
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@lowdefy/nunjucks": "0.0.0-experimental-20260928120643"
|
|
36
|
-
},
|
|
37
31
|
"publishConfig": {
|
|
38
32
|
"access": "public"
|
|
39
33
|
}
|
|
@@ -18,8 +18,6 @@ import fs from 'fs';
|
|
|
18
18
|
import path, { dirname } from 'path';
|
|
19
19
|
import { fileURLToPath } from 'url';
|
|
20
20
|
|
|
21
|
-
import { nunjucksFunction } from '@lowdefy/nunjucks';
|
|
22
|
-
|
|
23
21
|
// Runs inside the docs app build (see packages/docs/templates/generateSiteAssets.js),
|
|
24
22
|
// where pages are fully resolved: _refs inlined, template vars substituted.
|
|
25
23
|
// Markdown content lives on Markdown/MarkdownWithCode block properties in
|
|
@@ -53,37 +51,12 @@ function resolvePageSections(pages, menus) {
|
|
|
53
51
|
return sectionMap;
|
|
54
52
|
}
|
|
55
53
|
|
|
56
|
-
function isPlainObject(value) {
|
|
57
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Many docs pages write their markdown as a `_nunjucks` template so it can
|
|
61
|
-
// print the current version (`on: { version: _ref: version.yaml }`). With its
|
|
62
|
-
// _refs resolved, such a template renders to the same markdown at build time
|
|
63
|
-
// as in the browser. A template that reads state or other runtime operators
|
|
64
|
-
// (the live examples on block pages) has no static rendering and is skipped.
|
|
65
|
-
function renderStaticNunjucks(value) {
|
|
66
|
-
if (!isPlainObject(value) || !isPlainObject(value._nunjucks)) return undefined;
|
|
67
|
-
const { template, on = {} } = value._nunjucks;
|
|
68
|
-
if (typeof template !== 'string' || !isPlainObject(on)) return undefined;
|
|
69
|
-
const vars = {};
|
|
70
|
-
for (const [key, varValue] of Object.entries(on)) {
|
|
71
|
-
if (key.startsWith('~')) continue;
|
|
72
|
-
if (key.startsWith('_') || (typeof varValue === 'object' && varValue !== null)) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
vars[key] = varValue;
|
|
76
|
-
}
|
|
77
|
-
return nunjucksFunction(template)(vars);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
54
|
function extractPageMarkdown(page) {
|
|
81
55
|
const parts = [];
|
|
82
56
|
function collect(value) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
parts.push(markdown.trim());
|
|
57
|
+
// Unresolved runtime operators are objects — only static strings are docs content.
|
|
58
|
+
if (typeof value === 'string' && value.trim() !== '') {
|
|
59
|
+
parts.push(value.trim());
|
|
87
60
|
}
|
|
88
61
|
}
|
|
89
62
|
function walkBlock(block) {
|
|
@@ -126,10 +99,6 @@ function extractAgentDocs({ pages, menus, outputDir }) {
|
|
|
126
99
|
fs.rmSync(contentDir, { recursive: true, force: true });
|
|
127
100
|
|
|
128
101
|
const docs = [];
|
|
129
|
-
// The ref each page was resolved from (a non-enumerable build marker).
|
|
130
|
-
// recordSourceHashes, which runs after the build, maps it to the page's
|
|
131
|
-
// source files through the build's refMap.
|
|
132
|
-
const sources = {};
|
|
133
102
|
pages.filter(Boolean).forEach((page) => {
|
|
134
103
|
const title = page.properties?.title ?? page.id;
|
|
135
104
|
const section = sectionMap.get(page.id)?.label ?? 'Other';
|
|
@@ -150,12 +119,11 @@ function extractAgentDocs({ pages, menus, outputDir }) {
|
|
|
150
119
|
doc.typeName = title;
|
|
151
120
|
}
|
|
152
121
|
docs.push(doc);
|
|
153
|
-
sources[slug] = { refId: page['~r'] };
|
|
154
122
|
});
|
|
155
123
|
|
|
156
124
|
fs.writeFileSync(
|
|
157
125
|
path.join(outputDir, 'index.json'),
|
|
158
|
-
JSON.stringify({ version: packageJson.version, docs
|
|
126
|
+
JSON.stringify({ version: packageJson.version, docs }, null, 2)
|
|
159
127
|
);
|
|
160
128
|
}
|
|
161
129
|
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# EmailOtpSend
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
email: string
|
|
6
|
-
captchaToken?: string
|
|
7
|
-
}): void
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
The `EmailOtpSend` action emails a one-time sign-in code to an address. It requires `auth.emailOTP` to be enabled — see [Configuration](/auth-configuration).
|
|
11
|
-
|
|
12
|
-
A code is typed into the tab the person started from, so the sign-in survives corporate mail security that pre-fetches links (which consumes a single-use magic link before the person clicks it), and it works when the email is read on another device.
|
|
13
|
-
|
|
14
|
-
Use [`EmailOtpVerify`](/EmailOtpVerify) to complete the sign-in with the code.
|
|
15
|
-
|
|
16
|
-
When `auth.magicLink` is enabled alongside `auth.emailOTP`, the magic-link email already carries the code: the [`Login`](/Login) action with `magicLink: true` sends one email that serves both paths, and `EmailOtpSend` is then only needed for a code-only page that offers no link at all.
|
|
17
|
-
|
|
18
|
-
Under an invite-only signup policy an address that is not admitted gets no email, and the action still resolves successfully — the response is identical either way, so the "check your email" screen gives nothing away about who has an account.
|
|
19
|
-
|
|
20
|
-
#### Parameters
|
|
21
|
-
|
|
22
|
-
###### object
|
|
23
|
-
- `email: string`: __required__ - The email address to send the sign-in code to.
|
|
24
|
-
- `captchaToken: string`: A captcha token minted by a `Captcha` block, sent as the `x-captcha-response` header when `auth.captcha` is enabled. Tokens are single-use, so reset the `Captcha` block in `onError` for retries.
|
|
25
|
-
|
|
26
|
-
#### Examples
|
|
27
|
-
|
|
28
|
-
###### Send a sign-in code:
|
|
29
|
-
```yaml
|
|
30
|
-
- id: send_code
|
|
31
|
-
type: EmailOtpSend
|
|
32
|
-
params:
|
|
33
|
-
email:
|
|
34
|
-
_state: email
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
###### Send a code and tell the user to check their inbox:
|
|
38
|
-
```yaml
|
|
39
|
-
- id: send_code
|
|
40
|
-
type: Button
|
|
41
|
-
properties:
|
|
42
|
-
title: Send code
|
|
43
|
-
events:
|
|
44
|
-
onClick:
|
|
45
|
-
- id: validate
|
|
46
|
-
type: Validate
|
|
47
|
-
params:
|
|
48
|
-
regex: ^email$
|
|
49
|
-
- id: send
|
|
50
|
-
type: EmailOtpSend
|
|
51
|
-
params:
|
|
52
|
-
email:
|
|
53
|
-
_state: email
|
|
54
|
-
- id: sent
|
|
55
|
-
type: DisplayMessage
|
|
56
|
-
params:
|
|
57
|
-
content: Check your email for the sign-in code.
|
|
58
|
-
```
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# EmailOtpVerify
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
email: string
|
|
6
|
-
otp: string
|
|
7
|
-
callbackUrl?: {
|
|
8
|
-
home?: boolean
|
|
9
|
-
pageId?: string
|
|
10
|
-
url?: string
|
|
11
|
-
urlQuery?: object
|
|
12
|
-
} | false
|
|
13
|
-
}): void
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
The `EmailOtpVerify` action signs a user in with the one-time code emailed to them by [`EmailOtpSend`](/EmailOtpSend), or carried on the magic-link email when `auth.magicLink` and `auth.emailOTP` are both enabled. It requires `auth.emailOTP` to be enabled — see [Configuration](/auth-configuration).
|
|
17
|
-
|
|
18
|
-
On success the session cookie is set — creating the account on first sign-in, unless `emailOTP.disableSignUp` is `true` — and the browser lands on the resolved `callbackUrl`. Three sources are consulted, in order:
|
|
19
|
-
|
|
20
|
-
1. The `callbackUrl` param, if given.
|
|
21
|
-
2. The `?callbackUrl=` query parameter, which Lowdefy sets when it redirects an unauthenticated user to the sign-in page.
|
|
22
|
-
3. The app's home page.
|
|
23
|
-
|
|
24
|
-
To sign in without navigating, set `callbackUrl: false` — valid here, unlike on the magic-link and social paths, because this is a plain JSON sign-in with no redirect hop.
|
|
25
|
-
|
|
26
|
-
If the user has two-factor authentication enrolled, the code mints a challenge rather than a session: the action navigates to `authPages.twoFactor` carrying the resolved destination as `?callbackUrl=`, where [`TwoFactorVerify`](/two-factor) finishes the sign-in, and the event chain stops.
|
|
27
|
-
|
|
28
|
-
An expired, mistyped or already-used code is the auth server rejecting the attempt, not an app fault. The action throws a `UserError`: `catch` actions still run and the message still displays, but it is logged to the browser console only and is never reported to the server.
|
|
29
|
-
|
|
30
|
-
#### Parameters
|
|
31
|
-
|
|
32
|
-
###### object
|
|
33
|
-
- `email: string`: __required__ - The email address the code was sent to.
|
|
34
|
-
- `otp: string`: __required__ - The one-time code from the email.
|
|
35
|
-
- `callbackUrl: object | false`: Set to `false` to sign in without navigating. As an object:
|
|
36
|
-
- `home: boolean`: Land on the app's home page.
|
|
37
|
-
- `pageId: string`: The pageId to land on.
|
|
38
|
-
- `url: string`: The URL to land on. An absolute URL is not `basePath`-prefixed, so it can be an external landing page.
|
|
39
|
-
- `urlQuery: object`: The urlQuery to set on the destination.
|
|
40
|
-
|
|
41
|
-
#### Examples
|
|
42
|
-
|
|
43
|
-
###### Sign in with the code and land on the home page (or the page the user was bounced from):
|
|
44
|
-
```yaml
|
|
45
|
-
- id: verify_code
|
|
46
|
-
type: EmailOtpVerify
|
|
47
|
-
params:
|
|
48
|
-
email:
|
|
49
|
-
_state: email
|
|
50
|
-
otp:
|
|
51
|
-
_state: otp
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
###### Sign in and land on a specific page:
|
|
55
|
-
```yaml
|
|
56
|
-
- id: verify_code
|
|
57
|
-
type: EmailOtpVerify
|
|
58
|
-
params:
|
|
59
|
-
email:
|
|
60
|
-
_state: email
|
|
61
|
-
otp:
|
|
62
|
-
_state: otp
|
|
63
|
-
callbackUrl:
|
|
64
|
-
pageId: dashboard
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
###### Sign in inside a modal, without navigating:
|
|
68
|
-
```yaml
|
|
69
|
-
- id: verify_code
|
|
70
|
-
type: EmailOtpVerify
|
|
71
|
-
params:
|
|
72
|
-
email:
|
|
73
|
-
_state: email
|
|
74
|
-
otp:
|
|
75
|
-
_state: otp
|
|
76
|
-
callbackUrl: false
|
|
77
|
-
```
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# GetLocalStorage
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
key: string,
|
|
6
|
-
default?: any
|
|
7
|
-
}): any
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
The `GetLocalStorage` action reads a value from the browser's [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). Values written by the [`SetLocalStorage`](/SetLocalStorage) action are deserialized, so objects, arrays and dates are returned as the same types that were stored.
|
|
11
|
-
|
|
12
|
-
Local storage is per browser and per origin, so a value stored in one browser is not available in another.
|
|
13
|
-
|
|
14
|
-
A value that was not written by `SetLocalStorage` and is not valid JSON is returned as the plain string that is stored. If the browser blocks local storage, the action returns the `default` value, as if the key were not set. Keys starting with `lowdefy_` or `lf-` are reserved for settings Lowdefy stores itself, such as the dark mode preference, and the action throws an error if one is used.
|
|
15
|
-
|
|
16
|
-
#### Parameters
|
|
17
|
-
|
|
18
|
-
###### object
|
|
19
|
-
- `key: string`: __Required__ - The local storage key to read. Keys starting with `lowdefy_` or `lf-` are reserved.
|
|
20
|
-
- `default: any`: The value returned when the key is not set in local storage, or when the browser blocks local storage.
|
|
21
|
-
|
|
22
|
-
#### Response
|
|
23
|
-
|
|
24
|
-
The value stored at the key, or the `default` value when the key is not set or local storage is blocked. When the key is not set and no `default` is given, the response is `undefined`.
|
|
25
|
-
|
|
26
|
-
#### Examples
|
|
27
|
-
|
|
28
|
-
###### Restore a user preference on page load:
|
|
29
|
-
```yaml
|
|
30
|
-
- id: read_preference
|
|
31
|
-
type: GetLocalStorage
|
|
32
|
-
params:
|
|
33
|
-
key: dashboard_filters
|
|
34
|
-
default:
|
|
35
|
-
status: open
|
|
36
|
-
- id: apply_preference
|
|
37
|
-
type: SetState
|
|
38
|
-
params:
|
|
39
|
-
filters:
|
|
40
|
-
_actions: read_preference.response
|
|
41
|
-
```
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# MagicLinkVerify
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params?: {
|
|
5
|
-
callbackUrl?: {
|
|
6
|
-
home?: boolean
|
|
7
|
-
pageId?: string
|
|
8
|
-
url?: string
|
|
9
|
-
urlQuery?: object
|
|
10
|
-
}
|
|
11
|
-
errorCallbackUrl?: {
|
|
12
|
-
home?: boolean
|
|
13
|
-
pageId?: string
|
|
14
|
-
url?: string
|
|
15
|
-
urlQuery?: object
|
|
16
|
-
}
|
|
17
|
-
newUserCallbackUrl?: {
|
|
18
|
-
home?: boolean
|
|
19
|
-
pageId?: string
|
|
20
|
-
url?: string
|
|
21
|
-
urlQuery?: object
|
|
22
|
-
}
|
|
23
|
-
token?: string
|
|
24
|
-
}): void
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
The `MagicLinkVerify` action completes a magic-link sign-in from the landing page the sign-in email points at. It navigates the browser to the auth server's verify endpoint, which sets the session cookie and redirects the user on to their destination.
|
|
28
|
-
|
|
29
|
-
## Why a landing page
|
|
30
|
-
|
|
31
|
-
A magic-link token is single-use, and the verify endpoint consumes it on the **first** `GET` of the URL. Corporate mail security — Microsoft Defender Safe Links, Proofpoint URL Defense, Mimecast — fetches every link in a message as it is delivered. When the email links straight at the verify endpoint the scanner spends the token minutes before the person clicks, and the person lands on the auth error page with `INVALID_TOKEN`.
|
|
32
|
-
|
|
33
|
-
Setting [`auth.authPages.magicLink`](/auth-configuration#the-magic-link-landing-page) to a page in your app moves the email's link to that page, carrying the token and callback destinations on the URL query. Fetching a Lowdefy page has no side effect, so the token stays unspent until a person clicks a button that runs `MagicLinkVerify`.
|
|
34
|
-
|
|
35
|
-
This action **must** be bound to a click. Do not run it in `onMount` and do not auto-redirect from the landing page: scanning sandboxes that execute JavaScript would consume the token anyway, and you would be no better off than linking at the verify endpoint directly.
|
|
36
|
-
|
|
37
|
-
## Defaults come from the URL query
|
|
38
|
-
|
|
39
|
-
Every parameter is optional. The auth server minted the landing URL with the verify query on it, so the action reads its defaults from the page's own URL:
|
|
40
|
-
|
|
41
|
-
| Parameter | Default |
|
|
42
|
-
| --------- | ------- |
|
|
43
|
-
| `token` | the `?token=` query parameter |
|
|
44
|
-
| `callbackUrl` | the `?callbackURL=` query parameter, else the auth server's default |
|
|
45
|
-
| `newUserCallbackUrl` | the `?newUserCallbackURL=` query parameter, else `callbackUrl` |
|
|
46
|
-
| `errorCallbackUrl` | the `?errorCallbackURL=` query parameter, else `auth.authPages.error` |
|
|
47
|
-
|
|
48
|
-
Pass a parameter only to override what the email carried. The action throws if there is no token in either place, because there is nothing to verify.
|
|
49
|
-
|
|
50
|
-
`callbackUrl: false` is not valid here. Verification redirects through a hop the app does not control, so there is no staying put.
|
|
51
|
-
|
|
52
|
-
The event chain ends after this action, like every other action that navigates the browser away — a step after it would race the page being replaced.
|
|
53
|
-
|
|
54
|
-
#### Parameters
|
|
55
|
-
|
|
56
|
-
###### object
|
|
57
|
-
- `token: string`: The single-use magic-link token. Defaults to the `?token=` URL query parameter of the landing page.
|
|
58
|
-
- `callbackUrl: object`: Where a successful sign-in lands. Defaults to the `?callbackURL=` URL query parameter.
|
|
59
|
-
- `home: boolean`: Land on the app's home page.
|
|
60
|
-
- `pageId: string`: The pageId to land on.
|
|
61
|
-
- `url: string`: The URL to land on. An absolute URL is not `basePath`-prefixed, so it can be an external landing page.
|
|
62
|
-
- `urlQuery: object`: The urlQuery to set on the destination.
|
|
63
|
-
- `newUserCallbackUrl: object`: Where a sign-in that creates a new account lands, for a first-run or onboarding page. Defaults to the `?newUserCallbackURL=` URL query parameter. Same fields as `callbackUrl`.
|
|
64
|
-
- `errorCallbackUrl: object`: Where a failed verification lands, with the reason in `?error=`. Defaults to the `?errorCallbackURL=` URL query parameter, then to `auth.authPages.error`. Same fields as `callbackUrl`.
|
|
65
|
-
|
|
66
|
-
#### Examples
|
|
67
|
-
|
|
68
|
-
###### The landing page, with everything taken from the URL query:
|
|
69
|
-
```yaml
|
|
70
|
-
id: magic-link
|
|
71
|
-
type: PageHeaderMenu
|
|
72
|
-
blocks:
|
|
73
|
-
- id: content
|
|
74
|
-
type: Box
|
|
75
|
-
blocks:
|
|
76
|
-
- id: title
|
|
77
|
-
type: Title
|
|
78
|
-
properties:
|
|
79
|
-
content: Sign in
|
|
80
|
-
level: 3
|
|
81
|
-
- id: description
|
|
82
|
-
type: Paragraph
|
|
83
|
-
properties:
|
|
84
|
-
content: Click the button below to finish signing in.
|
|
85
|
-
- id: verify_button
|
|
86
|
-
type: Button
|
|
87
|
-
properties:
|
|
88
|
-
title: Sign in
|
|
89
|
-
events:
|
|
90
|
-
onClick:
|
|
91
|
-
- id: verify
|
|
92
|
-
type: MagicLinkVerify
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
###### Send a new user to an onboarding page instead:
|
|
96
|
-
```yaml
|
|
97
|
-
- id: verify
|
|
98
|
-
type: MagicLinkVerify
|
|
99
|
-
params:
|
|
100
|
-
newUserCallbackUrl:
|
|
101
|
-
pageId: welcome
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
###### Override where a successful sign-in lands:
|
|
105
|
-
```yaml
|
|
106
|
-
- id: verify
|
|
107
|
-
type: MagicLinkVerify
|
|
108
|
-
params:
|
|
109
|
-
callbackUrl:
|
|
110
|
-
pageId: dashboard
|
|
111
|
-
urlQuery:
|
|
112
|
-
source: magic-link
|
|
113
|
-
```
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# PostHogAlias
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
alias: string,
|
|
6
|
-
}): Promise<null>
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
The `PostHogAlias` action points a second id at the person PostHog already knows, for example when an app has its own identifier alongside the one used by [`PostHogIdentify`](/PostHogIdentify).
|
|
10
|
-
|
|
11
|
-
When PostHog is disabled or `posthog-js` could not be loaded, the action does nothing. Invalid params always throw, even when PostHog is disabled.
|
|
12
|
-
|
|
13
|
-
The action is part of the [`@lowdefy/plugin-posthog`](/PostHog) plugin, which is included by default. See the [PostHog guide](/PostHog) for how the actions fit together.
|
|
14
|
-
|
|
15
|
-
#### Parameters
|
|
16
|
-
|
|
17
|
-
###### object
|
|
18
|
-
- `alias: string`: __Required__ - The second id for the current person.
|
|
19
|
-
|
|
20
|
-
#### Examples
|
|
21
|
-
|
|
22
|
-
###### Alias a customer number:
|
|
23
|
-
```yaml
|
|
24
|
-
- id: alias_person
|
|
25
|
-
type: PostHogAlias
|
|
26
|
-
params:
|
|
27
|
-
alias:
|
|
28
|
-
_user: customerNumber
|
|
29
|
-
```
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# PostHogCapture
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
event: string,
|
|
6
|
-
properties?: object,
|
|
7
|
-
groups?: object,
|
|
8
|
-
}): Promise<null>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
The `PostHogCapture` action captures a named product event in [PostHog](https://posthog.com).
|
|
12
|
-
|
|
13
|
-
Autocapture already records clicks and pageviews, so keep the set of named events small. Every event is billable, and a funnel of thirty near identical events tells you less than one of five. Never send personally identifiable information as a property.
|
|
14
|
-
|
|
15
|
-
When PostHog is disabled or `posthog-js` could not be loaded, the action does nothing. Invalid params always throw, even when PostHog is disabled.
|
|
16
|
-
|
|
17
|
-
The action is part of the [`@lowdefy/plugin-posthog`](/PostHog) plugin, which is included by default. See the [PostHog guide](/PostHog) for how the actions fit together.
|
|
18
|
-
|
|
19
|
-
#### Parameters
|
|
20
|
-
|
|
21
|
-
###### object
|
|
22
|
-
- `event: string`: __Required__ - The event name. Snake case names that read as a completed action, like `report_submitted`, work best in funnels.
|
|
23
|
-
- `properties: object`: Event properties.
|
|
24
|
-
- `groups: object`: Groups to attach to this one event, as `{ groupType: groupKey }`. Sent to PostHog as the `$groups` property.
|
|
25
|
-
|
|
26
|
-
#### Examples
|
|
27
|
-
|
|
28
|
-
###### Capture an event after a request:
|
|
29
|
-
```yaml
|
|
30
|
-
- id: submit_report
|
|
31
|
-
type: Button
|
|
32
|
-
properties:
|
|
33
|
-
title: Submit report
|
|
34
|
-
events:
|
|
35
|
-
onClick:
|
|
36
|
-
- id: submit
|
|
37
|
-
type: Request
|
|
38
|
-
params: submit_report
|
|
39
|
-
- id: capture_event
|
|
40
|
-
type: PostHogCapture
|
|
41
|
-
params:
|
|
42
|
-
event: report_submitted
|
|
43
|
-
properties:
|
|
44
|
-
report_type:
|
|
45
|
-
_state: report_type
|
|
46
|
-
line_item_count:
|
|
47
|
-
_array.length:
|
|
48
|
-
_state: line_items
|
|
49
|
-
```
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# PostHogCapturePageLeave
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
properties?: object,
|
|
6
|
-
}): Promise<null>
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
The `PostHogCapturePageLeave` action captures a `$pageleave` event by hand, the counterpart to [`PostHogPageview`](/PostHogPageview). PostHog uses pageleaves to compute bounce rate and time on page.
|
|
10
|
-
|
|
11
|
-
`posthog-js` captures a pageleave itself when the tab is closed, as long as automatic pageviews are on, because `capture_pageleave` defaults to `if_capture_pageview`. With `capture_pageview: false`, set `capture_pageleave: true` in the [`PostHogInit`](/PostHogInit) options to keep them, or use this action, for example before a `Link` or `Logout` action. The page `onHidden` event is not a page leave: it also fires when the browser window loses focus.
|
|
12
|
-
|
|
13
|
-
When PostHog is disabled or `posthog-js` could not be loaded, the action does nothing. Invalid params always throw, even when PostHog is disabled.
|
|
14
|
-
|
|
15
|
-
The action is part of the [`@lowdefy/plugin-posthog`](/PostHog) plugin, which is included by default. See the [PostHog guide](/PostHog) for how the actions fit together.
|
|
16
|
-
|
|
17
|
-
#### Parameters
|
|
18
|
-
|
|
19
|
-
###### object
|
|
20
|
-
- `properties: object`: Properties to add to the `$pageleave` event.
|
|
21
|
-
|
|
22
|
-
#### Examples
|
|
23
|
-
|
|
24
|
-
###### Capture a pageleave before signing out:
|
|
25
|
-
```yaml
|
|
26
|
-
- id: sign_out
|
|
27
|
-
type: Button
|
|
28
|
-
properties:
|
|
29
|
-
title: Sign out
|
|
30
|
-
events:
|
|
31
|
-
onClick:
|
|
32
|
-
- id: capture_pageleave
|
|
33
|
-
type: PostHogCapturePageLeave
|
|
34
|
-
- id: reset_posthog
|
|
35
|
-
type: PostHogReset
|
|
36
|
-
- id: logout
|
|
37
|
-
type: Logout
|
|
38
|
-
```
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# PostHogFeatureFlag
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
key: string,
|
|
6
|
-
default?: any,
|
|
7
|
-
enabled?: boolean,
|
|
8
|
-
payload?: boolean,
|
|
9
|
-
}): Promise<any>
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
The `PostHogFeatureFlag` action reads a PostHog feature flag and returns its value, so it can be used further down the action chain with the [`_actions`](/_actions) operator.
|
|
13
|
-
|
|
14
|
-
The value is whatever PostHog resolved for this person when flags were last loaded; the action does not wait for a network call. When the person or their groups just changed, reload the flags first with [`PostHogReloadFeatureFlags`](/PostHogReloadFeatureFlags).
|
|
15
|
-
|
|
16
|
-
Reading a flag value, with or without `enabled`, sends a `$feature_flag_called` event to PostHog, which is what PostHog experiments use to count exposures. Reading a payload does not.
|
|
17
|
-
|
|
18
|
-
When PostHog is disabled, not initialised, or `posthog-js` could not be loaded, the action returns `default`. Invalid params always throw, even when PostHog is disabled.
|
|
19
|
-
|
|
20
|
-
The action is part of the [`@lowdefy/plugin-posthog`](/PostHog) plugin, which is included by default. See the [PostHog guide](/PostHog) for how the actions fit together.
|
|
21
|
-
|
|
22
|
-
#### Parameters
|
|
23
|
-
|
|
24
|
-
###### object
|
|
25
|
-
- `key: string`: __Required__ - The feature flag key.
|
|
26
|
-
- `default: any`: Returned when the flag has no value for this person, and when PostHog is disabled. Defaults to `null`.
|
|
27
|
-
- `enabled: boolean`: Return a boolean, using `isFeatureEnabled`, instead of the variant value.
|
|
28
|
-
- `payload: boolean`: Return the flag payload, using `getFeatureFlagPayload`, instead of the flag value. Takes precedence over `enabled`.
|
|
29
|
-
|
|
30
|
-
#### Response
|
|
31
|
-
|
|
32
|
-
The flag value, the payload, or a boolean, depending on the params. `default` when the flag has no value.
|
|
33
|
-
|
|
34
|
-
#### Examples
|
|
35
|
-
|
|
36
|
-
###### Store a flag variant in state:
|
|
37
|
-
```yaml
|
|
38
|
-
events:
|
|
39
|
-
onMount:
|
|
40
|
-
- id: read_flag
|
|
41
|
-
type: PostHogFeatureFlag
|
|
42
|
-
params:
|
|
43
|
-
key: new-checkout
|
|
44
|
-
default: control
|
|
45
|
-
- id: store_flag
|
|
46
|
-
type: SetState
|
|
47
|
-
params:
|
|
48
|
-
checkout_variant:
|
|
49
|
-
_actions: read_flag.response
|
|
50
|
-
```
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# PostHogGroup
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
type: string,
|
|
6
|
-
key: string,
|
|
7
|
-
properties?: object,
|
|
8
|
-
}): Promise<null>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
The `PostHogGroup` action associates the current person with a group, so events can be analysed per organization, team or account. The association sticks until [`PostHogReset`](/PostHogReset) is called, so run it after [`PostHogIdentify`](/PostHogIdentify). Group types have to be enabled on the PostHog project.
|
|
12
|
-
|
|
13
|
-
When PostHog is disabled or `posthog-js` could not be loaded, the action does nothing. Invalid params always throw, even when PostHog is disabled.
|
|
14
|
-
|
|
15
|
-
The action is part of the [`@lowdefy/plugin-posthog`](/PostHog) plugin, which is included by default. See the [PostHog guide](/PostHog) for how the actions fit together.
|
|
16
|
-
|
|
17
|
-
#### Parameters
|
|
18
|
-
|
|
19
|
-
###### object
|
|
20
|
-
- `type: string`: __Required__ - The group type, for example `organization`.
|
|
21
|
-
- `key: string`: __Required__ - The id of the group instance.
|
|
22
|
-
- `properties: object`: Group properties.
|
|
23
|
-
|
|
24
|
-
#### Examples
|
|
25
|
-
|
|
26
|
-
###### Associate the person with their organization:
|
|
27
|
-
```yaml
|
|
28
|
-
- id: set_group
|
|
29
|
-
type: PostHogGroup
|
|
30
|
-
params:
|
|
31
|
-
type: organization
|
|
32
|
-
key:
|
|
33
|
-
_user: organizationId
|
|
34
|
-
properties:
|
|
35
|
-
plan:
|
|
36
|
-
_user: plan
|
|
37
|
-
```
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# PostHogIdentify
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
(params: {
|
|
5
|
-
id?: string | null,
|
|
6
|
-
properties?: object,
|
|
7
|
-
propertiesOnce?: object,
|
|
8
|
-
}): Promise<null>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
The `PostHogIdentify` action ties the current browser session to a person in [PostHog](https://posthog.com). Run it once the user is known, usually right after [`PostHogInit`](/PostHogInit) in the shared page `onInit` actions, or after a successful login.
|
|
12
|
-
|
|
13
|
-
A missing, `null` or empty `id` is a no-op, so on a public page the anonymous session is left alone. That anonymous session is what a later `PostHogIdentify` merges into the person, which is what makes signup funnels work.
|
|
14
|
-
|
|
15
|
-
The action is safe to run on every page. It reads the identity `posthog-js` already holds:
|
|
16
|
-
|
|
17
|
-
- __Same person__: when `id` is already the current `distinct_id`, it only updates the person properties, if any are given. `posthog-js` skips a property update identical to the previous one.
|
|
18
|
-
- __Person swap__: PostHog refuses to move an identified `distinct_id` onto a different person, so when the browser is identified as someone else, the action calls `reset()` before identifying the new person.
|
|
19
|
-
- __Anonymous visitor__: identified without a reset, so the anonymous session merges into the person.
|
|
20
|
-
|
|
21
|
-
Never send personally identifiable information as a person property.
|
|
22
|
-
|
|
23
|
-
When PostHog is disabled or `posthog-js` could not be loaded, the action does nothing. Invalid params always throw, even when PostHog is disabled.
|
|
24
|
-
|
|
25
|
-
The action is part of the [`@lowdefy/plugin-posthog`](/PostHog) plugin, which is included by default. See the [PostHog guide](/PostHog) for how the actions fit together.
|
|
26
|
-
|
|
27
|
-
#### Parameters
|
|
28
|
-
|
|
29
|
-
###### object
|
|
30
|
-
- `id: string`: The person's id.
|
|
31
|
-
- `properties: object`: Person properties to set. `null` and `undefined` values are dropped, so an absent value never overwrites one PostHog already has.
|
|
32
|
-
- `propertiesOnce: object`: Person properties that are only set the first time, for example a signup date.
|
|
33
|
-
|
|
34
|
-
#### Examples
|
|
35
|
-
|
|
36
|
-
###### Identify the logged in user on every page:
|
|
37
|
-
```yaml
|
|
38
|
-
# shared/posthog_init.yaml
|
|
39
|
-
- id: init_posthog
|
|
40
|
-
type: PostHogInit
|
|
41
|
-
params:
|
|
42
|
-
apiKey:
|
|
43
|
-
_build.env: POSTHOG_API_KEY
|
|
44
|
-
- id: identify_person
|
|
45
|
-
type: PostHogIdentify
|
|
46
|
-
params:
|
|
47
|
-
id:
|
|
48
|
-
_user: id
|
|
49
|
-
properties:
|
|
50
|
-
role:
|
|
51
|
-
_user: role
|
|
52
|
-
locale:
|
|
53
|
-
_locale: active
|
|
54
|
-
```
|