diff --git a/.github/workflows/i18n-auto-translate.yml b/.github/workflows/i18n-auto-translate.yml index 189f33d1e127d2..8d08a28fa1d687 100644 --- a/.github/workflows/i18n-auto-translate.yml +++ b/.github/workflows/i18n-auto-translate.yml @@ -28,15 +28,18 @@ concurrency: jobs: translate: + # Fork-only guard applies to all runs, including manual dispatch. # Loop prevention ([i18n-bot] commits) and Crowdin commits/merges (l10n_* branches) are ignored if: >- - github.event_name == 'workflow_dispatch' || ( - !contains(github.event.head_commit.message, '[i18n-bot]') && - !contains(github.event.head_commit.message, 'l10n_') && - !contains(github.event.head_commit.message, 'New Crowdin') && - !contains(github.event.head_commit.message, 'New translations') && - !contains(github.event.head_commit.author.name, 'crowdin') && - !contains(github.actor, 'crowdin') + github.repository == 'doc4d/docs' && ( + github.event_name == 'workflow_dispatch' || ( + !contains(github.event.head_commit.message, '[i18n-bot]') && + !contains(github.event.head_commit.message, 'l10n_') && + !contains(github.event.head_commit.message, 'New Crowdin') && + !contains(github.event.head_commit.message, 'New translations') && + !contains(github.event.head_commit.author.name, 'crowdin') && + !contains(github.actor, 'crowdin') + ) ) runs-on: ubuntu-latest timeout-minutes: 60 diff --git a/.github/workflows/i18n-cleanup.yml b/.github/workflows/i18n-cleanup.yml new file mode 100644 index 00000000000000..e2b7bf3d226364 --- /dev/null +++ b/.github/workflows/i18n-cleanup.yml @@ -0,0 +1,83 @@ +name: i18n branch cleanup + +on: + pull_request_target: + types: [closed] + +permissions: {} + +jobs: + cleanup: + if: >- + github.repository == 'doc4d/docs' && + github.event.pull_request.merged == true && + github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + steps: + # Metadata only: never check out or execute code from the PR. + - name: Delete merged translation branch + env: + GH_TOKEN: ${{ github.token }} + run: | + python3 - <<'PY' + import json + import os + from urllib.error import HTTPError + from urllib.parse import quote + from urllib.request import Request, urlopen + + with open(os.environ["GITHUB_EVENT_PATH"]) as event_file: + event = json.load(event_file) + pr = event["pull_request"] + repo = event["repository"] + head = pr["head"] + branch = head["ref"] + prefix = "i18n/auto-pt-" + if ( + repo["full_name"] != "doc4d/docs" + or not pr["merged"] + or (head.get("repo") or {}).get("full_name") != repo["full_name"] + or not branch.startswith(prefix) + or len(branch) == len(prefix) + or branch in ("main", repo["default_branch"], pr["base"]["ref"]) + ): + print("Branch is not eligible for cleanup.") + raise SystemExit(0) + + def api(method, path): + request = Request( + f'{os.environ["GITHUB_API_URL"]}/repos/{repo["full_name"]}/{path}', + method=method, + headers={ + "Authorization": "Bearer " + os.environ["GH_TOKEN"], + "Accept": "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + }, + ) + with urlopen(request, timeout=30) as response: + body = response.read() + return json.loads(body) if body else None + + ref = f"heads/{branch}" + # matching-refs returns [] for a missing branch; API/auth errors still fail. + refs = api("GET", f"git/matching-refs/{quote(ref, safe='')}") + current = next((item for item in refs if item["ref"] == f"refs/{ref}"), None) + if current is None: + print("Branch is already deleted.") + elif current["object"]["sha"] != head["sha"]: + print("Branch tip has changed; preserving it.") + else: + try: + api("DELETE", f"git/refs/{quote(ref, safe='')}") + except HTTPError as error: + # Another cleanup may have deleted the ref after our SHA check. + body = error.read() + if error.code != 422 or json.loads(body).get("message") != "Reference does not exist": + raise + print("Branch is already deleted.") + else: + print("Merged translation branch deleted.") + PY diff --git a/docs/API/DataStoreClass.md b/docs/API/DataStoreClass.md index ca480416fb69eb..f6661185ec8b85 100644 --- a/docs/API/DataStoreClass.md +++ b/docs/API/DataStoreClass.md @@ -17,14 +17,19 @@ A [Datastore](ORDA/dsMapping.md#datastore) is the interface object provided by O |[](#dataclassname)
| |[](#encryptionstatus)
| |[](#flushandlock)
| +|[](#generatefinegrainedtoken)
| |[](#getallremotecontexts)
| |[](#getglobalstamp)
| |[](#getinfo)
| |[](#getremotecontextinfo)
| |[](#getrequestlog)
| +|[](#listfinegrainedtokens)
| +|[](#listoauthgrants)
| |[](#locked)
| |[](#makeselectionsalterable)
| |[](#providedatakey)
| +|[](#revokefinegrainedtoken)
| +|[](#revokeoauthgrant)
| |[](#setadminprotection)
| |[](#setglobalstamp)
| |[](#setremotecontextinfo)
| @@ -299,6 +304,82 @@ ds.unlock() //Our copy is over, we can now unlock the datastore [.locked()](#locked)
[.unlock()](#unlock) + +## .generateFineGrainedToken() + +
History + +|Release|Changes| +|---|---| +|21 R6|Added| + +
+ +**.generateFineGrainedToken**( *privilege* : Text ; *name* : Text ; *expiry* : Date {; *info* : Object} ) : Object
**.generateFineGrainedToken**( *privileges* : Collection ; *name* : Text ; *expiry* : Date {; *info* : Object} ) : Object
**.generateFineGrainedToken**( *settings* : Object ; *name* : Text ; *expiry* : Date {; *info* : Object} ) : Object + + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|privilege|Text|→|Privilege name, or comma-separated privilege names| +|privileges|Collection|→|Collection of privilege names| +|settings|Object|→|Object with a "privileges" and/or "roles" property| +|name|Text|→|Name of the token| +|expiry|Date|→|Expiration date of the token| +|info|Object|→|Information stored with the token and passed to `ds.mcpAuthenticated()`| +|Result|Object|←|`{id; token}`| +
+ + +#### Description + +The `.generateFineGrainedToken()` function generates a Fine-Grained Token that gives access to the MCP server with the privileges you pass. For more information, see [Fine-Grained Tokens](../WebServer/mcp-server.md#fine-grained-tokens). + +You pass the privileges and/or roles of the token in the same forms as for [`Session.setPrivileges()`](SessionClass.md#setprivileges): + +- In the *privilege* parameter, pass a string containing a privilege name (or several comma-separated privilege names). +- In the *privileges* parameter, pass a collection of strings containing privilege names. +- In the *settings* parameter, pass an object with a `privileges` and/or a `roles` property (string or collection of strings). + +Unlike `Session.setPrivileges()`, a name that is not declared in the [`roles.json`](../ORDA/privileges.md#rolesjson-file) file raises an error. + +In *name*, pass a name that identifies the token, for example the user and the client that will use it. It is the user name of the MCP sessions opened with the token. + +In *expiry*, pass the expiration date of the token. It is required, and it must be later than the current date and at most 366 days ahead. + +In *info*, you can pass an object that 4D stores with the token as is, and passes to the [`ds.mcpAuthenticated()`](../ORDA/ordaClasses.md#function-mcpauthenticated) function when an MCP session is opened with the token. Since it cannot be modified later, store stable identifiers (such as a user ID) and read the current values in `ds.mcpAuthenticated()`. Build *info* from the authenticated session, never from values sent by the client. + +The function can only be called in a web context, i.e. from code executed for a web or REST request (for example an exposed function called after the user was authenticated). Every privilege of the token must be held by the current session ([`Session.getPrivileges()`](SessionClass.md#getprivileges), roles included, promoted privileges excluded). Otherwise, an error is raised. + +If an error is raised, no token is created. + +**Returned object** + +|Property|Type|Description| +|---|---|---| +|id|Text|Identifier of the token. It is not secret: use it to [revoke](#revokefinegrainedtoken) the token| +|token|Text|The token, starting with "4dfgt_". It is returned only once: 4D only stores its hash, in the `fgt.json` file of the data folder| + +#### Example + +In an exposed function of the DataStore class, called by an authenticated user, you generate a token valid for 3 months: + +```4d +exposed Function getMCPToken() : Text + var $expiry:=Add to date(Current date; 0; 3; 0) + var $result:=ds.generateFineGrainedToken({roles: "salesperson"}; "Claude Desktop - "+Session.userName; $expiry; {userName: Session.userName}) + return $result.token // "4dfgt_..." +``` + +#### See also + +[.listFineGrainedTokens()](#listfinegrainedtokens)
[.revokeFineGrainedToken()](#revokefinegrainedtoken) + + + + ## .getAllRemoteContexts()
History @@ -632,6 +713,114 @@ By default, the Data Explorer access is granted for `webAdmin` sessions, but it + +## .listFineGrainedTokens() + +
History + +|Release|Changes| +|---|---| +|21 R6|Added| + +
+ +**.listFineGrainedTokens**() : Collection + + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|Result|Collection|←|Collection of token description objects| +
+ + +#### Description + +The `.listFineGrainedTokens()` function returns the description of the Fine-Grained Tokens generated for the MCP server (see [`.generateFineGrainedToken()`](#generatefinegrainedtoken)). + +When the function is called in a web context (code executed for a web or REST request), the collection only contains the tokens whose privileges are all held by the current session. Elsewhere (for example in a method or a stored procedure), it contains all the tokens. + +Each object of the returned collection contains the following properties. The token itself and its hash are never returned. + +|Property|Type|Description| +|---|---|---| +|id|Text|Identifier of the token| +|name|Text|Name of the token| +|privileges|Text, Collection or Object|Privileges and roles of the token, as passed at generation| +|expiry|Text|Expiration date of the token| +|info|Object|Information stored with the token| +|createdAt|Text|Date and time of the token generation| + +#### Example + +You revoke all the tokens generated for a user: + +```4d +var $tokens:=ds.listFineGrainedTokens().query("info.userName = :1"; "jsmith") +var $token : Object +For each ($token; $tokens) + ds.revokeFineGrainedToken($token.id) +End for each +``` + + + + + +## .listOAuthGrants() + +
History + +|Release|Changes| +|---|---| +|21 R6|Added| + +
+ +**.listOAuthGrants**() : Collection + + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|Result|Collection|←|Collection of grant description objects| +
+ + +#### Description + +The `.listOAuthGrants()` function returns the description of the grants given to users through the OAuth mode of the MCP server. A grant is created each time a user logs in from an MCP client (see [OAuth 2.1 mode](../WebServer/mcp-server.md#oauth-21-mode)). + +When the function is called in a web context (code executed for a web or REST request), the collection only contains the grants whose privileges are all held by the current session. Elsewhere, it contains all the grants. + +Each object of the returned collection contains the following properties: + +|Property|Type|Description| +|---|---|---| +|id|Text|Identifier of the grant| +|userName|Text|User name of the grant (`userName` returned by [`ds.mcpGrant()`](../ORDA/ordaClasses.md#function-mcpgrant), or the login name)| +|clientId|Text|Identifier of the MCP client| +|clientName|Text|Name of the MCP client| +|privileges|Text, Collection or Object|Privileges and roles returned by `ds.mcpGrant()`| +|createdAt|Text|Date and time of the login| +|lastUsedAt|Text|Date and time of the last use of the grant| +|expiresAt|Text|Expiration date and time of the grant| + +#### Example + +You list the MCP clients in which a user is logged in: + +```4d +var $clients:=ds.listOAuthGrants().query("userName = :1"; "jsmith").extract("clientName") +``` + + + + ## .locked()
History @@ -787,6 +976,108 @@ If no *curPassphrase* or *curDataKey* is given, `.provideDataKey()` returns **nu + +## .revokeFineGrainedToken() + +
History + +|Release|Changes| +|---|---| +|21 R6|Added| + +
+ +**.revokeFineGrainedToken**( *id* : Text )
**.revokeFineGrainedToken**( *tokenObj* : Object ) + + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|id|Text|→|Identifier of the token to revoke| +|tokenObj|Object|→|Object with a `token` property containing the token to revoke| +
+ + +#### Description + +The `.revokeFineGrainedToken()` function revokes a Fine-Grained Token of the MCP server. + +You designate the token: + +- in the *id* parameter, with its identifier (returned by [`.generateFineGrainedToken()`](#generatefinegrainedtoken) and [`.listFineGrainedTokens()`](#listfinegrainedtokens)), +- or in the *tokenObj* parameter, with an object whose `token` property contains the token itself (`"4dfgt_..."`), for example to let the holder of a token revoke it. + +The token stops working at the next request, and the MCP sessions opened with it are closed. [Binary URLs](../WebServer/mcp-server.md#binary-attributes) already returned to the client remain valid until they expire (10 minutes at most). + +When the function is called in a web context (code executed for a web or REST request), it can only revoke a token whose privileges are all held by the current session. + +#### Example + +You revoke a token by its id: + +```4d +var $tokens:=ds.listFineGrainedTokens().query("name = :1"; "Claude Desktop - jsmith") +If ($tokens.length>0) + ds.revokeFineGrainedToken($tokens[0].id) +End if +``` + +#### See also + +[.generateFineGrainedToken()](#generatefinegrainedtoken)
[.listFineGrainedTokens()](#listfinegrainedtokens) + + + + +## .revokeOAuthGrant() + +
History + +|Release|Changes| +|---|---| +|21 R6|Added| + +
+ +**.revokeOAuthGrant**( *id* : Text ) + + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|id|Text|→|Identifier of the grant to revoke| +
+ + +#### Description + +The `.revokeOAuthGrant()` function revokes a grant given to a user through the OAuth mode of the MCP server (see [`.listOAuthGrants()`](#listoauthgrants)). + +The access tokens of the grant get an HTTP 401 status from the next request, its refresh token is refused, and its MCP sessions are closed. The user must log in again from the MCP client. + +When the function is called in a web context (code executed for a web or REST request), it can only revoke a grant whose privileges are all held by the current session. + +#### Example + +When you deactivate a user of your application, you revoke their OAuth grants: + +```4d +var $grant : Object +For each ($grant; ds.listOAuthGrants().query("userName = :1"; "jsmith")) + ds.revokeOAuthGrant($grant.id) +End for each +``` + +#### See also + +[.listOAuthGrants()](#listoauthgrants)
[.revokeFineGrainedToken()](#revokefinegrainedtoken) + + + ## .setAdminProtection() diff --git a/docs/API/MCPContextClass.md b/docs/API/MCPContextClass.md new file mode 100644 index 00000000000000..e01bb140705d38 --- /dev/null +++ b/docs/API/MCPContextClass.md @@ -0,0 +1,303 @@ +--- +id: MCPContextClass +title: MCPContext +--- + +The `MCPContext` class provides information about the current call of a tool of the [MCP server](../WebServer/mcp-server.md), and lets the tool ask the user for a confirmation or for values before running an action (see [Asking the user for confirmation](../WebServer/mcp-server.md#asking-the-user-for-confirmation)). + +
History + +|Release|Changes| +|---|---| +|21 R6|Class added| + +
+ +### MCPContext Object + +`MCPContext` objects are returned by the [`MCP`](../commands/mcp) command. + +The object is attached to the process while a [custom tool](../WebServer/mcp-server.md#custom-tools) function runs, and it is available in the methods and functions called by this function. Anywhere else (for example in a REST request or in a method run from the 4D environment), the object is inert: its functions do nothing and its properties are empty. + +### Summary + +|| +|---| +|[](#bound)
| +|[](#canelicit)
| +|[](#clientinfo)
| +|[](#error)
| +|[](#hasinput)
| +|[](#input)
| +|[](#requireinput)
| +|[](#toolname)
| + + + + +## .bound + +**.bound** : any + +#### Description + +The `.bound` property contains the *bind* value passed to `.requireInput()` when the input was asked, as verified by 4D. + +The value comes back signed with the user's answers, so the function can compare it with the current value and detect a change that occurred while the user was answering (for example, a modified entity). It is empty when the call does not carry verified answers. + +The *bind* value is signed, not encrypted: the client can read it. + +This property is **read-only**. + +#### Example + +You check that the entity was not modified while the user was confirming its deletion: + +```4d +If (MCP.bound#This.getStamp()) + MCP.error("The record was modified, please try again") + return +End if +``` + + + + + +## .canElicit + +**.canElicit** : Boolean + +#### Description + +The `.canElicit` property contains **True** if the MCP client can display input forms (it declared the `elicitation` capability in the request), and **False** otherwise or outside an MCP tool call. + +When `.canElicit` is **False**, [`.requireInput()`](#requireinput) asks nothing and the call returns the error "This action requires a confirmation your client cannot display". + +This property is **read-only**. + +#### Example + +You return a clear message when the client cannot display the confirmation: + +```4d +If (Not(MCP.canElicit)) + MCP.error("Please confirm this action from the application") + return +End if +``` + + + + + +## .clientInfo + +**.clientInfo** : Object + +#### Description + +The `.clientInfo` property contains information about the MCP client that sent the request, as provided in the metadata (`_meta`) of the request, for example its name and version. It is *Null* outside an MCP tool call. + +This property is **read-only**. + +#### Example + +You log the client that called the tool: + +```4d +var $client:=MCP.clientInfo +If ($client#Null) + LOG EVENT(Into 4D debug message; "MCP call from "+String($client.name)) +End if +``` + + + + + +## .error() + +**.error**( *message* : Text ) + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|message|Text|→|Error message returned to the client| +
+ + +#### Description + +The `.error()` function makes the current tool call return an error result with *message*. The result has `isError: true`, and the value returned by the function is ignored. + +`.error()` does not stop the execution of the function: call `return` after it if needed. + +Outside an MCP tool call, `.error()` does nothing. + +#### Example + +You refuse an amount that is too high: + +```4d +exposed MCP Function refund($amount : Real) : Text + If ($amount>1000) + MCP.error("Refunds over 1000 must be done by an accountant") + return + End if + // ... +``` + + + + + +## .hasInput() + +**.hasInput**( *name* : Text ) : Boolean + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|name|Text|→|Name of a field requested with `.requireInput()`| +|Result|Boolean|←|True if the user answered this field| +
+ + +#### Description + +The `.hasInput()` function returns **True** if the current call contains a verified answer of the user for the *name* field. + +The answer is verified when the client calls the tool again with the answers and a valid `requestState`: signed by 4D for the same token, tool, arguments, and fields, less than 10 minutes ago, and since the MCP server was last enabled. Otherwise, `.hasInput()` returns **False**. + +Outside an MCP tool call, `.hasInput()` returns **False**. + +#### Example + +You ask for a confirmation only if the user has not answered yet: + +```4d +If (Not(MCP.hasInput("confirm"))) + MCP.requireInput({confirm: {type: "boolean"; title: "Send the invoice to the customer"}}) + return +End if +``` + + + + + +## .input + +**.input** : Object + +#### Description + +The `.input` property contains the verified answers of the user, one property per field requested with `.requireInput()`. Only answers whose type matches the type of the requested field are kept. + +It does not contain any answer when the call does not carry verified answers, or outside an MCP tool call. + +This property is **read-only**. + +#### Example + +You use the comment entered by the user: + +```4d +If (MCP.hasInput("comment")) + This.closingComment:=MCP.input.comment +End if +``` + + + + + +## .requireInput() + +**.requireInput**( *fields* : Object {; *bind* : any} ) : Object + + +
+ +|Parameter|Type||Description| +|---|---|---|---| +|fields|Object|→|Message and fields to display to the user| +|bind|any|→|Value signed with the answers, returned in `.bound`| +|Result|Object|←|*Null* when the input is requested| +
+ + +#### Description + +The `.requireInput()` function asks the user, through the MCP client, to fill in a form before the tool continues. + +In *fields*, pass an object with: + +- an optional `message` property (Text): the text displayed to the user, +- one property per field to display, whose name is the field name and whose value is the JSON Schema of a `"boolean"`, `"string"`, `"number"`, or `"integer"` field (for example `{type: "boolean"; title: "Confirm"}`). A field is required unless its schema contains `required: False`. + +When the tool function returns, 4D answers the call with `resultType: "input_required"`, the form, and a `requestState` signed by 4D. The client displays the form, then calls the tool again with the answers. The function then runs again **from the top**: [`.hasInput()`](#hasinput) returns **True** for the answered fields and [`.input`](#input) contains the answers. If the answers are already there and *bind* has the same value as when the input was asked, `.requireInput()` does not ask again. + +In *bind*, you can pass a value to bind to the answers, such as the stamp of an entity: it is signed with the answers and returned in [`.bound`](#bound) when the client calls the tool again, so that you can check that nothing changed in the meantime. If *bind* changed, the input is asked again. + +If the client cannot display forms (see [`.canElicit`](#canelicit)), `.requireInput()` asks nothing and the call returns the error "This action requires a confirmation your client cannot display". + +Outside an MCP tool call, `.requireInput()` asks nothing and returns *Null*. + +:::caution + +Do not ask for secrets such as passwords with `.requireInput()`: the answers go through the AI client. + +::: + +#### Example + +You ask the user to confirm the closing of a ticket and to enter an optional comment: + +```4d +// cs.TicketEntity class +Class extends Entity + +exposed MCP Function close() : Text + If (Not(MCP.hasInput("confirm"))) + MCP.requireInput({message: "Close ticket "+String(This.ID)+"?"; confirm: {type: "boolean"; title: "Close"}; comment: {type: "string"; title: "Comment"; required: False}}; This.getStamp()) + return + End if + If (MCP.input.confirm) + This.status:="closed" + This.comment:=String(MCP.input.comment) + This.save() + End if + return This.status +``` + + + + + +## .toolName + +**.toolName** : Text + +#### Description + +The `.toolName` property contains the name of the MCP tool being called, for example `"OrderManager-getYearTotal"`. It is an empty string outside an MCP tool call. + +This property is **read-only**. + +#### Example + +You run a method only when it is called by an MCP tool: + +```4d +If (MCP.toolName#"") + // called from an MCP tool +End if +``` + + diff --git a/docs/API/QuotaManagerClass.md b/docs/API/QuotaManagerClass.md index 390bd7eb971b1d..6a06dc0901acd4 100644 --- a/docs/API/QuotaManagerClass.md +++ b/docs/API/QuotaManagerClass.md @@ -12,6 +12,12 @@ The `4D.QuotaManager` class provides you with an interface to configure and moni ::: +:::tip Related Blog post + +[A 4D web server that knows when to say No](https://blog.4d.com/a-4d-web-server-that-knows-when-to-say-no/) + +::: + `4D.QuotaManager` objects can be instantiated by: - the [`quotas` property of a Session](./SessionClass.md#quotas) object - the [`quotas` property of a Web server](./WebServerClass.md#quotas) object diff --git a/docs/API/SessionClass.md b/docs/API/SessionClass.md index 9f836fecc8a478..a6ebf584171a94 100644 --- a/docs/API/SessionClass.md +++ b/docs/API/SessionClass.md @@ -23,7 +23,7 @@ Session objects are returned by the [`Session`](../commands/session) command. Th The following types of sessions are supported by this class: -- [**Web user sessions**](WebServer/sessions.md): Web user sessions are available when [scalable sessions are enabled in your project](WebServer/sessions.md#enabling-web-sessions). They are used for Web connections (including REST access), and are controlled by assigned [privileges](../ORDA/privileges.md). +- [**Web user sessions**](../WebServer/sessions.md): Web user sessions are available when [scalable sessions are enabled in your project](../WebServer/sessions.md#enabling-web-sessions). They are used for Web connections (including REST access and [MCP server](../WebServer/mcp-server.md) access), and are controlled by assigned [privileges](../ORDA/privileges.md). - [**Remote user sessions**](../Desktop/sessions.md#remote-user-sessions): In client/server applications, remote users have their own sessions, managed from the client and from the server. - [**Stored procedures sessions**](../Desktop/sessions.md#stored-procedure-sessions): Virtual user session for all stored procedures executed on the server. - [**Standalone sessions**](../Desktop/sessions.md#standalone-sessions): Local session object returned in single-user application (useful in development and test phases of client/server applications). @@ -535,6 +535,7 @@ End if |Release|Changes| |---|---| +|21 R6|New "mcp" session type| |21 R4|New *unreachableSince* property| |20 R5|Added| @@ -556,7 +557,7 @@ The `.info` object contains the following properties: |Property|Type|Description| |---|---|---| -|type|Text|Session type: "remote", "storedProcedure", "standalone", "rest", "web"| +|type|Text|Session type: "remote", "storedProcedure", "standalone", "rest", "web", "mcp" (session of the [MCP server](../WebServer/mcp-server.md#mcp-sessions))| |userName|Text|4D user name (same value as [`.userName`](#username))| |machineName|Text|| |systemUserName|Text|
@@ -775,7 +834,9 @@ You can configure quotas via the `quotas` property in the *settings* parameter o ::: -Customized session settings will be reset when the [`.stop()`](#stop) function is called. +You can configure the [MCP server](../WebServer/mcp-server.md) via the [`mcp`](#mcp) property in the *settings* parameter. + +Customized session settings will be reset when the [`.stop()`](#stop) function is called, except the `mcp` settings, which are kept. #### Returned object @@ -812,6 +873,15 @@ The following example starts the web server with customized settings: End if ``` +#### Example 2 + +The following example starts the web server with the MCP server enabled: + +```4d +var $webServer:=WEB Server +var $result:=$webServer.start({mcp: {enabled: True; instructions: "Use describeModel to learn the data model."}}) +``` + diff --git a/docs/Concepts/classes.md b/docs/Concepts/classes.md index adec7f24ac37aa..8677d6a7c92305 100644 --- a/docs/Concepts/classes.md +++ b/docs/Concepts/classes.md @@ -167,6 +167,8 @@ If the function is declared in a [shared class](#shared-classes), you can use th In the context of a client/server application, the `local` or `server` keyword allows you to specify on which machine the function must be executed. These keywords can only be used with ORDA data model functions and shared/session singleton functions. For more information, refer to the [local and server functions](#local-and-server) paragraph below. +In ORDA data model classes and singleton classes, the [`exposed`](../ORDA/ordaClasses.md#exposed-vs-non-exposed-functions) keyword allows a function to be called by REST requests, and the `exposed MCP Function` declaration publishes the function as a tool of the [MCP server](../WebServer/mcp-server.md). The `MCP` keyword is supported in the DataStore class, DataClass and Entity classes, and shared singleton classes. A function declared with `MCP` but without `exposed` is not published. For more information, refer to [`exposed MCP Function`](../ORDA/ordaClasses.md#exposed-mcp-function). + The function name must be compliant with [object naming rules](Concepts/identifiers.md#object-properties). @@ -611,6 +613,252 @@ Class constructor ($side : Integer) ``` +## Function comments + +You can document a class function or a class constructor with comment lines written right above its `Function` or `Class constructor` declaration. 4D reads this comment block and shows it in the code assistance of the [4D code editor](../code-editor/write-class-method.md#help-tips) and of VS Code (completion details, help tips, and signature help), together with the function signature. The same comments also provide the [MCP tool metadata](#mcp-tool-metadata) of the function. + +The comment block follows these rules: + +- It is made of `//` lines and/or a `/* */` block. Each line of a `/* */` block is handled like a `//` line, and the `/*` and `*/` markers are not displayed. +- It must be placed immediately above the declaration. A blank line between the comment block and the declaration breaks the association: only the signature is displayed. +- Each comment block is associated only with the next declaration, even when it is written right after the code of the previous function. +- Only the saved code is read: after you edit a comment, the code assistance shows the new text once the class is saved. +- The text is displayed as plain text: Markdown markers such as `**` or `*` are shown as written. + +Each line of the block is interpreted according to its beginning: + +|Line|Meaning| +|---|---| +|`// `|Description of the function. Several description lines are combined in order, with their line breaks. Empty `//` lines at the start or at the end of the block are ignored.| +|`// $name: `|Description of the *$name* parameter.| +|`// {$name}: `|Description of the *$name* parameter, marked as optional for MCP.| +|`// ...: `|Description of the [variadic parameters](parameters.md#declaring-variadic-parameters) (`... : Type`).| +|`// param: $name `, `// param: {$name} `, `// param: ... `|Same as `$name:`, `{$name}:`, and `...:` lines.| +|`// MCP: `|Description of the function for MCP only. Several `MCP:` description lines are combined in order.| +|`// MCP: @tag {@tag}` or `// @tag {@tag}`|MCP behavior tags (see [MCP tool metadata](#mcp-tool-metadata)). The line must contain only supported tags, otherwise it is a description line.| + +A `$name:` or `{$name}:` line is a parameter description only if *$name* is a parameter of the function signature. Otherwise, it is a description line (for example `// $120: price in dollars`). A `...:` line is a parameter description only if the function has variadic parameters. + +The code assistance displays the description lines, then a blank line, then the parameter lines as written. `MCP:` lines are never displayed in the code assistance. + +When you [compile](../Project/compiler.md) the project, the compiler reports a [warning](../Project/compiler.md#warnings-on-function-comments) for each parameter of the signature that has no `$name:` or `{$name}:` line in the comment block, and for contradictory MCP behavior tags. Functions without a comment block are not checked. + +:::note + +Comment blocks are supported in project classes (including shared and singleton classes) and in component classes. For compiled components, the descriptions are provided by the [syntax file](../Extensions/develop-components.md#code-completion-for-compiled-components). + +::: + +#### Example 1 + +You want to document a function and its parameter so that they are displayed in the code editor: + +```4d +// Class: Invoice + +// Returns the price with taxes +// The rate is a percentage +// $rate: tax rate to apply (20 for 20%) +Function priceWithTaxes($rate : Real) : Real + return This.price*(1+($rate/100)) +``` + +When you type `$invoice.priceWithTaxes(` in a method, the help displays the signature with: + +``` +Returns the price with taxes +The rate is a percentage + +$rate: tax rate to apply (20 for 20%) +``` + +#### Example 2 + +You want to document a class constructor with a `/* */` block: + +```4d +// Class: Counter + +/* +Creates a counter starting at a value +$start: initial value of the counter +*/ +Class constructor($start : Integer) + This.value:=$start +``` + +The description and the `$start:` line are displayed when you type `cs.Counter.new(`. + +### MCP tool metadata + +The comment blocks of `exposed MCP Function` declarations also describe these functions as MCP tools. When the project is compiled, 4D generates the `Project/DerivedData/syntaxMCP.json` file, which contains the metadata of these tools in a `toolList` array. + +Only functions of the following classes are listed: + +- the DataStore class, +- DataClass and Entity classes, +- singleton classes. + +Functions of EntitySelection classes and of other classes, as well as functions that are not declared `exposed MCP Function`, are not listed, even if their comment block contains `MCP:` lines. + +:::note + +If a `Resources/syntaxMCP.json` file exists in the project, it is used instead of the generated file. The compiler never overwrites it. See [`Resources` folder](../Project/architecture.md#resources). + +::: + +The [MCP server](../WebServer/mcp-server.md) of 4D builds its tool catalog from the same comment blocks and the same type conversions, using the running code: in interpreted mode, a function you add or modify is published at the next `tools/list` request, without restarting. The catalog of the MCP server also adds the elements needed to call the tools, such as a `key` argument for Entity class functions and `"additionalProperties": false` in `inputSchema` (see [Tool catalog](../WebServer/mcp-server.md#tool-catalog)). The following functions are not published, and 4D logs a message: + +- a function whose tool name is longer than 64 characters, contains characters other than letters, digits, `_` and `-`, or is the name of another tool (including a built-in CRUD tool), +- an Entity class function that declares a `$key` parameter, +- a function that declares both a `$args` parameter and variadic parameters. + +A function without description is published, and 4D logs a warning. + +Each tool of the `toolList` array is an object with the following properties: + +|Property|Description| +|---|---| +|`name`|Name of the tool: the function name for a DataStore class function, `ClassName-functionName` for other classes| +|`description`|Text of the `MCP:` description lines, or the description lines if there is no `MCP:` description. Omitted if there is no description| +|`inputSchema`|`{"type": "object", "properties": {...}, "required": [...]}`: one property per parameter of the signature, named without the `$`, with the parameter comment as `description`| +|`outputSchema`|Schema of the return type. Omitted if the function returns nothing or a Variant| +|`annotations`|Behavior hints derived from the `MCP:` behavior tags| + +In `inputSchema`: + +- every parameter is listed in `required`, except those documented with a `{$name}:` line. `required` is omitted if it is empty. +- typed variadic parameters (`... : Type`) are represented by an optional `args` property of type `array`, whose `items` have the schema of *Type*. The `...:` line is its description. + +Parameter and return types are converted to JSON Schema as follows: + +|4D type|JSON Schema| +|---|---| +|Text|`{"type": "string"}`| +|Integer|`{"type": "integer"}`| +|Real|`{"type": "number"}`| +|Boolean|`{"type": "boolean"}`| +|Date|`{"type": "string", "format": "date"}`| +|Time|`{"type": "integer", "description": "duration in seconds"}`| +|Object, class instance|`{"type": "object"}`| +|Collection|`{"type": "array"}`| +|Blob, 4D.Blob, Picture|`{"type": "string", "contentEncoding": "base64"}`| +|Variant, or no type|`{}`| + +The supported behavior tags are converted to annotations as follows: + +|Tag|Annotation| +|---|---| +|`@readOnly`|`"readOnlyHint": true`| +|`@destructive`|`"destructiveHint": true`| +|`@additive`|`"destructiveHint": false`| +|`@idempotent`|`"idempotentHint": true`| +|`@openWorld`|`"openWorldHint": true`| + +`openWorldHint` is always present: it is `false` if `@openWorld` is not used. Other hints are omitted when their tag is not used. `@readOnly`, `@destructive`, and `@additive` contradict each other: if a function uses two or more of them, the compiler reports a warning and the corresponding hints are omitted. Unknown tags are ignored. + +#### Example 3 + +You document the MCP tools of a `DateTime` singleton class: + +```4d +// Class: DateTime + +singleton Class constructor() + This.date:=Current date + +// Adds a number of days to the date +// MCP: Add days to the date-time +// $days: number of days to add (negative to subtract) +exposed MCP Function addDays($days : Integer) : Date + This.date:=Add to date(This.date; 0; 0; $days) + return This.date + +// Adds zero or more day offsets to the date and returns the updated date +// MCP: Add day offsets to the date-time +// MCP: @idempotent +// ...: day offsets to add (negative to subtract) +exposed MCP Function addDayOffsets(... : Integer) : Date + var $offsetIndex; $totalDays : Integer + For ($offsetIndex; 1; Count parameters) + $totalDays+=${$offsetIndex} + End for + This.date:=Add to date(This.date; 0; 0; $totalDays) + return This.date +``` + +After compilation, `Project/DerivedData/syntaxMCP.json` contains: + +```json +{ + "toolList": [ + { + "name": "DateTime-addDays", + "description": "Add days to the date-time", + "inputSchema": { + "type": "object", + "properties": { + "days": { "type": "integer", "description": "number of days to add (negative to subtract)" } + }, + "required": ["days"] + }, + "outputSchema": { "type": "string", "format": "date" }, + "annotations": { "openWorldHint": false } + }, + { + "name": "DateTime-addDayOffsets", + "description": "Add day offsets to the date-time", + "inputSchema": { + "type": "object", + "properties": { + "args": { + "type": "array", + "items": { "type": "integer" }, + "description": "day offsets to add (negative to subtract)" + } + } + }, + "outputSchema": { "type": "string", "format": "date" }, + "annotations": { "idempotentHint": true, "openWorldHint": false } + } + ] +} +``` + +#### Example 4 + +You want to read the names of the MCP tools generated by the last compilation: + +```4d +var $file : 4D.File:=File("/PACKAGE/Project/DerivedData/syntaxMCP.json") +var $metadata : Object:=JSON Parse($file.getText()) +var $names : Collection:=$metadata.toolList.extract("name") +// $names is ["DateTime-addDays";"DateTime-addDayOffsets"] +``` + +#### Example 5 + +You document a tool with `param:` lines and a behavior tag line without the `MCP:` prefix: + +```4d +// Class: Stock + +shared singleton Class constructor() + +// Returns the quantity in stock of a product +// param: $reference reference of the product +// param: {$warehouse} code of the warehouse (all warehouses if omitted) +// @readOnly +exposed MCP Function getQuantity($reference : Text; $warehouse : Text) : Integer + If ($warehouse="") + return ds.Stock.query("reference = :1"; $reference).sum("quantity") + End if + return ds.Stock.query("reference = :1 and warehouse = :2"; $reference; $warehouse).sum("quantity") +``` + +The `Stock-getQuantity` tool has a required `reference` property, an optional `warehouse` property, and the `"readOnlyHint": true` annotation. + + ## Class function commands The following commands have specific features when they are used within class functions: diff --git a/docs/Concepts/error-handling.md b/docs/Concepts/error-handling.md index 28a3eab54aa2d1..6a464300c30f3c 100644 --- a/docs/Concepts/error-handling.md +++ b/docs/Concepts/error-handling.md @@ -101,7 +101,7 @@ Within a custom error method, you have access to several pieces of information t ::: - the [`Last errors`](../commands/last-errors) command that returns a collection of the current stack of errors that occurred in the 4D application. -- the `Call chain` command that returns a collection of objects describing each step of the method call chain within the current process. +- the [`Call chain`](../commands/call-chain) command that returns a collection of objects describing each step of the method call chain within the current process. #### Example diff --git a/docs/Develop-legacy/field-properties-legacy.md b/docs/Develop-legacy/field-properties-legacy.md index 2b76e0ec94099e..b02165c5c4c32e 100644 --- a/docs/Develop-legacy/field-properties-legacy.md +++ b/docs/Develop-legacy/field-properties-legacy.md @@ -103,7 +103,7 @@ $myTextVar:=[myTable]myTextField The **Autoincrement** property generates sequence numbers in the table. It can be used with fields of the [Integer, Long Integer and Integer 64 bits types](../Concepts/data-types.md). -A field with this property is automatically incremented each time a record is created in the table. The sequence number assigned to the field matches that of the "internal counter" of the table, maintained by 4D. This internal counter can also be accessed using 4D commands [`Sequence number`](../commands/sequence-number) and [`Get database parameter`](../commands/get-database-parameter) and using the `#N` marker (see Default values). +A field with this property is automatically incremented each time a record is created in the table. The sequence number assigned to the field matches that of the "internal counter" of the table, maintained by 4D. This internal counter can also be accessed using 4D commands [`Sequence number`](../commands/sequence-number) and [`Get database parameter`](../commands/get-database-parameter) and using the `#N` marker (see [**Default value**](../FormObjects/properties_RangeOfValues.md#default-value). The numbers assigned are never reused in the table, even when records are deleted. Numbers generated during a transaction that is cancelled are "lost”. The Autoincrement property corresponds to the SQL AUTO_INCREMENT attribute and can be specified using this language. The AUTO INCREMENT label also appears in the SQL information area of the [Inspector](../Develop/structure-editor.md#inspector-palette) for fields having this attribute. diff --git a/docs/Develop/structure-indexes.md b/docs/Develop/structure-indexes.md index 76b60f05baf53c..805f5f5e3add57 100644 --- a/docs/Develop/structure-indexes.md +++ b/docs/Develop/structure-indexes.md @@ -154,7 +154,7 @@ To add a field to the index, click on the **[+]** button. The list of fields of - If you want to create a composite index, add each field to be included in the index successively. Once the list is completed, you can reorder the fields using the arrow buttons or using drag and drop. - If you create a composite index based on primary key fields, make sure you put the fields in the same order in the primary key and in the index. -- If you have chosen the “Keyword Index” type, only Alpha or Text fields can be selected. Also in this case, you cannot include only one field in the index. +- If you have chosen the “Keyword Index” type, only Alpha, Text, or Picture fields can be selected. Also in this case, you can include only one field in the index. To delete a field from the index, select it in the list and click on the **[-]** button. diff --git a/docs/Extensions/develop-components.md b/docs/Extensions/develop-components.md index 587072106a1038..dc98472830c018 100644 --- a/docs/Extensions/develop-components.md +++ b/docs/Extensions/develop-components.md @@ -278,6 +278,20 @@ A syntax file (JSON format) is then automatically created during the compilation If you don't enter a [component namespace](#declaring-the-component-namespace), the resources for the classes and exposed methods are not generated even if the syntax file option is checked. +When your class functions and class constructors are documented with a [comment block above their declaration](../Concepts/classes.md#function-comments), the syntax file also contains their description and parameter comments (`MCP:` lines are never included). Host projects then display them as plain text in the code completion and help of the compiled component. For example, with the following function in a component class: + +```4d +// Class: Tools + +// Scales a value by a factor +// $value: value to scale +// $factor: multiplier to apply +Function scale($value : Real; $factor : Real) : Real + return $value*$factor +``` + +a host project that types `cs.MyComponent.Tools.new().scale(` sees "Scales a value by a factor" and the `$value:` and `$factor:` lines below the signature. + ## Passing variables Variables are not shared between components and host projects. The only way to modify component variables from the host project and vice versa is using pointers. diff --git a/docs/FormEditor/createStylesheet.md b/docs/FormEditor/createStylesheet.md index 410f843279e77f..9dc45b91b7698e 100644 --- a/docs/FormEditor/createStylesheet.md +++ b/docs/FormEditor/createStylesheet.md @@ -313,6 +313,7 @@ The attributes listed below are able to accept either the 4D name or the CSS nam |4D|CSS| |---|---| |`borderStyle`|`border-style`| +|`borderColor`|`border-color`| |`fill`|`background-color`| |`fontFamily`|`font-family`| |`fontSize`|`font-size`| diff --git a/docs/FormEditor/properties_FormProperties.md b/docs/FormEditor/properties_FormProperties.md index a6b0b1b4d0df13..60a3c9755af01d 100644 --- a/docs/FormEditor/properties_FormProperties.md +++ b/docs/FormEditor/properties_FormProperties.md @@ -36,7 +36,7 @@ A CSS file defined at the form level will override default style sheet(s). For m |Name|Data Type|Possible Values| |---|---|---| -|css |string or collection |CSS file path(s) provided as:
  • a string (a file for both platforms)
  • a collection of strings (a list of files for both platform)
  • a collection of {"path":string;"media":"mac" | "win"} objects
  • | +|css |string or collection |CSS file path(s) provided as:
  • a string (a file for both platforms)
  • a collection of strings (a list of files for both platform)
  • a collection of {"path":string;"media":"mac" | "windows"} objects
  • | --- diff --git a/docs/FormObjects/buttonGrid_overview.md b/docs/FormObjects/buttonGrid_overview.md index 12c577ba308e3b..e4f6ea53625aa4 100644 --- a/docs/FormObjects/buttonGrid_overview.md +++ b/docs/FormObjects/buttonGrid_overview.md @@ -31,7 +31,7 @@ You can assign the `gotoPage` [standard action](/Desktop/standard-actions) to a ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Columns](properties_Crop.md#columns) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Rows](properties_Crop.md#rows) - [Standard action](properties_Action.md#standard-action) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Width](properties_CoordinatesAndSizing.md#width) - [Visibility](properties_Display.md#visibility) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Columns](properties_Crop.md#columns) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Rows](properties_Crop.md#rows) - [Standard action](properties_Action.md#standard-action) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Width](properties_CoordinatesAndSizing.md#width) - [Visibility](properties_Display.md#visibility) ## Supported Events diff --git a/docs/FormObjects/button_overview.md b/docs/FormObjects/button_overview.md index 5440d09ed7910c..2b09e9f079f84b 100644 --- a/docs/FormObjects/button_overview.md +++ b/docs/FormObjects/button_overview.md @@ -328,11 +328,12 @@ On Windows Classic UI theme, this style is not supported. The Custom button style accepts a personalized background picture and allows managing [additional properties](#additional-properties-for-custom-buttons) such as [icon offset](properties_TextAndPicture.md#icon-offset) and [margins](properties_TextAndPicture.md#horizontal-margin). + +#### JSON Example: ![](../assets/en/FormObjects/button_custom.png) - -#### JSON Example: + ```code "myButton": { @@ -361,7 +362,6 @@ The Custom button style accepts a personalized background picture and allows man - ## Supported Properties All buttons share the same set of basic properties: diff --git a/docs/FormObjects/dropdownList_Overview.md b/docs/FormObjects/dropdownList_Overview.md index 2c45f2ee6da3f2..f6615afaf6abfb 100644 --- a/docs/FormObjects/dropdownList_Overview.md +++ b/docs/FormObjects/dropdownList_Overview.md @@ -166,7 +166,7 @@ At runtime the drop-down list will display an automatic list of values, e.g. bac ## Supported Properties -[Alpha Format](properties_Display.md#alpha-format) - [Bold](properties_Text.md#bold) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Button Style](properties_TextAndPicture.md#button-style) - [Choice List](properties_DataSource.md#choice-list) - [Class](properties_Object.md#css-class) - [Data Type (expression type)](properties_DataSource.md#data-type-expression-type) - [Data Type (list)](properties_DataSource.md#data-type-list) - [Date Format](properties_Display.md#date-format) - [Expression Type](properties_Object.md#expression-type) - [Focusable](properties_Entry.md#focusable) - [Font](properties_Text.md#font) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Alignment](properties_Text.md#horizontal-alignment) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Italic](properties_Text.md#italic) - [Left](properties_CoordinatesAndSizing.md#left) - [Not rendered](properties_Display.md#not-rendered) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Standard action](properties_Action.md#standard-action) - [Save value](properties_Object.md#save-value) - [Time Format](properties_Display.md#time-format) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Underline](properties_Text.md#underline) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Alpha Format](properties_Display.md#alpha-format) - [Bold](properties_Text.md#bold) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Choice List](properties_DataSource.md#choice-list) - [Class](properties_Object.md#css-class) - [Data Type (expression type)](properties_DataSource.md#data-type-expression-type) - [Data Type (list)](properties_DataSource.md#data-type-list) - [Date Format](properties_Display.md#date-format) - [Expression Type](properties_Object.md#expression-type) - [Focusable](properties_Entry.md#focusable) - [Font](properties_Text.md#font) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Alignment](properties_Text.md#horizontal-alignment) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Italic](properties_Text.md#italic) - [Left](properties_CoordinatesAndSizing.md#left) - [Not rendered](properties_Display.md#not-rendered) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Standard action](properties_Action.md#standard-action) - [Save value](properties_Object.md#save-value) - [Time Format](properties_Display.md#time-format) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Underline](properties_Text.md#underline) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/list_overview.md b/docs/FormObjects/list_overview.md index afff2babd0d260..33e9d08b61cfa2 100644 --- a/docs/FormObjects/list_overview.md +++ b/docs/FormObjects/list_overview.md @@ -155,7 +155,7 @@ You can control whether hierarchical list items can be modified by the user by u ## Supported Properties -[Bold](properties_Text.md#bold) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Choice List](properties_DataSource.md#choice-list) - [Class](properties_Object.md#css-class) - [Draggable](properties_Action.md#draggable) - [Droppable](properties_Action.md#droppable) - [Enterable](properties_Entry.md#enterable) - [Entry Filter](properties_Entry.md#entry-filter) - [Fill Color](properties_BackgroundAndBorder.md#background-color--fill-color) - [Focusable](properties_Entry.md#focusable) - [Font](properties_Text.md#font) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Hide focus rectangle](properties_Appearance.md#hide-focus-rectangle) - [Horizontal Scroll Bar](properties_Appearance.md#horizontal-scroll-bar) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Italic](properties_Text.md#italic) - [Left](properties_CoordinatesAndSizing.md#left) - [Multi-selectable](properties_Action.md#multi-selectable) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Underline](properties_Text.md#underline) - [Vertical Scroll Bar](properties_Appearance.md#vertical-scroll-bar) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Bold](properties_Text.md#bold) - [Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Choice List](properties_DataSource.md#choice-list) - [Class](properties_Object.md#css-class) - [Draggable](properties_Action.md#draggable) - [Droppable](properties_Action.md#droppable) - [Enterable](properties_Entry.md#enterable) - [Entry Filter](properties_Entry.md#entry-filter) - [Fill Color](properties_BackgroundAndBorder.md#background-color--fill-color) - [Focusable](properties_Entry.md#focusable) - [Font](properties_Text.md#font) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Hide focus rectangle](properties_Appearance.md#hide-focus-rectangle) - [Horizontal Scroll Bar](properties_Appearance.md#horizontal-scroll-bar) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Italic](properties_Text.md#italic) - [Left](properties_CoordinatesAndSizing.md#left) - [Multi-selectable](properties_Action.md#multi-selectable) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Underline](properties_Text.md#underline) - [Vertical Scroll Bar](properties_Appearance.md#vertical-scroll-bar) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/listbox-object.md b/docs/FormObjects/listbox-object.md index e11959c4339bd9..e3eb7dadb901ed 100644 --- a/docs/FormObjects/listbox-object.md +++ b/docs/FormObjects/listbox-object.md @@ -71,6 +71,7 @@ Supported properties depend on the list box type. |[Background Color](properties_BackgroundAndBorder.md#background-color--fill-color)|X|X|X| |[Bold](properties_Text.md#bold)|X|X|X| |[Background Color Expression](properties_BackgroundAndBorder.md#background-color-expression)||X|X| +|[Border color](./properties_BackgroundAndBorder.md#border-color)|X|X|X| |[Border Line Style](properties_BackgroundAndBorder.md#border-line-style)|X|X|X| |[Bottom](properties_CoordinatesAndSizing.md#bottom)|X|X|X| |[Class](properties_Object.md#css-class)|X|X|X| diff --git a/docs/FormObjects/pictureButton_overview.md b/docs/FormObjects/pictureButton_overview.md index 8004697d0cab30..28000d25b024e7 100644 --- a/docs/FormObjects/pictureButton_overview.md +++ b/docs/FormObjects/pictureButton_overview.md @@ -63,7 +63,7 @@ The following other modes are available: ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Button Style](properties_TextAndPicture.md#button-style) - [Class](properties_Object.md#css-class) - [Columns](properties_Crop.md#columns) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Italic](properties_Text.md#italic) - [Left](properties_CoordinatesAndSizing.md#left) - [Loop back to first frame](properties_Animation.md#loop-back-to-first-frame) - [Object Name](properties_Object.md#object-name) - [Pathname](properties_Picture.md#pathname) - [Right](properties_CoordinatesAndSizing.md#right) - [Rows](properties_Crop.md#rows) - [Shortcut](properties_Entry.md#shortcut) - [Standard action](properties_Action.md#standard-action) - [Switch back when released](properties_Animation.md#switch-back-when-released) - [Switch continuously on clicks](properties_Animation.md#switch-continuously-on-clicks) - [Switch every x seconds](properties_Animation.md#switch-every-x-seconds) - [Title](properties_Object.md#title) - [Switch when roll over](properties_Animation.md#switch-when-roll-over) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Use Last frame as disabled](properties_Animation.md#use-last-frame-as-disabled) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Button Style](properties_TextAndPicture.md#button-style) - [Class](properties_Object.md#css-class) - [Columns](properties_Crop.md#columns) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Italic](properties_Text.md#italic) - [Left](properties_CoordinatesAndSizing.md#left) - [Loop back to first frame](properties_Animation.md#loop-back-to-first-frame) - [Object Name](properties_Object.md#object-name) - [Pathname](properties_Picture.md#pathname) - [Right](properties_CoordinatesAndSizing.md#right) - [Rows](properties_Crop.md#rows) - [Shortcut](properties_Entry.md#shortcut) - [Standard action](properties_Action.md#standard-action) - [Switch back when released](properties_Animation.md#switch-back-when-released) - [Switch continuously on clicks](properties_Animation.md#switch-continuously-on-clicks) - [Switch every x seconds](properties_Animation.md#switch-every-x-seconds) - [Title](properties_Object.md#title) - [Switch when roll over](properties_Animation.md#switch-when-roll-over) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Use Last frame as disabled](properties_Animation.md#use-last-frame-as-disabled) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/picturePopupMenu_overview.md b/docs/FormObjects/picturePopupMenu_overview.md index 5fa05080297ffd..de2ad89425fe23 100644 --- a/docs/FormObjects/picturePopupMenu_overview.md +++ b/docs/FormObjects/picturePopupMenu_overview.md @@ -29,7 +29,7 @@ If you want to manage the effect of a click yourself, select `No action`. ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) -[Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Columns](properties_Crop.md#columns) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Object Name](properties_Object.md#object-name) - [Pathname](properties_Picture.md#pathname) - [Right](properties_CoordinatesAndSizing.md#right) - [Rows](properties_Crop.md#rows)- [Standard action](properties_Action.md#standard-action) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) -[Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Columns](properties_Crop.md#columns) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Object Name](properties_Object.md#object-name) - [Pathname](properties_Picture.md#pathname) - [Right](properties_CoordinatesAndSizing.md#right) - [Rows](properties_Crop.md#rows)- [Standard action](properties_Action.md#standard-action) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/pluginArea_overview.md b/docs/FormObjects/pluginArea_overview.md index f0deebf716ce16..5e8c4b528d52ec 100644 --- a/docs/FormObjects/pluginArea_overview.md +++ b/docs/FormObjects/pluginArea_overview.md @@ -22,7 +22,7 @@ If advanced options are provided by the author of the plug-in, a **Plug-in** the ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Advanced Properties](properties_Plugins.md) - [Class](properties_Object.md#css-class) - [Draggable](properties_Action.md#draggable) - [Droppable](properties_Action.md#droppable) - [Expression Type](properties_Object.md#expression-type) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Plug-in Kind](properties_Object.md#plug-in-kind) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibilty](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Advanced Properties](properties_Plugins.md) - [Class](properties_Object.md#css-class) - [Draggable](properties_Action.md#draggable) - [Droppable](properties_Action.md#droppable) - [Expression Type](properties_Object.md#expression-type) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Plug-in Kind](properties_Object.md#plug-in-kind) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibilty](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/progressIndicator.md b/docs/FormObjects/progressIndicator.md index b47f12c88f6723..f7222b2a2db8d1 100644 --- a/docs/FormObjects/progressIndicator.md +++ b/docs/FormObjects/progressIndicator.md @@ -41,7 +41,7 @@ Multiple graphical options are available: minimum/maximum values, graduations, s ### Supported Properties -[Barber shop](properties_Scale.md#barber-shop) - [Bold](properties_Text.md#bold) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) -[Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Display graduation](properties_Scale.md#display-graduation) - [Enterable](properties_Entry.md#enterable) - [Execute object method](properties_Action.md#execute-object-method) - [Expression Type](properties_Object.md#expression-type) (only "integer", "number", "date", or "time") - [Font](properties_Text.md#font) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Height](properties_CoordinatesAndSizing.md#height) - [Italic](properties_Text.md#italic) - [Graduation step](properties_Scale.md#graduation-step) -[Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Label Location](properties_Scale.md#label-location) - [Left](properties_CoordinatesAndSizing.md#left) - [Maximum](properties_Scale.md#maximum) - [Minimum](properties_Scale.md#minimum) - [Number Format](properties_Display.md#number-format) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Step](properties_Scale.md#step) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Underline](properties_Text.md#underline) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Barber shop](properties_Scale.md#barber-shop) - [Bold](properties_Text.md#bold) - [Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) -[Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Display graduation](properties_Scale.md#display-graduation) - [Enterable](properties_Entry.md#enterable) - [Execute object method](properties_Action.md#execute-object-method) - [Expression Type](properties_Object.md#expression-type) (only "integer", "number", "date", or "time") - [Font](properties_Text.md#font) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Height](properties_CoordinatesAndSizing.md#height) - [Italic](properties_Text.md#italic) - [Graduation step](properties_Scale.md#graduation-step) -[Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Label Location](properties_Scale.md#label-location) - [Left](properties_CoordinatesAndSizing.md#left) - [Maximum](properties_Scale.md#maximum) - [Minimum](properties_Scale.md#minimum) - [Number Format](properties_Display.md#number-format) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Step](properties_Scale.md#step) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Underline](properties_Text.md#underline) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ### Supported Events diff --git a/docs/FormObjects/properties_Action.md b/docs/FormObjects/properties_Action.md index cab91ee3ac96c8..70ad97f30e1797 100644 --- a/docs/FormObjects/properties_Action.md +++ b/docs/FormObjects/properties_Action.md @@ -24,7 +24,7 @@ For more information, refer to the [Drag and Drop](../Desktop/drag-and-drop.md) |Name|Data Type|Possible Values| |---|---|---| -|dragging|text |"none" (default), "custom", "automatic" (excluding list box)| +|dragging|text |"none" (default), "custom" (excluding plug-in area), "automatic" (excluding button and list box)| #### Objects Supported @@ -60,7 +60,7 @@ For more information, refer to the [Drag and Drop](../Desktop/drag-and-drop.md) |Name|Data Type|Possible Values| |---|---|---| -|dropping|text |"none" (default), "custom", "automatic" (excluding list box)| +|dropping|text |"none" (default), "custom" (excluding plug-in area), "automatic" (excluding button and list box)| #### Objects Supported diff --git a/docs/FormObjects/properties_Appearance.md b/docs/FormObjects/properties_Appearance.md index cd1756da32195c..cfaf49d9b9130e 100644 --- a/docs/FormObjects/properties_Appearance.md +++ b/docs/FormObjects/properties_Appearance.md @@ -30,7 +30,28 @@ defaultButton|boolean|true, false | [Custom Button](button_overview.md#custom) - [Regular Button](button_overview.md#regular) - [Flat Button](button_overview.md#regular) ---- + + +## Display formula source as symbol + +Displays source text of formulas as symbols when expressions are shown as references. + +#### JSON Grammar + +|Name|Data Type|Possible Values| +|---|---|---| +displayFormulaAsSymbol|boolean|true (default), false| + +#### Objects Supported + +[4D Write Pro area](writeProArea_overview.md) + +#### Commands + +[WP Get view properties](../WritePro/commands-legacy/wp-get-view-properties.md) - [WP SET VIEW PROPERTIES](../WritePro/commands-legacy/wp-set-view-properties.md) + + + ## Hide focus rectangle @@ -146,8 +167,8 @@ dpi|number|0=automatic, 72, 96 | --- -## Show background - +## Show background and anchored elements + Displays/hides both background images and background color. #### JSON Grammar @@ -165,7 +186,26 @@ showBackground|boolean|true (default), false| [WP Get view properties](../WritePro/commands-legacy/wp-get-view-properties.md) - [WP SET VIEW PROPERTIES](../WritePro/commands-legacy/wp-set-view-properties.md) ---- + + +## Show empty or unsupported images + +Displays/hides a black rectangle for images that cannot be loaded or computed (empty images or images in an unsupported format). + +#### JSON Grammar + +|Name|Data Type|Possible Values| +|---|---|---| +showEmptyImages|boolean|true (default), false| + +#### Objects Supported + +[4D Write Pro area](writeProArea_overview.md) + +#### Commands + +[WP Get view properties](../WritePro/commands-legacy/wp-get-view-properties.md) - [WP SET VIEW PROPERTIES](../WritePro/commands-legacy/wp-set-view-properties.md) + ## Show footers @@ -340,7 +380,35 @@ showReferences|boolean|true, false (default)| [WP Get view properties](../WritePro/commands-legacy/wp-get-view-properties.md) - [WP SET VIEW PROPERTIES](../WritePro/commands-legacy/wp-set-view-properties.md) ---- +## Show table borders + +Displays internal and external table borders as dotted lines when these borders are partially or totally invisible. This facilitates page layout (more accessible, more visual resizing) and data entry (convenient in the case of merged cells, for example). + +![](../assets/en/FormObjects/visible.png) + + +:::tip Related blog post + +[4D Write Pro: Make Hidden Table Borders Visible (Temporarily)](https://blog.4d.com/4d-write-pro-make-hidden-table-borders-visible-temporarily/) + +::: + +#### JSON Grammar + +|Name|Data Type|Possible Values| +|---|---|---| +showTableBorders|boolean|true, false (default)| + +#### Objects Supported + +[4D Write Pro area](writeProArea_overview.md) + +#### Commands + +[WP Get view properties](../WritePro/commands-legacy/wp-get-view-properties.md) - [WP SET VIEW PROPERTIES](../WritePro/commands-legacy/wp-set-view-properties.md) + + + ## Show vertical ruler @@ -373,7 +441,7 @@ When tab controls with a custom direction are displayed under Windows, they auto |Name|Data Type|Possible Values| |---|---|---| -labelsPlacement|boolean|"top", "bottom" | +labelsPlacement|text|"top", "bottom" | #### Objects Supported diff --git a/docs/FormObjects/properties_BackgroundAndBorder.md b/docs/FormObjects/properties_BackgroundAndBorder.md index 9d61c2b14e9071..15ecb61c9994ff 100644 --- a/docs/FormObjects/properties_BackgroundAndBorder.md +++ b/docs/FormObjects/properties_BackgroundAndBorder.md @@ -6,7 +6,7 @@ title: Background and Border ## Alternate Background Color -Allows setting a different background color for odd-numbered rows/columns in a list box. By default, *Automatic* is selected: the column uses the alternate background color set at the list box level. +Allows setting a different background color for odd-numbered rows/columns in a list box. By default, *Automatic* is selected for list box columns: the column uses the alternate background color set at the list box level. You can also set this property using the [`OBJECT SET RGB COLORS`](../commands/object-set-rgb-colors) command. @@ -28,7 +28,7 @@ You can also set this property using the [`OBJECT SET RGB COLORS`](../commands/o ## Background Color / Fill color -Defines the background color / fill color of an object. It can be defined for some standard objects (`fill` JSON property) or ["custom style" objects](#custom-style-button-check-box-or-radio-button) (`borderFillColor` JSON property). +Defines the background color / fill color of an object. It can be defined for some standard objects (`fill` JSON property) or ["custom style" objects](#custom-style-button-check-box-or-radio-button) (`borderFillColor` JSON property). :::note @@ -39,7 +39,7 @@ The **Fill color** property is named **Background color** with [List Box](listbo ### Standard objects -In the case of a list box, by default *Automatic* is selected: the column uses the background color set at the list box level. +In the case of a list box column, by default *Automatic* is selected: the column uses the background color set at the list box level. #### JSON Grammar @@ -113,14 +113,24 @@ You can also set this property using the [`LISTBOX SET PROPERTY`](../commands/li ## Border Color {#border-color} -Allows defining the color of the inner border for: -- [custom buttons](./button_overview.md#custom) with the ["custom" Border Line Style](#border-line-style), -- [custom check boxes](./checkbox_overview.md#custom), -- [custom radio buttons](./radio_overview.md#custom). +Allows defining the border color. The effect of this property varies slightly depending on the type of object to which it is applied. + + + + +- **objects with text properties**: [buttons](./button_overview.md) (all styles except "custom", see below), [hierarchical lists](list_overview.md), [inputs](input_overview.md), [list boxes](listbox_overview.md), [progress indicators](./progressIndicator.md), [rulers](./ruler.md), and [text areas](text.md). +By default, the border color of these objects is automatically set to their [**font color**](./properties_Text.md#font-color) property. This default configuration corresponds to the **Same as font** option in the Property List (`borderColor` property is undefined in JSON). +You can separate these two properties by setting a color value for the object's "Border color" property (only available when the [**border line style**](#border-line-style) property is **plain** (`solid` in JSON property) or **dotted**). + +- **objects without text properties**: [4D View Pro areas](viewProArea_overview.md), [4D Write Pro areas](writeProArea_overview.md), [button grids](buttonGrid_overview.md), [picture buttons](pictureButton_overview.md), [picture pop-up menus](picturePopupMenu_overview.md), [plug-in areas](pluginArea_overview.md), [subforms](subform_overview.md), [spinners](spinner.md), [splitters](splitters.md), [steppers](stepper.md), [web areas](webArea_overview.md). +The border color property sets the color of the borders. The default color value is "Automatic", i.e. the border is displayed with the automatic color set by your OS. + + +- **custom-styled buttons**: [custom buttons](./button_overview.md#custom) with ["custom" Border Line Style](#border-line-style), [custom check boxes](./checkbox_overview.md#custom), and [custom radio buttons](./radio_overview.md#custom). +In this case, the border color property defines the color of an *inner* border, which is an attribute of the object itself ans not a decoration property. This inner border can also have a [width](#border-width) (it is displayed only if the width > 0). + -In other contexts, the property is ignored. -Note that the border is only displayed when its [width](#border-width) is > 0. #### JSON Grammar @@ -131,31 +141,43 @@ Note that the border is only displayed when its [width](#border-width) is > 0. #### Objects Supported -[Custom Button](./button_overview.md#custom) (with ["custom" Border Line Style](#border-line-style)) - [Custom Check Box](checkbox_overview.md#custom) - [Custom Radio Button](radio_overview.md#custom) +[4D View Pro area](viewProArea_overview.md) - [4D Write Pro area](writeProArea_overview.md) - [Button](./button_overview.md) - [Button Grid](buttonGrid_overview.md) - [Check Box ("custom" style)](checkbox_overview.md#custom) - [Hierarchical List](list_overview.md) - [Input](input_overview.md) - [List Box](listbox_overview.md) - [Picture Button](pictureButton_overview.md) - [Picture Pop-up Menu](picturePopupMenu_overview.md) - [Plug-in Area](pluginArea_overview.md) - [Progress Indicator](./progressIndicator.md) - [Radio Button ("custom" style)](radio_overview.md#custom) - [Ruler](./ruler.md) - [Text Area](text.md) - [Spinner](spinner.md) - [Splitter](splitters.md) - [Stepper](stepper.md) - [Subform](subform_overview.md) - [Web Area](webArea_overview.md) #### Commands [`OBJECT GET RGB COLORS`](../commands/object-get-rgb-colors) - [`OBJECT SET RGB COLORS`](../commands/object-set-rgb-colors) +#### See also + +[Line Color](#line-color) (for shapes) ## Border Line Style {#border-line-style} -Allows setting a standard style for the object border. - -:::note +Allows setting a style for the object border. The following choices are available (all choices are not possible depending on the object): -For [custom buttons](./button_overview.md#custom), the **custom** border line style enables the inner frame design, that includes a set of extra properties: [Fill color](#background-color--fill-color), [Frame color](#frame-color), [Frame width](#frame-width), and [Corner radius](./properties_BackgroundAndBorder.md#corner-radius). +|Style |Objects (\*)|Description| +|----|----|----| +|None|all|Objects appear with no border.| +|Plain |all|Objects appear framed with a continuous 1-pt. border line. ("solid" json value) | +|Dotted |all|Objects appear framed with a dotted 1-pt. border line.| +|Raised|all|Objects appear framed with a 3D effect.| +|Sunken |all|Objects appear framed with a sunken 3D effect.| +|Double|all|Objects appear framed with a double line, i.e., two continuous 1-pt. lines separated by a pixel.| +|System|all *except* [buttons](button_overview.md) and [text areas](text.md)|Objects appear with a border line based on the graphic specifications of the OS.| +|System rounded|[inputs](input_overview.md)|On macOS, objects appear with a native "Liquid Glass" system border effect (for information about Liquid Glass, see [this 4D blog post](https://blog.4d.com/the-new-macos-tahoe-design-comes-to-your-4d-applications/)). It includes system-defined inner border, corner radius, grey border color, and inner padding. Note that the "Liquid Glass" appearance is *not* used in a multiline input object if the [scroll bars property](./properties_Appearance.md#vertical-scroll-bar) is enabled ("System" is used in this case).
    On Windows, this style is similar to "System" at runtime. | +|Custom|[custom buttons](./button_overview.md#custom)|Enables the inner border design, that includes a set of extra properties: [Fill color](#fill-color), [Border color](#border-color), [Border width](#border-width), and [Corner radius](#corner-radius).
    ![](../assets/en/FormObjects/custom-button.png)| -![](../assets/en/FormObjects/custom-button.png) +(\*) "all" means "all objects supported" listed below. -::: +:::tip Related blog posts -:::tip Related blog post +- [Customize Buttons, Radio Buttons, and Check Boxes with Background and Border Properties](https://blog.4d.com/customize-buttons-radio-buttons-and-check-boxes-with-background-and-border-properties). +- [Give Your Form Objects the Border Color They Deserve](https://blog.4d.com/give-your-form-objects-the-border-color-they-deserve) +- [Choose the Right Native Input Style for Your Interface on macOS](https://blog.4d.com/choose-the-right-native-input-style-for-your-interface-on-macos) -[Customize Buttons, Radio Buttons, and Check Boxes with Background and Border Properties](https://blog.4d.com/customize-buttons-radio-buttons-and-check-boxes-with-background-and-border-properties). ::: @@ -164,7 +186,7 @@ For [custom buttons](./button_overview.md#custom), the **custom** border line st |Name|Data Type|Possible Values| |---|---|---| -|borderStyle|text |"system", "none", "solid", "dotted", "raised", "sunken", "double", "custom"| +|borderStyle|text |"custom", "dotted", "double", "none", "raised", "solid", "sunken", "system", "systemRounded"| @@ -178,6 +200,12 @@ For [custom buttons](./button_overview.md#custom), the **custom** border line st [`OBJECT Get border style`](../commands/object-get-border-style) - [`OBJECT SET BORDER STYLE`](../commands/object-set-border-style) + +#### See also + +[Dotted Line Type](#dotted-line-type) (shapes) + + --- ## Border Width {#border-width} @@ -202,7 +230,7 @@ The value is expressed in pixels. #### Objects Supported -[Custom Button](./button_overview.md#custom) (with ["custom" Border Line Style](#border-line-style)) - [Custom Check Box](checkbox_overview.md#custom) - [Custom Radio Button](radio_overview.md#custom) +[Button ("custom" style)](./button_overview.md#custom) (with ["custom" Border Line Style](#border-line-style)) - [Check Box ("custom style")](checkbox_overview.md#custom) - [Radio Button ("custom" style)](radio_overview.md#custom) --- @@ -245,7 +273,7 @@ In [custom buttons](./button_overview.md#custom) (with a ["custom" Border Line S #### Objects Supported -[Custom Button](./button_overview.md#custom) (with ["custom" Border Line Style](#border-line-style)) - [Custom Check Box](checkbox_overview.md#custom) - [Input](input_overview.md) - [Rectangle](shapes_overview.md#rectangle) - [Text Area](text.md) - [Custom Radio Button](radio_overview.md#custom) +[Button ("custom" style)](./button_overview.md#custom) (with ["custom" Border Line Style](#border-line-style)) - [Check Box ("custom" style)](checkbox_overview.md#custom) - [Input](input_overview.md) - [Rectangle](shapes_overview.md#rectangle) - [Text Area](text.md) - [Radio Button ("custom" style)](radio_overview.md#custom) #### Commands @@ -315,7 +343,11 @@ You can also set this property using the [`OBJECT SET RGB COLORS`](../commands/o |---|---|---| |stroke |string |any css value, "transparent", "automatic"| -> This property is also available for text based objects, in which case it designates both the font color and the object's lines, see [Font color](properties_Text.md#font-color). +:::note + +This property is also available for objects with text properties, in which case it designates both the [Font color](properties_Text.md#font-color) and the object's lines, except if you used the [Border color](#border-color) property. + +::: #### Objects Supported diff --git a/docs/FormObjects/properties_DataSource.md b/docs/FormObjects/properties_DataSource.md index 80557a393b29ca..ae5f368f54259f 100644 --- a/docs/FormObjects/properties_DataSource.md +++ b/docs/FormObjects/properties_DataSource.md @@ -339,13 +339,13 @@ Specifies a variable or expression that will be assigned the elements or entitie Specifies the named selection to be used. You must enter the name of a valid named selection. It can be a process or interprocess named selection. The contents of the list box will be based on this selection. The named selection chosen must exist and be valid at the time the list box is displayed, otherwise the list box will be displayed blank. -> Named selections are ordered lists of records. They are used to keep the order and current record of a selection in memory. For more information, refer to **Named Selections** section in the *4D Language Reference manual*. +> Named selections are ordered lists of records. They are used to keep the order and current record of a selection in memory. For more information, refer to [**Named Selections**](../Develop/named-selections) section. #### JSON Grammar |Name|Data Type|Possible Values| |---|---|---| -|namedSelection| string|Named selection name| +|selectionName| string|Named selection name| #### Objects Supported diff --git a/docs/FormObjects/properties_Display.md b/docs/FormObjects/properties_Display.md index f93f7660e97ecd..73d1ddd7a8e858 100644 --- a/docs/FormObjects/properties_Display.md +++ b/docs/FormObjects/properties_Display.md @@ -671,7 +671,7 @@ Note that regardless of the Wordwrap option’s value, the row height is not cha |Name|Data Type|Possible Values| |---|---|---| -|wordwrap |string | "automatic" (excluding list box), "normal", "none"| +|wordwrap |string | "automatic" (excluding list box column and footer), "normal", "none"| #### Objects Supported diff --git a/docs/FormObjects/properties_Footers.md b/docs/FormObjects/properties_Footers.md index 57ef869832c863..3a3b0e3f8fe262 100644 --- a/docs/FormObjects/properties_Footers.md +++ b/docs/FormObjects/properties_Footers.md @@ -59,7 +59,7 @@ Note that converting back and forth may lead to an end result that is different |Name|Data Type|Possible Values| |---|---|---| -|footerHeight|string |positive decimal+px | em| +|footerHeight|string |value+px | em| #### Objects Supported diff --git a/docs/FormObjects/properties_Headers.md b/docs/FormObjects/properties_Headers.md index 67ec603e79360c..4155e37b15ff83 100644 --- a/docs/FormObjects/properties_Headers.md +++ b/docs/FormObjects/properties_Headers.md @@ -46,7 +46,7 @@ Note that converting back and forth may lead to an end result that is different #### JSON Example -``` +```json "List Box": { "type": "listbox", "showHeaders": true, @@ -59,7 +59,7 @@ Note that converting back and forth may lead to an end result that is different |Name|Data Type|Possible Values| |---|---|---| -|headerHeight|string |positive decimal+px | em | +|headerHeight|string |value+px | em | #### Objects Supported diff --git a/docs/FormObjects/properties_Hierarchy.md b/docs/FormObjects/properties_Hierarchy.md index eb2c11584a8945..2f8844c8e9bd0a 100644 --- a/docs/FormObjects/properties_Hierarchy.md +++ b/docs/FormObjects/properties_Hierarchy.md @@ -17,7 +17,7 @@ See [Hierarchical list boxes](listbox_overview.md#hierarchical-list-boxes) |Name|Data Type|Possible Values| |---|---|---| -|datasource|string array |Collection of array names defining the hierarchy| +|dataSource|string array |Collection of array names defining the hierarchy| #### Objects Supported diff --git a/docs/FormObjects/properties_ListBox.md b/docs/FormObjects/properties_ListBox.md index 2c801ee083188c..2d7c264d852284 100644 --- a/docs/FormObjects/properties_ListBox.md +++ b/docs/FormObjects/properties_ListBox.md @@ -170,15 +170,11 @@ Number of columns that cannot be moved during execution. --- ## Number of Columns -Sets the number of columns of the list box. +Sets the length of the [column collection](#columns) of the list box. >You can add or remove columns dynamically by programming, using commands such as [`LISTBOX INSERT COLUMN`](../commands/listbox-insert-column) or [`LISTBOX DELETE COLUMN`](../commands/listbox-delete-column). -#### JSON Grammar -|Name|Data Type|Possible Values| -|---|---|---| -|columnCount|integer |minimum: 1 #### Objects Supported diff --git a/docs/FormObjects/properties_Object.md b/docs/FormObjects/properties_Object.md index 11ae1b8f637589..8b059a74a87107 100644 --- a/docs/FormObjects/properties_Object.md +++ b/docs/FormObjects/properties_Object.md @@ -19,7 +19,7 @@ This property designates the type of the [active or inactive form object](formOb #### Objects Supported -[4D View Pro area](viewProArea_overview.md) - [4D Write Pro area](writeProArea_overview.md) - [Button](button_overview.md) - [Button Grid](buttonGrid_overview.md) - [Check Box](checkbox_overview.md) - [Combo Box](comboBox_overview.md) - [Drop-down List](dropdownList_Overview.md) - [Group Box](groupBox.md) - [Hierarchical List](list_overview.md) - [List Box](listbox_overview.md) - [List Box Column](listbox-column.md) - [List Box Footer](listbox-header-footer.md#footers) - [List Box Header](listbox-header-footer.md#headers) - [Picture Button](pictureButton_overview.md) - [Picture Pop-up Menu](picturePopupMenu_overview.md) - [Plug-in Area](pluginArea_overview.md) - [Progress indicator](progressIndicator.md) - [Radio Button](radio_overview.md) -[Spinner](spinner.md) - [Splitter](splitters.md) - [Static Picture](staticPicture.md) - [Stepper](stepper.md) - [Subform](subform_overview.md) - [Tab control](tabControl.md) - [Text Area](text.md) - [Web Area](webArea_overview.md) +[4D View Pro area](viewProArea_overview.md) - [4D Write Pro area](writeProArea_overview.md) - [Button](button_overview.md) - [Button Grid](buttonGrid_overview.md) - [Check Box](checkbox_overview.md) - [Combo Box](comboBox_overview.md) - [Drop-down List](dropdownList_Overview.md) - [Group Box](groupBox.md) - [Hierarchical List](list_overview.md) - [List Box](listbox_overview.md) - [List Box Column](listbox-column.md) - [List Box Footer](listbox-header-footer.md#footers) - [List Box Header](listbox-header-footer.md#headers) - [Picture Button](pictureButton_overview.md) - [Picture Pop-up Menu](picturePopupMenu_overview.md) - [Plug-in Area](pluginArea_overview.md) - [Progress indicator](progressIndicator.md) - [Radio Button](radio_overview.md) - [Spinner](spinner.md) - [Splitter](splitters.md) - [Static Picture](staticPicture.md) - [Stepper](stepper.md) - [Subform](subform_overview.md) - [Tab control](tabControl.md) - [Text Area](text.md) - [Web Area](webArea_overview.md) --- @@ -332,7 +332,7 @@ When **Custom** ("none" in JSON) is set, no automatic calculations are performed |Name|Data Type|Possible Values| |---|---|---| -|variableCalculation|string|"none", "minimum", "maximum", "sum", "count", "average", "standardDeviation", "variance", "sumSquare"| +|variableCalculation|string|"none", "minimum", "maximum", "sum", "count", "average", "standardDeviation", "variance", "sumSquares"| #### Objects Supported diff --git a/docs/FormObjects/properties_RangeOfValues.md b/docs/FormObjects/properties_RangeOfValues.md index db44ce6f9664ee..541d31c56310a3 100644 --- a/docs/FormObjects/properties_RangeOfValues.md +++ b/docs/FormObjects/properties_RangeOfValues.md @@ -15,7 +15,7 @@ The default value can only be used if the [data source type](properties_Object.m - time - boolean -4D provides stamps for generating default values for the date, time, and sequence number. The date and time are taken from the system date and time. 4D automatically generates any sequence numbers needed. The table below shows the stamp to use to generate default values automatically: +4D provides stamps for generating default values for a date, a time, and a sequence number. The date and time are taken from the system date and time. 4D automatically generates any sequence numbers needed. The table below shows the stamp to use to generate default values automatically: |Stamp| Meaning| |---|---| @@ -23,7 +23,7 @@ The default value can only be used if the [data source type](properties_Object.m |#H|Current time| |#N|Sequence number| -You can use a sequence number to create a unique number for each record in the table for the current data file. A sequence number is a longint that is generated for each new record. The numbers start at one (1) and increase incrementally by one (1). A sequence number is never repeated even if the record it is assigned to is deleted from the table. Each table has its own internal counter of sequence numbers. For more information, refer to the [Autoincrement](https://doc.4d.com/4Dv20/4D/20.2/Field-properties.300-6750280.en.html#976029) paragraph. +You can use a sequence number to create a unique number for each record in the table for the current data file. A sequence number is a longint that is generated for each new record. The numbers start at one (1) and increase incrementally by one (1). A sequence number is never repeated even if the record it is assigned to is deleted from the table. Each table has its own internal counter of sequence numbers. For more information, refer to the [Autoincrement](../Develop/structure-fields#autoincrement) paragraph. > Do not make confusion between this property and the "[default values](properties_DataSource.md#default-list-of-values)" property that allows to fill a list box column with static values. @@ -31,7 +31,7 @@ You can use a sequence number to create a unique number for each record in the t |Name|Data Type|Possible Values| |---|---|---| -|defaultValue |string, number, date, time, boolean|Any value and/or a stamp: "#D", "#H", "#N"| +|defaultValue |string|Any value and/or a stamp as a string: "#D", "#H", "#N", "42", "true"...| #### Objects Supported diff --git a/docs/FormObjects/properties_Reference.md b/docs/FormObjects/properties_Reference.md index 16f70ba90753e2..fa2b6ab8f2d536 100644 --- a/docs/FormObjects/properties_Reference.md +++ b/docs/FormObjects/properties_Reference.md @@ -53,7 +53,7 @@ You will find in this page a comprehensive list of all object properties sorted |[`columns`](properties_ListBox.md#columns)|A collection of list box columns|Collection of column objects with defined column properties |[`contextMenu`](properties_Entry.md#context-menu)|Provides the user access to a standard context menu in the selected area. |"automatic", "none"| |[`continuousExecution`](properties_Action.md#execute-object-method)|Designates whether or not to run the method of an object while the user is tracking the control. |true, false| -|[`controlType`](properties_Display.md#display-type)|Specifies how the value should be rendered in a list box cell.|"input", "checkbox" (for boolean / numeric columns), "automatic", "popup" (only for boolean columns)| +|[`controlType`](properties_Display.md#display-type)|Specifies how the value should be rendered in a list box cell.|"automatic" or "checkbox" for numeric columns, "popup" or "checkbox" for boolean columns| |[`currentItemSource`](properties_DataSource.md#current-item)| The last selected item in a list box.|Object expression | |[`currentItemPositionSource`](properties_DataSource.md#current-item-position)| The position of the last selected item in a list box.|Number expression | |[`customBackgroundPicture`](properties_TextAndPicture.md#background-pathname) |Sets the picture that will be drawn in the background of a button.|Relative path in POSIX syntax. Must be used in conjunction with the style property with the "custom" option.| @@ -70,6 +70,7 @@ You will find in this page a comprehensive list of all object properties sorted |[`deletableInList`](properties_Subform.md#allow-deletion)|Specifies if the user can delete subrecords in a list subform|true, false| |[`detailForm`](properties_ListBox.md#detail-form-name) (list box)
    [`detailForm`](properties_Subform.md#detail-form) (subform)|Associates a detail form with a list subform.|Name (string) of table or project form, a POSIX path (string) to a .json file describing the form, or an object describing the form | |[`display`](properties_Display.md#not-rendered)|The object is drawn or not on the form.|true, false| +|[`displayFormulaAsSymbol`](properties_Display.md#display-formula-source-as-symbol)|Displays source text of formulas as symbols.|true, false| |[`doubleClickInEmptyAreaAction`](properties_Subform.md#double-click-on-empty-row)|Action to perform in case of a double-click on an empty line of a list subform.|"addSubrecord" or "" to do nothing| |[`doubleClickInRowAction`](properties_ListBox.md#double-click-on-row) (list box)
    [`doubleClickInRowAction`](properties_Subform.md#double-click-on-row) (subform)|Action to perform in case of a double-click on a record. |"editSubrecord", "displaySubrecord"| |[`dpi`](properties_Appearance.md#resolution)|Screen resolution for the 4D Write Pro area contents.|0=automatic, 72, 96| @@ -173,7 +174,8 @@ You will find in this page a comprehensive list of all object properties sorted |[`shortcutControl`](properties_Entry.md#shortcut)|Designates the Control key (Windows)|true, false| |[`shortcutKey`](properties_Entry.md#shortcut)|The letter or name of a special meaning key.|"a", "b",... or "[F1]" -> "[F15]", "[Return]", "[Enter]", "[Backspace]", "[Tab]", "[Esc]", "[Del]", "[Home]", "[End]", "[Help]", "[Page up]", "[Page down]", "[left arrow]", "[right arrow]", "[up arrow]", "[down arrow]"| |[`shortcutShift`](properties_Entry.md#shortcut) |Designates the Shift key |true, false| -|[`showFooters`](properties_Footers.md#display-footers)|Displays or hides column footers. |true, false| +|[`showBackground`](properties_Appearance.md#show-background-and-anchored-elements)| Displays or hides background contents. |true, false| +|[`showEmptyImages`](properties_Appearance.md#show-empty-or-unsupported-images)|Displays/hides a black rectangle for empty images|true, false||[`showFooters`](properties_Footers.md#display-footers)|Displays or hides column footers. |true, false| |[`showGraduations`](properties_Scale.md#display-graduation)|Displays/Hides the graduations next to the labels. |true, false| |[`showHeaders`](properties_Headers.md#display-headers)|Displays or hides column headers. |true, false| |[`showHiddenChars`](properties_Appearance.md#show-hidden-characters)|Displays/hides invisible characters.|true, false| @@ -182,6 +184,7 @@ You will find in this page a comprehensive list of all object properties sorted |[`showPageFrames`](properties_Appearance.md#show-page-frame)|Displays/hides the page frame when the document view is in Page view mode|true, false| |[`showReferences`](properties_Appearance.md#show-references)|Displays all 4D expressions inserted in the 4D Write Pro document as *references*|true, false| |[`showSelection`](properties_Entry.md#selection-always-visible)|Keeps the selection visible within the object after it has lost the focus |true, false| +|[`showTableBorders`](properties_Appearance.md#show-table-borders)|Displays internal and external table borders as dotted lines when these borders are invisible|true, false| |[`showVerticalRuler`](properties_Appearance.md#show-vertical-ruler)|Displays/hides the vertical ruler when the document view is in Page view mode|true, false| |[`singleClickEdit`](properties_Entry.md#single-click-edit)|Enables direct passage to edit mode.|true, false| |[`sizingX`](properties_ResizingOptions.md#horizontal-sizing)|Specifies if the horizontal size of an object should be moved or resized when a user resizes the form.|"grow", "move", "fixed"| @@ -221,7 +224,7 @@ You will find in this page a comprehensive list of all object properties sorted |[`userInterface`](properties_Appearance.md#user-interface)|4D View Pro area interface.|"none" (default), "ribbon", "toolbar"| |**v**||| |[`values`](properties_DataSource.md#default-list-of-values)|List of default values for an array listbox column|ex: "A","B","42"...| -|[`variableCalculation`](properties_Object.md#variable-calculation)|Allows mathematical calculations to be performed.|"none", "minimum", "maximum", "sum", "count", "average", "standardDeviation", "variance", "sumSquare"| +|[`variableCalculation`](properties_Object.md#variable-calculation)|Allows mathematical calculations to be performed.|"none", "minimum", "maximum", "sum", "count", "average", "standardDeviation", "variance", "sumSquares"| |[`verticalAlign`](properties_Text.md#vertical-alignment)|Vertical location of text within the area that contains it. |"automatic", "top", "middle", "bottom"| |[`verticalLineStroke`](properties_Gridlines.md#vertical-line-color)|Defines the color of the vertical lines in a list box (gray by default).|Any CSS value, "transparent", "automatic"| |[`verticalPadding`](./properties_CoordinatesAndSizing.md#vertical-padding)|Sets a vertical padding for listbox cells.|Number of pixels (must be >=0)| @@ -230,7 +233,7 @@ You will find in this page a comprehensive list of all object properties sorted |[`webEngine`](properties_WebArea.md#use-embedded-web-rendering-engine)| Used to choose between two rendering engines for the Web area, depending on the specifics of the application.|"embedded", "system"| |[`width`](properties_CoordinatesAndSizing.md#width)|Designates an object's horizontal size|minimum: 0| |[`withFormulaBar`](properties_Appearance.md#show-formula-bar)|Manages the display of a formula bar with the Toolbar interface in the 4D View Pro area.|true, false| -|[`wordwrap`](properties_Display.md#wordwrap) |Manages the display of contents when it exceeds the width of the object. | "automatic" (excluding list box), "normal", "none"| +|[`wordwrap`](properties_Display.md#wordwrap) |Manages the display of contents when it exceeds the width of the object. | "automatic" (excluding list box column and footer), "normal", "none"| |[`writingTools`](properties_Entry.md#writing-tools) |Manages the availability of local AI-based Writing Tools. | true, false| |**z**||| |[`zoom`](properties_Appearance.md#zoom)|Zoom percentage for displaying 4D Write Pro area|number (minimum=0)| diff --git a/docs/FormObjects/properties_Text.md b/docs/FormObjects/properties_Text.md index c0140f64351fa0..7a2dd3ccf5f6bf 100644 --- a/docs/FormObjects/properties_Text.md +++ b/docs/FormObjects/properties_Text.md @@ -78,7 +78,7 @@ Sets the text to have a line running beneath it. |Name|Data Type|Possible Values| |---|---|---| -|textDecoration|string|"normal", "underline"| +|textDecoration|string|"none", "underline"| #### Objects Supported @@ -166,7 +166,7 @@ Allows defining the object's font size in points. #### Objects Supported -[Button](button_overview.md) - [Check Box](checkbox_overview.md) - [Combo Box](comboBox_overview.md) - [Drop-down List](dropdownList_Overview.md) - [Group Box](groupBox.md) - [Hierarchical List](list_overview.md) - [Input](input_overview.md) - [List Box](listbox_overview.md) - [List Box Column](listbox-column.md) - [List Box Footer](listbox-header-footer.md#footers) - [List Box Header](listbox-header-footer.md#headers) - [Radio Button](radio_overview.md) - [Text Area](text.md) +[Button](button_overview.md) - [Check Box](checkbox_overview.md) - [Combo Box](comboBox_overview.md) - [Drop-down List](dropdownList_Overview.md) - [Group Box](groupBox.md) - [Hierarchical List](list_overview.md) - [Input](input_overview.md) - [List Box](listbox_overview.md) - [List Box Column](listbox-column.md) - [List Box Footer](listbox-header-footer.md#footers) - [List Box Header](listbox-header-footer.md#headers) - [Progress Indicators](progressIndicator.md) - [Radio Button](radio_overview.md) - [Ruler](ruler.md) - [Text Area](text.md) #### Commands @@ -178,7 +178,13 @@ Allows defining the object's font size in points. Designates the font color. -> This property also sets the color of object's border (if any) when "plain" or "dotted" style is used. + +:::note + +For objects with text properties, this property also sets the color of the border when "plain" or "dotted" [border style](./properties_BackgroundAndBorder.md#border-line-style) is used, except if you used the [Border color](./properties_BackgroundAndBorder.md#border-color) property. + +::: + The color can be specified by: @@ -196,7 +202,7 @@ You can also set this property using the [**OBJECT SET RGB COLORS**](../commands #### Objects Supported -[Button](button_overview.md) - [Check Box](checkbox_overview.md) - [Combo Box](comboBox_overview.md) - [Drop-down List](dropdownList_Overview.md) - [Group Box](groupBox.md) - [Hierarchical List](list_overview.md) - [Input](input_overview.md) - [List Box](listbox_overview.md) - [List Box Column](listbox-column.md) - [List Box Footer](listbox-header-footer.md#footers) - [List Box Header](listbox-header-footer.md#headers) - [Progress Indicators](progressIndicator.md) - [Ruler](ruler.md) - [Radio Button](radio_overview.md) - [Text Area](text.md) +[Button](button_overview.md) - [Check Box](checkbox_overview.md) - [Combo Box](comboBox_overview.md) - [Drop-down List](dropdownList_Overview.md) - [Group Box](groupBox.md) - [Hierarchical List](list_overview.md) - [Input](input_overview.md) - [List Box](listbox_overview.md) - [List Box Column](listbox-column.md) - [List Box Footer](listbox-header-footer.md#footers) - [List Box Header](listbox-header-footer.md#headers) - [Progress Indicators](progressIndicator.md) - [Radio Button](radio_overview.md) - [Ruler](ruler.md) - [Text Area](text.md) #### Commands @@ -287,7 +293,7 @@ Horizontal location of text within the area that contains it. :::note -- "automatic" is not supported by [check boxes](checkbox_overview.md) and [radio buttons](radio_overview.md) +- "automatic" is not supported by [buttons](button_overview.md), [check boxes](checkbox_overview.md), and [radio buttons](radio_overview.md) - "justify" is only supported by [inputs](input_overview.md) and [text areas](text.md) ::: diff --git a/docs/FormObjects/properties_TextAndPicture.md b/docs/FormObjects/properties_TextAndPicture.md index e13e0128a0c593..728babd7653d80 100644 --- a/docs/FormObjects/properties_TextAndPicture.md +++ b/docs/FormObjects/properties_TextAndPicture.md @@ -39,7 +39,7 @@ General appearance of the button. The button style also plays a part in the avai #### Objects Supported -[Button](button_overview.md) - [Radio Button](radio_overview.md) - [Check Box](checkbox_overview.md) - [Radio Button](radio_overview.md) +[Button](button_overview.md) - [Radio Button](radio_overview.md) - [Check Box](checkbox_overview.md) #### Commands diff --git a/docs/FormObjects/ruler.md b/docs/FormObjects/ruler.md index a35b78f8248e23..fcf6cb53aa3ddc 100644 --- a/docs/FormObjects/ruler.md +++ b/docs/FormObjects/ruler.md @@ -14,7 +14,7 @@ For more information, please refer to [Using indicators](progressIndicator.md#us ### Supported Properties -[Bold](properties_Text.md#bold) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) -[Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Display graduation](properties_Scale.md#display-graduation) - [Enterable](properties_Entry.md#enterable) - [Execute object method](properties_Action.md#execute-object-method) - [Expression Type](properties_Object.md#expression-type) - [Height](properties_CoordinatesAndSizing.md#height) - [Graduation step](properties_Scale.md#graduation-step) -[Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Label Location](properties_Scale.md#label-location) - [Left](properties_CoordinatesAndSizing.md#left) - [Maximum](properties_Scale.md#maximum) - [Minimum](properties_Scale.md#minimum) - [Number Format](properties_Display.md#number-format) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Step](properties_Scale.md#step) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Bold](properties_Text.md#bold) - [Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) -[Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Display graduation](properties_Scale.md#display-graduation) - [Enterable](properties_Entry.md#enterable) - [Execute object method](properties_Action.md#execute-object-method) - [Expression Type](properties_Object.md#expression-type) - [Font Color](properties_Text.md#font-color) - [Font Size](properties_Text.md#font-size) - [Graduation step](properties_Scale.md#graduation-step) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Label Location](properties_Scale.md#label-location) - [Left](properties_CoordinatesAndSizing.md#left) - [Maximum](properties_Scale.md#maximum) - [Minimum](properties_Scale.md#minimum) - [Number Format](properties_Display.md#number-format) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Step](properties_Scale.md#step) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ### Supported Events diff --git a/docs/FormObjects/spinner.md b/docs/FormObjects/spinner.md index ddf64c360657fb..a3d605e1fb8215 100644 --- a/docs/FormObjects/spinner.md +++ b/docs/FormObjects/spinner.md @@ -16,7 +16,7 @@ When the form is executed, the object is not animated. You manage the animation ### Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Expression Type](properties_Object.md#expression-type) - [Height](properties_CoordinatesAndSizing.md#height) -[Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Expression Type](properties_Object.md#expression-type) - [Height](properties_CoordinatesAndSizing.md#height) -[Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ### Supported Events diff --git a/docs/FormObjects/splitters.md b/docs/FormObjects/splitters.md index f9270d3dfd298b..d85c859d3f9a93 100644 --- a/docs/FormObjects/splitters.md +++ b/docs/FormObjects/splitters.md @@ -37,7 +37,7 @@ Once it is inserted, the splitter appears as a line. You can modify its [border ### Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Line Color](properties_BackgroundAndBorder.md#line-color) - [Object Name](properties_Object.md#object-name) - [Pusher](properties_ResizingOptions.md#pusher) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Line Color](properties_BackgroundAndBorder.md#line-color) - [Object Name](properties_Object.md#object-name) - [Pusher](properties_ResizingOptions.md#pusher) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ### Supported Events diff --git a/docs/FormObjects/stepper.md b/docs/FormObjects/stepper.md index 1e2cba2590762a..b812b901aff5c3 100644 --- a/docs/FormObjects/stepper.md +++ b/docs/FormObjects/stepper.md @@ -25,7 +25,7 @@ For more information, please refer to [Using indicators](progressIndicator.md#us ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Enterable](properties_Entry.md#enterable) - [Execute object method](properties_Action.md#execute-object-method) - [Expression Type](properties_Object.md#expression-type) (only "integer", "number", "date", or "time") - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Maximum](properties_Scale.md#maximum) - [Minimum](properties_Scale.md#minimum) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Step](properties_Scale.md#step) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Enterable](properties_Entry.md#enterable) - [Execute object method](properties_Action.md#execute-object-method) - [Expression Type](properties_Object.md#expression-type) (only "integer", "number", "date", or "time") - [Height](properties_CoordinatesAndSizing.md#height) - [Help Tip](properties_Help.md#help-tip) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Maximum](properties_Scale.md#maximum) - [Minimum](properties_Scale.md#minimum) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Step](properties_Scale.md#step) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/subform_overview.md b/docs/FormObjects/subform_overview.md index 59d4a58f664b65..38bcbba1407833 100644 --- a/docs/FormObjects/subform_overview.md +++ b/docs/FormObjects/subform_overview.md @@ -222,7 +222,7 @@ For more information, refer to the description of the `EXECUTE METHOD IN SUBFORM ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Detail Form](properties_Subform.md#detail-form) - [Double click on empty row](properties_Subform.md#double-click-on-empty-row) - [Double click on row](properties_Subform.md#double-click-on-row) - [Enterable in list](properties_Subform.md#enterable-in-list) - [Expression Type](properties_Object.md#expression-type) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Detail Form](properties_Subform.md#detail-form) - [Double click on empty row](properties_Subform.md#double-click-on-empty-row) - [Double click on row](properties_Subform.md#double-click-on-row) - [Enterable in list](properties_Subform.md#enterable-in-list) - [Expression Type](properties_Object.md#expression-type) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Hide focus rectangle](properties_Appearance.md#hide-focus-rectangle) - [Horizontal Scroll Bar](properties_Appearance.md#horizontal-scroll-bar) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [List Form](properties_Subform.md#list-form) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Print Frame](properties_Print.md#print-frame) - [Right](properties_CoordinatesAndSizing.md#right) - [Selection mode](properties_Subform.md#selection-mode) - [Source](properties_Subform.md#source) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Scroll Bar](properties_Appearance.md#vertical-scroll-bar) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) diff --git a/docs/FormObjects/viewProArea_overview.md b/docs/FormObjects/viewProArea_overview.md index b5ca17e1e008e5..30cc7692de1752 100644 --- a/docs/FormObjects/viewProArea_overview.md +++ b/docs/FormObjects/viewProArea_overview.md @@ -17,7 +17,7 @@ Once you use 4D View Pro areas in your forms, you can import and export spreadsh ## Supported Properties -[Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Height](properties_CoordinatesAndSizing.md#height) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Show Formula Bar](properties_Appearance.md#show-formula-bar) - [Type](properties_Object.md#type) - [User Interface](properties_Appearance.md#user-interface) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Height](properties_CoordinatesAndSizing.md#height) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Right](properties_CoordinatesAndSizing.md#right) - [Show Formula Bar](properties_Appearance.md#show-formula-bar) - [Type](properties_Object.md#type) - [User Interface](properties_Appearance.md#user-interface) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/webArea_overview.md b/docs/FormObjects/webArea_overview.md index 849656dfde86ba..940d41136e9ef1 100644 --- a/docs/FormObjects/webArea_overview.md +++ b/docs/FormObjects/webArea_overview.md @@ -253,7 +253,7 @@ When you have done the settings as described above, you then have new options su ## Supported Properties -[Access 4D methods](properties_WebArea.md#access-4d-methods) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Context Menu](properties_Entry.md#context-menu) - [Height](properties_CoordinatesAndSizing.md#height) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Progression](properties_WebArea.md#progression) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [URL](properties_WebArea.md#url) - [Use embedded Web rendering engine](properties_WebArea.md#use-embedded-web-rendering-engine) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibilty](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) +[Access 4D methods](properties_WebArea.md#access-4d-methods) - [Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Context Menu](properties_Entry.md#context-menu) - [Height](properties_CoordinatesAndSizing.md#height) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Progression](properties_WebArea.md#progression) - [Right](properties_CoordinatesAndSizing.md#right) - [Top](properties_CoordinatesAndSizing.md#top) - [Type](properties_Object.md#type) - [URL](properties_WebArea.md#url) - [Use embedded Web rendering engine](properties_WebArea.md#use-embedded-web-rendering-engine) - [Variable or Expression](properties_Object.md#variable-or-expression) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Visibilty](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) ## Supported Events diff --git a/docs/FormObjects/writeProArea_overview.md b/docs/FormObjects/writeProArea_overview.md index df02f332cbe5db..0d08ed1ca3c93f 100644 --- a/docs/FormObjects/writeProArea_overview.md +++ b/docs/FormObjects/writeProArea_overview.md @@ -15,7 +15,7 @@ title: 4D Write Pro area ## Supported Properties -[Auto Spellcheck](properties_Entry.md#auto-spellcheck) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Context Menu](properties_Entry.md#context-menu) - [Draggable](properties_Action.md#draggable) - [Droppable](properties_Action.md#droppable) - [Enterable](properties_Entry.md#enterable) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Hide focus rectangle](properties_Appearance.md#hide-focus-rectangle) - [Horizontal Scroll Bar](properties_Appearance.md#horizontal-scroll-bar) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Keyboard Layout](properties_Entry.md#keyboard-layout) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Print Variable Frame](properties_Print.md#print-frame) - [Resolution](properties_Appearance.md#resolution) - [Right](properties_CoordinatesAndSizing.md#right) - [Selection always visible](properties_Entry.md#selection-always-visible) - [Show background](properties_Appearance.md#show-background) - [Show footers](properties_Appearance.md#show-footers) - [Show headers](properties_Appearance.md#show-headers) - [Show hidden characters](properties_Appearance.md#show-hidden-characters) - [Show horizontal ruler](properties_Appearance.md#show-horizontal-ruler) - [Show HTML WYSIWYG](properties_Appearance.md#show-html-wysiwyg) - [Show page frame](properties_Appearance.md#show-page-frame) - [Show references](properties_Appearance.md#show-references) - [Show vertical ruler](properties_Appearance.md#show-vertical-ruler) - [Type](properties_Object.md#type) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Vertical Scroll Bar](properties_Appearance.md#vertical-scroll-bar) - [View mode](properties_Appearance.md#view-mode) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) - [Writing Tools](properties_Entry.md#writing-tools) - [Zoom](properties_Appearance.md#zoom) +[Auto Spellcheck](properties_Entry.md#auto-spellcheck) - [Border color](./properties_BackgroundAndBorder.md#border-color) - [Border Line Style](properties_BackgroundAndBorder.md#border-line-style) - [Bottom](properties_CoordinatesAndSizing.md#bottom) - [Class](properties_Object.md#css-class) - [Context Menu](properties_Entry.md#context-menu) - [Draggable](properties_Action.md#draggable) - [Droppable](properties_Action.md#droppable) - [Enterable](properties_Entry.md#enterable) - [Focusable](properties_Entry.md#focusable) - [Height](properties_CoordinatesAndSizing.md#height) - [Hide focus rectangle](properties_Appearance.md#hide-focus-rectangle) - [Horizontal Scroll Bar](properties_Appearance.md#horizontal-scroll-bar) - [Horizontal Sizing](properties_ResizingOptions.md#horizontal-sizing) - [Keyboard Layout](properties_Entry.md#keyboard-layout) - [Left](properties_CoordinatesAndSizing.md#left) - [Method](properties_Action.md#method) - [Object Name](properties_Object.md#object-name) - [Print Variable Frame](properties_Print.md#print-frame) - [Resolution](properties_Appearance.md#resolution) - [Right](properties_CoordinatesAndSizing.md#right) - [Selection always visible](properties_Entry.md#selection-always-visible) - [Show background](properties_Appearance.md#show-background) - [Show footers](properties_Appearance.md#show-footers) - [Show headers](properties_Appearance.md#show-headers) - [Show hidden characters](properties_Appearance.md#show-hidden-characters) - [Show horizontal ruler](properties_Appearance.md#show-horizontal-ruler) - [Show HTML WYSIWYG](properties_Appearance.md#show-html-wysiwyg) - [Show page frame](properties_Appearance.md#show-page-frame) - [Show references](properties_Appearance.md#show-references) - [Show vertical ruler](properties_Appearance.md#show-vertical-ruler) - [Type](properties_Object.md#type) - [Vertical Sizing](properties_ResizingOptions.md#vertical-sizing) - [Vertical Scroll Bar](properties_Appearance.md#vertical-scroll-bar) - [View mode](properties_Appearance.md#view-mode) - [Visibility](properties_Display.md#visibility) - [Width](properties_CoordinatesAndSizing.md#width) - [Writing Tools](properties_Entry.md#writing-tools) - [Zoom](properties_Appearance.md#zoom) ## Supported Events diff --git a/docs/Notes/updates.md b/docs/Notes/updates.md index eedc7add73ef44..5084df730f30d6 100644 --- a/docs/Notes/updates.md +++ b/docs/Notes/updates.md @@ -4,6 +4,25 @@ title: Release Notes --- +## 4D 21 R6 + +Read [**What’s new in 4D 21 R6**](https://blog.4d.com/whats-new-in-4d-21-r6/), the blog post that lists all new features and enhancements in 4D 21 R6. + +#### Highlights + +- Class functions and class constructors can be documented with a [comment block above their declaration](../Concepts/classes.md#function-comments): the description and parameter comments are displayed in the code completion and help of the [4D code editor](../code-editor/write-class-method.md#help-tips) and VS Code, and in the [syntax file of compiled components](../Extensions/develop-components.md#code-completion-for-compiled-components). +- `MCP:` comment lines and behavior tags provide the [MCP tool metadata](../Concepts/classes.md#mcp-tool-metadata) of `exposed MCP Function` declarations, generated at compilation in [`Project/DerivedData/syntaxMCP.json`](../Project/architecture.md#deriveddata) or provided by a custom [`Resources/syntaxMCP.json`](../Project/architecture.md#resources) file. +- New native [MCP server](../WebServer/mcp-server.md) in the 4D Web Server: AI clients can call your [`exposed MCP Function`](../ORDA/ordaClasses.md#exposed-mcp-function) functions and the [built-in CRUD tools](../WebServer/mcp-server.md#built-in-crud-tools), with the same [roles and privileges](../ORDA/privileges.md#mcp-tools) as REST requests. The MCP server is configured with the new [`WebServer.mcp`](../API/WebServerClass.md#mcp) property. +- MCP clients authenticate with Fine-Grained Tokens managed with the new [`ds.generateFineGrainedToken()`](../API/DataStoreClass.md#generatefinegrainedtoken), [`ds.listFineGrainedTokens()`](../API/DataStoreClass.md#listfinegrainedtokens), and [`ds.revokeFineGrainedToken()`](../API/DataStoreClass.md#revokefinegrainedtoken) functions. The reserved [`mcpAuthenticated()`](../ORDA/ordaClasses.md#function-mcpauthenticated) DataStore class function prepares each MCP session, whose [`Session.info.type`](../API/SessionClass.md#info) is "mcp". +- Optional [OAuth 2.1 mode](../WebServer/mcp-server.md#oauth-21-mode) of the MCP server, enabled by the reserved [`mcpGrant()`](../ORDA/ordaClasses.md#function-mcpgrant) DataStore class function. Grants are managed with the new [`ds.listOAuthGrants()`](../API/DataStoreClass.md#listoauthgrants) and [`ds.revokeOAuthGrant()`](../API/DataStoreClass.md#revokeoauthgrant) functions. +- New [`MCP`](../commands/mcp) command and [`4D.MCPContext`](../API/MCPContextClass.md) class to [ask the user for a confirmation](../WebServer/mcp-server.md#asking-the-user-for-confirmation) in MCP tools. +- A reference [MCP Bundle](../WebServer/mcp-server.md#claude-desktop-bundle) lets Claude Desktop connect to a 4D MCP server on the local network. + +#### Behavior changes + +- The compiler now reports [warnings on function comments](../Project/compiler.md#warnings-on-function-comments): a class function or class constructor that has a comment block above its declaration gets a warning for each parameter without a `$name:` comment, and for contradictory MCP behavior tags. + + ## 4D 21 R5 Read [**What’s new in 4D 21 R5**](https://blog.4d.com/whats-new-in-4d-21-r5/), the blog post that lists all new features and enhancements in 4D 21 R5. @@ -21,8 +40,9 @@ Read [**What’s new in 4D 21 R5**](https://blog.4d.com/whats-new-in-4d-21-r5/), - New [`WebServer.quotas`](../API/WebServerClass.md#quotas) property and enhanced [`4D.QuotaManager`](../API/QuotaManagerClass.md) class to configure [Web server quotas](../WebServer/quotas.md). - Text Area and Input objects: New [top padding](../FormObjects/properties_CoordinatesAndSizing.md#top-padding), [bottom padding](../FormObjects/properties_CoordinatesAndSizing.md#bottom-padding), [left padding](../FormObjects/properties_CoordinatesAndSizing.md#left-padding), [right padding](../FormObjects/properties_CoordinatesAndSizing.md#right-padding) with related [CSS support](../FormEditor/createStylesheet.md#attribute-mapping). Support for [vertical alignment](../FormObjects/properties_Text.md#vertical-alignment). - New [`OBJECT SET PADDING`](../commands/object-set-padding) and [`OBJECT Get padding`](../commands/object-get-padding) commands to manage padding by programming. -- New inner border design for [custom buttons](../FormObjects/button_overview.md#custom), [custom check boxes](../FormObjects/checkbox_overview.md#custom) and [custom radio buttons](../FormObjects/radio_overview.md#custom): support of [fill color](../FormObjects/properties_BackgroundAndBorder.md#background-color--fill-color) and [corner radius](../FormObjects/properties_BackgroundAndBorder.md#corner-radius) properties; new [border color](../FormObjects/properties_BackgroundAndBorder.md#border-color) and [border width](../FormObjects/properties_BackgroundAndBorder.md#border-width) properties. -- Direct access to the [4D Corner platform](https://corner.4d.com/) from the [Dependency manager](../Project/components.md#using-4d-corner). +- New inner border design for [custom buttons](../FormObjects/button_overview.md#custom), [custom check boxes](../FormObjects/checkbox_overview.md#custom) and [custom radio buttons](../FormObjects/radio_overview.md#custom): support of [fill color](../FormObjects/properties_BackgroundAndBorder.md#background-color--fill-color) and [corner radius](../FormObjects/properties_BackgroundAndBorder.md#corner-radius) properties; new [Border width](../FormObjects/properties_BackgroundAndBorder.md#border-width) property. +- Support of ["System rounded" border line style](../FormObjects/properties_BackgroundAndBorder.md#border-line-style) property for [inputs](../FormObjects/input_overview.md), compliant with macOS *Liquid glass* design. Also supported by [`OBJECT SET BORDER STYLE`](../commands/object-set-border-style) and [`OBJECT GET BORDER STYLE`](../commands/object-get-border-style) commands. +- New ["Border color" property](../FormObjects/properties_BackgroundAndBorder.md#border-color) available for most form objects. [`OBJECT SET RGB COLORS`](../commands/object-set-rgb-colors) and [`OBJECT GET RGB COLORS`](../commands/object-get-rgb-colors) commands support a new *borderColor* parameter. - [New **Code editor** preference](../Preferences/methods.md#code-editor) to use automatically the 4D code editor or VS Code when creating or opening 4D methods and classes. - [**Fixed bug list**](https://bugs.4d.fr/fixedbugslist?version=21_R5): list of all bugs that have been fixed in 4D 21 R5. @@ -39,6 +59,7 @@ In 4D 21 R5 and higher, vectors are created with a [32-bit precision by default] + ## 4D 21 R4 Read [**What’s new in 4D 21 R4**](https://blog.4d.com/whats-new-in-4d-21-r4/), the blog post that lists all new features and enhancements in 4D 21 R4. diff --git a/docs/ORDA/ordaClasses.md b/docs/ORDA/ordaClasses.md index e6efa26ad6d232..1a8358df8d89a7 100644 --- a/docs/ORDA/ordaClasses.md +++ b/docs/ORDA/ordaClasses.md @@ -66,6 +66,7 @@ Also, object instances from ORDA data model user classes benefit from their pare |Release|Changes| |---|---| +|21 R6|Support for the `MCP` keyword. New reserved `mcpAuthenticated()` and `mcpGrant()` DataStore class functions. |21 R3|Support for the `server` keyword. |19 R4|Alias attributes in the Entity Class |19 R3|Computed attributes in the Entity Class @@ -83,6 +84,8 @@ A 4D database exposes its own DataStore class in the `cs` class store. You can create functions in the DataStore class that will be available through the `ds` object. +The `mcpAuthenticated()` and `mcpGrant()` function names are reserved for the [MCP server](../WebServer/mcp-server.md) (see [`Function mcpAuthenticated`](#function-mcpauthenticated) and [`Function mcpGrant`](#function-mcpgrant)). + #### Example @@ -1142,3 +1145,157 @@ It can be called by the following HTTP GET request: IP:port/rest/Products/getThumbnail?$params='["Yellow Pack",200,200]' ``` + +## MCP functions + +The [MCP server](../WebServer/mcp-server.md) of the 4D Web Server publishes data model class functions as tools for AI clients, and calls specific functions of the DataStore class to authenticate the clients. + +### `exposed MCP Function` + +#### Syntax + +```4d +exposed MCP Function ({$parameterName : type; ...}){->$parameterName : type} +// code +``` + +The `MCP` keyword publishes an exposed function as a [custom tool](../WebServer/mcp-server.md#custom-tools) of the MCP server. It is a second opt-in on top of the `exposed` keyword: + +- a function declared `exposed` without `MCP` can be called by REST requests but is not an MCP tool, +- a function declared with `MCP` but without `exposed` is not published at all. + +The `MCP` keyword is supported in the following classes: + +- the DataStore class: the tool name is the function name, +- DataClass classes and Entity classes: the tool name is `ClassName-functionName`, +- shared [singleton classes](../Concepts/classes.md#singleton-classes): the tool name is `ClassName-functionName`. + +Functions of EntitySelection classes are not published. + +The [comment block](../Concepts/classes.md#function-comments) written above the declaration describes the tool and its parameters for the AI client. The client can call the tool if its session has the **execute** permission on the function in the [`roles.json`](privileges.md#rolesjson-file) file, as for a REST request. + +**Entity class functions** + +A tool published from an Entity class function gets a required `key` argument (string or integer): the primary key of the entity on which the function is called. 4D loads this entity as `This`, with the **read** permission of the dataclass and its [restriction filter](entities.md#restricting-entity-selections). If the entity cannot be found or read, the call returns the "Entity not found" error and the function does not run. + +An Entity class function that declares a `$key` parameter is not published, and 4D logs a message. + +#### Example + +You publish an Entity class function. The client calls the tool with the primary key of the invoice in the `key` argument: + +```4d +// cs.InvoiceEntity class +Class extends Entity + +// Returns the amount still due on the invoice +// MCP: @readOnly +exposed MCP Function getAmountDue() : Real + return This.amount-This.payments.sum("amount") +``` + + +### `Function mcpAuthenticated` + +#### Syntax + +```4d +// DataStore class +Function mcpAuthenticated($info : Object) +// code +``` + +The `mcpAuthenticated()` function of the DataStore class is called by 4D when an [MCP session](../WebServer/mcp-server.md#mcp-sessions) is created, after the privileges of the token are applied and before any other code of the application runs for this session. It is called once per session. + +Use it to prepare the session from the information stored with the token, for example to fill [`Session.storage`](../API/SessionClass.md#storage) with the current values of the user, which your [restriction filters](entities.md#restricting-entity-selections) can use. + +The *$info* parameter contains: + +|Property|Type|Description| +|---|---|---| +|type|Text|"fineGrainedToken" for a [Fine-Grained Token](../WebServer/mcp-server.md#fine-grained-tokens), "oauth" for an [OAuth](../WebServer/mcp-server.md#oauth-21-mode) access token| +|id|Text|Identifier of the token or of the OAuth grant| +|name|Text|Fine-Grained Token: name of the token| +|userName|Text|OAuth: user name of the grant| +|clientId|Text|OAuth: identifier of the MCP client| +|clientName|Text|OAuth: name of the MCP client| +|privileges|Text, Collection or Object|Privileges and roles of the token or of the grant| +|expiry|Text|Fine-Grained Token: expiration date of the token| +|expiresAt|Text|OAuth: expiration date and time of the grant| +|info|Object|Fine-Grained Token: *info* object passed to [`ds.generateFineGrainedToken()`](../API/DataStoreClass.md#generatefinegrainedtoken) (*Null* if none)| +|createdAt|Text|Date and time of the token generation or of the login| +|IPAddress|Text|IP address of the MCP client| + +The following rules apply: + +- Only 4D calls this function. A REST request or a remote datastore call to `mcpAuthenticated()` gets an HTTP 403 error, even if the function is declared `exposed` (in this case, 4D also logs a warning). +- The function cannot change the privileges of the session: calling [`Session.setPrivileges()`](../API/SessionClass.md#setprivileges) or [`Session.clearPrivileges()`](../API/SessionClass.md#clearprivileges) in it raises an error. +- The function cannot refuse the session. To stop the access of a user, revoke their tokens with [`ds.revokeFineGrainedToken()`](../API/DataStoreClass.md#revokefinegrainedtoken) or [`ds.revokeOAuthGrant()`](../API/DataStoreClass.md#revokeoauthgrant). +- If the function fails, 4D logs an error and the session is still created. + +#### Example + +You store the user of the token in the session storage: + +```4d +// cs.DataStore class +Class extends DataStoreImplementation + +Function mcpAuthenticated($info : Object) + var $login : Text:=($info.type="oauth") ? $info.userName : $info.info.userName + var $user : cs.UsersEntity:=ds.Users.query("login = :1"; $login).first() + If ($user#Null) + Use (Session.storage) + Session.storage.user:=New shared object("ID"; $user.ID; "name"; $user.name) + End use + End if +``` + + +### `Function mcpGrant` + +#### Syntax + +```4d +// DataStore class +Function mcpGrant($user : Text; $password : Text; $clientId : Text) : Variant +// code +``` + +When the DataStore class defines the `mcpGrant()` function, the [OAuth 2.1 mode](../WebServer/mcp-server.md#oauth-21-mode) of the MCP server is enabled. 4D calls this function when a user submits the login page of the MCP server, to check the credentials and get the privileges to give to the user in this MCP client. + +The function receives: + +- *$user* and *$password*: the user name and the password entered in the login page, +- *$clientId*: the identifier of the MCP client (the URL of its metadata document, or the id issued at its [registration](../WebServer/mcp-server.md#client-registration)). + +It returns the privileges to give, in any form accepted by [`Session.setPrivileges()`](../API/SessionClass.md#setprivileges): + +- a privilege name, or several comma-separated privilege names (Text), +- a collection of privilege names, +- an object with `privileges` and/or `roles` properties. The object can also contain a `userName` property: it becomes the user name of the grant and of the MCP sessions (otherwise, *$user* is used). + +An empty value or *Null* refuses the login. A privilege or role that is not declared in the [`roles.json`](privileges.md#rolesjson-file) file also refuses the login, and 4D logs a message. + +The following rules apply: + +- Only 4D calls this function. A REST request or a remote datastore call to `mcpGrant()` gets an HTTP 403 error, even if the function is declared `exposed` (in this case, 4D also logs a warning). +- The function runs in a session without privileges. It cannot change the privileges of the session: calling [`Session.setPrivileges()`](../API/SessionClass.md#setprivileges) or [`Session.clearPrivileges()`](../API/SessionClass.md#clearprivileges) in it raises an error. +- Never store or compare passwords in clear: use [`Generate password hash`](../commands/generate-password-hash) and [`Verify password hash`](../commands/verify-password-hash). + +#### Example + +Users are stored in the Users dataclass, with a hashed password and a role: + +```4d +// cs.DataStore class +Class extends DataStoreImplementation + +Function mcpGrant($user : Text; $password : Text; $clientId : Text) : Variant + var $account : cs.UsersEntity:=ds.Users.query("login = :1"; $user).first() + If ($account=Null) || (Not(Verify password hash($password; $account.password))) + return Null // login refused + End if + return {roles: $account.role; userName: $account.login} +``` + diff --git a/docs/ORDA/privileges.md b/docs/ORDA/privileges.md index 847778b2bc4c1e..fb679eeccba7a4 100644 --- a/docs/ORDA/privileges.md +++ b/docs/ORDA/privileges.md @@ -74,6 +74,35 @@ Available actions are related to target resource. Setting permissions requires to be consistent, in particular **update** and **drop** permissions also need **read** permission (but **create** does not need it). +### MCP tools + +The same permissions apply to the sessions of the [MCP server](../WebServer/mcp-server.md), with nothing specific to configure: + +- A [custom tool](../WebServer/mcp-server.md#custom-tools) (`exposed MCP Function`) requires the **execute** permission on its function, and benefits from its **promote** permission. +- The [built-in CRUD tools](../WebServer/mcp-server.md#built-in-crud-tools) require the **read**, **create**, **update**, or **drop** permission on the dataclass, and the attribute permissions apply. Each attribute of a path used in a filter, a sort, or a projection requires the **read** permission. +- The CRUD tools are listed only if the session has at least one data permission on a dataclass, and the `describeModel` tool only describes the dataclasses on which the session has a data permission, with their readable or writable attributes. +- A tool, a dataclass, or an attribute that the session cannot access is reported as if it did not exist. + +#### Example + +MCP clients authenticated with the "salesReader" privilege can read the Customer and Order dataclasses with the CRUD tools, and call the tools published by the `OrderManager` singleton (for example `OrderManager-getYearTotal`): + +```json +{ + "privileges": [{"privilege": "salesReader", "includes": []}], + "roles": [], + "permissions": { + "allowed": [ + {"applyTo": "Customer", "type": "dataclass", "read": ["salesReader"]}, + {"applyTo": "Order", "type": "dataclass", "read": ["salesReader"]}, + {"applyTo": "OrderManager", "type": "singleton", "execute": ["salesReader"]} + ] + }, + "restrictedByDefault": true +} +``` + + ### Inherited permissions diff --git a/docs/Project/architecture.md b/docs/Project/architecture.md index 6b43818dcf7890..1632398af8f428 100644 --- a/docs/Project/architecture.md +++ b/docs/Project/architecture.md @@ -161,6 +161,8 @@ Within these folders, deleted element names are in parentheses, e.g. "(myMethod) The DerivedData folder contains cached data used internally by 4D to optimize processing. It is automatically created or recreated when necessary. You can ignore this folder. +When the project is compiled, 4D also generates in this folder the `syntaxMCP.json` file, which contains the [MCP tool metadata](../Concepts/classes.md#mcp-tool-metadata) of the `exposed MCP Function` class functions. This file is not used if a `syntaxMCP.json` file exists in the [`Resources`](#resources) folder. + ## `Libraries` > This folder is used on macOS only. @@ -175,6 +177,7 @@ Contents|Description|Format --------|-------|---- *item*|Project resource files and folders|various Images/Library/*item*|Pictures from the Picture Library as separate files(*). Names of these items become file names. If a duplicate exists, a number is added to the name.|picture +syntaxMCP.json|Custom [MCP tool metadata](../Concepts/classes.md#mcp-tool-metadata). If this file exists, it is used instead of the `Project/DerivedData/syntaxMCP.json` file generated at compilation. The compiler never modifies it.|JSON (*) only if the project was exported from a .4db binary database. diff --git a/docs/Project/compiler.md b/docs/Project/compiler.md index c115826c26e907..1280524624d2e4 100644 --- a/docs/Project/compiler.md +++ b/docs/Project/compiler.md @@ -28,6 +28,8 @@ If no errors are detected, the actual compilation begins and the "Compilation su You can immediately [run your application in compiled mode](#run-compiled) and see how faster it is. +When the compilation succeeds, the compiler also generates the `Project/DerivedData/syntaxMCP.json` file, which contains the [MCP tool metadata](../Concepts/classes.md#mcp-tool-metadata) of the project, whatever the [syntax file setting](../Extensions/develop-components.md#code-completion-for-compiled-components). + If errors are detected, the process is stopped and the "Compilation failed" message is displayed. The information area of the window displays the method names and line numbers concerned in a hierarchical list: ![](../assets/en/Project/compilerWin2.png) @@ -289,6 +291,23 @@ The special warnings comments have priority over the warnings display settings s ::: +### Warnings on function comments + +When a class function or a class constructor has a [comment block above its declaration](../Concepts/classes.md#function-comments), the compiler checks it and reports a warning: + +- for each parameter of the signature that is not documented by a `$name:` or `{$name}:` line (variadic parameters are not checked), +- when the `MCP:` behavior tags contradict each other (`@readOnly`, `@destructive`, and `@additive` used together). In this case, the corresponding hints are omitted from the [MCP tool metadata](../Concepts/classes.md#mcp-tool-metadata). + +Functions without a comment block are not checked. For example, the following function generates a warning for the *$factor* parameter and a warning for the `@readOnly` and `@destructive` tags: + +```4d +// Scales a value by a factor +// MCP: @readOnly @destructive +// $value: value to scale +Function scale($value : Real; $factor : Real) : Real + return $value*$factor +``` + ## Compilation tools ### Symbol file diff --git a/docs/WebServer/mcp-server.md b/docs/WebServer/mcp-server.md new file mode 100644 index 00000000000000..4573b27cb3bf2f --- /dev/null +++ b/docs/WebServer/mcp-server.md @@ -0,0 +1,581 @@ +--- +id: mcp-server +title: MCP server +--- + +
    History + +|Release|Changes| +|---|---| +|21 R6|Added| + +
    + +The 4D Web Server includes a native [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server. AI assistants and agents (Claude Desktop, Claude Code, MCP Inspector, etc.) can connect to it to discover and call the business logic and the data of your application. + +The MCP server publishes two kinds of **tools**: + +- the [custom tools](#custom-tools) that you write as ORDA or singleton class functions declared with `exposed MCP Function`, +- the [built-in CRUD tools](#built-in-crud-tools), which let a client read and write data of the datastore. + +You do not need to write the MCP layer: 4D generates the tool catalog, converts the arguments and the results, and applies the same [roles and privileges](../ORDA/privileges.md) as for REST requests. Clients authenticate with a [Fine-Grained Token](#fine-grained-tokens) generated by your application, or through the optional [OAuth 2.1 mode](#oauth-21-mode). + +## Enabling the MCP server + +The MCP server is disabled by default. It requires: + +- the web server of the host application (the MCP server is not available on [component web servers](webServerObject.md)), +- [scalable sessions](sessions.md#enabling-web-sessions). If scalable sessions are disabled, the MCP server does not start, 4D logs a message in the [diagnostic log](../Debugging/debugLogFiles.md#4ddiagnosticlogtxt), and `/mcp` answers 404. + +You enable the MCP server with the `enabled` property of the [`mcp`](../API/WebServerClass.md#mcp) object of the web server. You can set it in the *settings* parameter of [`.start()`](../API/WebServerClass.md#start), or at runtime without restarting the web server: + +```4d +var $webServer : 4D.WebServer:=WEB Server +$webServer.mcp.enabled:=True // /mcp now accepts MCP requests +``` + +When you set `mcp.enabled` to **False**, the calls being executed finish and get their response, every later request gets a 404 status, and the MCP sessions are closed (their licenses are released). + +The [`mcp`](../API/WebServerClass.md#mcp) object also contains the other MCP server settings (server name, instructions, allowed tools, proxies, etc.). These settings are kept when the web server is restarted. + +#### Example + +You start the web server with the MCP server enabled and a description of the application for the clients: + +```4d +var $settings:={mcp: {enabled: True; serverName: "Sales"; instructions: "Call describeModel first to learn the data model."}} +var $status:=WEB Server.start($settings) +``` + +## MCP endpoint + +The MCP server answers on the `/mcp` URL of the web server (for example `https://myserver.example.com/mcp`). It implements the stateless MCP revision **2026-07-28** only, over HTTP or HTTPS. + +Every request is a self-describing `POST` request: + +- its body is a single JSON-RPC 2.0 request, +- the `MCP-Protocol-Version` header contains `2026-07-28`, +- the `Mcp-Method` header contains the JSON-RPC method, and the `Mcp-Name` header contains the tool name for `tools/call`. These headers must match the body. A value that is not plain ASCII is sent as `=?base64??=`, +- the `Authorization: Bearer ` header contains the [token](#authentication), except for `server/discover` and `ping`. + +For example: + +``` +POST /mcp HTTP/1.1 +Host: myserver.example.com +Content-Type: application/json +Authorization: Bearer 4dfgt_... +MCP-Protocol-Version: 2026-07-28 +Mcp-Method: tools/call +Mcp-Name: queryEntities + +{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "queryEntities", "arguments": {"dataClass": "Customer", "filter": "city = :1", "params": ["Paris"]}}} +``` + +Responses are `application/json`. Every result contains a `resultType` property (`"complete"`, or `"input_required"` when the user must [answer a question](#asking-the-user-for-confirmation)). 4D never reads nor sends an `Mcp-Session-Id` header. + +The following methods are supported: + +|Method|Token required|Description| +|---|---|---| +|`server/discover`|No|Returns the capabilities of the server (see below)| +|`ping`|No|Returns an empty result| +|`tools/list`|Yes|Returns the [tool catalog](#tool-catalog) of the session| +|`tools/call`|Yes|Calls a [custom tool](#calling-a-custom-tool) or a [built-in CRUD tool](#built-in-crud-tools)| + +Clients may call `tools/list` and `tools/call` directly, without calling `server/discover` first. The legacy `initialize` request of previous MCP revisions is not supported. + +#### `server/discover` + +The `server/discover` result is the same for all callers. It contains: + +|Property|Description| +|---|---| +|`supportedVersions`|`["2026-07-28"]`| +|`capabilities`|`{"tools": {"listChanged": false}}`| +|`_meta["io.modelcontextprotocol/serverInfo"]`|`name`: [`mcp.serverName`](../API/WebServerClass.md#mcp), or the application name by default. `version`: `mcp.serverVersion`, or by default the version of the built application (`"0.0.0"` if the application is not built)| +|`instructions`|[`mcp.instructions`](../API/WebServerClass.md#mcp) (empty by default)| +|`cacheScope`|`"public"`| +|`ttlMs`|`3600000` (the client can keep the result for one hour)| + +#### Example + +You check from 4D that the MCP server answers on the local machine: + +```4d +var $headers:={} +$headers["MCP-Protocol-Version"]:="2026-07-28" +$headers["Mcp-Method"]:="server/discover" + +var $request:=4D.HTTPRequest.new("http://127.0.0.1/mcp"; {method: "POST"; headers: $headers; body: {jsonrpc: "2.0"; id: 1; method: "server/discover"}}) +$request.wait() +// $request.response.status is 200 +// $request.response.body.result.supportedVersions is ["2026-07-28"] +``` + +### Request checks and errors + +4D checks each request in the following order, before running any code of the application. The first failing check gives the answer: + +|Check|HTTP status|JSON-RPC error| +|---|---|---| +|MCP server disabled|404, no body|| +|Plain HTTP not allowed (see [Secure connections](#secure-connections))|404, no body|| +|Method other than `POST`|405, no body (`Allow: POST`)|| +|`Origin` header present (requests from web browsers)|403, no body|| +|Body is not valid JSON|400|`-32700`| +|Body is not a single JSON-RPC request or notification (batch array, response, missing `jsonrpc` or `method`)|400|`-32600`| +|JSON-RPC notification (no `id`): accepted, nothing is executed|202, no body|| +|Missing `MCP-Protocol-Version`, `Mcp-Method` or `Mcp-Name` header, or header that does not match the body. A legacy `initialize` request gets a message naming the `2026-07-28` revision|400|`-32020`| +|Unsupported protocol version (`data.supported` lists the supported versions)|400|`-32022`| +|Unknown method|404|`-32601`| + +Then, for methods that require a token: + +|Case|HTTP status| +|---|---| +|No token, or unknown, invalid, expired or revoked token|401 (with a `WWW-Authenticate` challenge in [OAuth mode](#oauth-21-mode))| +|No 4D license available for a new MCP session|503 with a `Retry-After` header and the "No 4D license available" JSON-RPC error| +|[Quota](#quotas) exceeded|429 with a `Retry-After` header| + +Errors of the tools themselves are returned as tool results with `isError: true` (see [Calling a custom tool](#calling-a-custom-tool) and [Built-in CRUD tools](#built-in-crud-tools)). A tool that does not exist or that the session is not allowed to call gets the `-32602` "Unknown tool: \" JSON-RPC error. + +## Secure connections + +The MCP server uses the TLS configuration of the web server: there is no specific certificate. For a test server with a self-signed certificate, the certificate must be trusted on the client side (for example with the `NODE_EXTRA_CA_CERTS` environment variable for Node.js clients). + +A token is a long-lived secret: 4D never accepts it in clear over the network. Requests to `/mcp` (and to its [binary URLs](#binary-attributes)) over plain HTTP are only served: + +- from a loopback address (`127.0.0.1`, `::1`), +- or from a reverse proxy listed in [`mcp.trustedProxies`](../API/WebServerClass.md#mcp) that sends `X-Forwarded-Proto: https` (TLS terminated by the proxy). + +Any other plain HTTP request gets a 404 status before authentication, and 4D logs a message in the [diagnostic log](../Debugging/debugLogFiles.md#4ddiagnosticlogtxt). On a local network without a certificate, you can set [`mcp.allowInsecureHTTP`](../API/WebServerClass.md#mcp) to **True** to accept plain HTTP requests (not recommended). This setting never applies to the [OAuth](#oauth-21-mode) endpoints. + +Requests with an `Origin` header are refused (403) to protect the server against DNS rebinding attacks from web browsers. + +#### Proxies and public URL + +4D publishes some URLs (OAuth metadata and endpoints, binary URLs). Their base is: + +- [`mcp.publicURL`](../API/WebServerClass.md#mcp) if it is set (recommended when the server is reachable under several names), +- otherwise the scheme and the `Host` header of the request. The `X-Forwarded-Proto` and `X-Forwarded-Host` headers are only used when the request comes from a proxy listed in `mcp.trustedProxies`. + +The **caller IP address**, used to [identify MCP sessions](#mcp-sessions) and for the [OAuth limits](#client-registration), is the address of the connection or, when the connection comes from a trusted proxy, the rightmost address of the `X-Forwarded-For` header that is not itself a trusted proxy. + +#### Example + +Your 4D server is behind a reverse proxy at 10.0.0.5 that terminates TLS for `https://sales.example.com`: + +```4d +var $webServer : 4D.WebServer:=WEB Server +var $mcp:={enabled: True; trustedProxies: ["10.0.0.5"]; publicURL: "https://sales.example.com"} +var $status:=$webServer.start({mcp: $mcp}) +``` + +## Authentication + +Every request (except `server/discover` and `ping`) carries a token in its `Authorization: Bearer ` header. There is no anonymous MCP session. Two kinds of tokens are accepted side by side: + +||Fine-Grained Token|OAuth 2.1 (optional)| +|---|---|---| +|Who authenticates the user|Your application, its own way, before generating the token|4D, through a login page that calls your [`ds.mcpGrant()`](../ORDA/ordaClasses.md#function-mcpgrant) function| +|Token|`4dfgt_…`|JWT signed by 4D| +|Privileges|Given when the token is generated|Returned by `ds.mcpGrant()`| +|Lifetime|Expiry date chosen at generation (366 days at most)|15 minutes, renewed with a refresh token| +|Revocation|[`ds.revokeFineGrainedToken()`](../API/DataStoreClass.md#revokefinegrainedtoken)|[`ds.revokeOAuthGrant()`](../API/DataStoreClass.md#revokeoauthgrant)| +|Typical use|Services, the [Claude Desktop bundle](#claude-desktop-bundle), applications with their own login|Interactive login of each user in their AI client| + +### Fine-Grained Tokens + +A Fine-Grained Token (FGT) is generated by your application, with the privileges to give to the MCP client, after the user has been authenticated by the application (for example through the [`authentify()`](../REST/authUsers.md#function-authentify) function). You give the token to the user, who enters it in the configuration of the AI client. + +- [`ds.generateFineGrainedToken()`](../API/DataStoreClass.md#generatefinegrainedtoken) creates a token. It can only be called from a web or REST session, and only with privileges that the session holds. +- [`ds.listFineGrainedTokens()`](../API/DataStoreClass.md#listfinegrainedtokens) lists the tokens (never the tokens themselves). +- [`ds.revokeFineGrainedToken()`](../API/DataStoreClass.md#revokefinegrainedtoken) revokes a token. It stops working at the next request. + +The tokens are stored hashed in the `fgt.json` file of the data folder. The token itself is returned only once, at generation. + +When a request comes with an FGT, 4D checks the token at every request, then applies its privileges before running any code of the application. A privilege or role named by the token and removed since from the `roles.json` file is ignored (4D logs a message). A token left without any declared privilege gets a 401 status. + +#### Example + +In the DataStore class, an exposed function lets an authenticated user get a token for their AI client: + +```4d +// cs.DataStore class +Class extends DataStoreImplementation + +exposed Function getMCPToken() : Text + var $expiry:=Add to date(Current date; 0; 3; 0) // valid for 3 months + var $result:=ds.generateFineGrainedToken("salesReader"; "Claude - "+Session.userName; $expiry; {userName: Session.userName}) + return $result.token // "4dfgt_..." +``` + +### MCP sessions + +Requests are stateless, but 4D keeps one web session per token and caller IP address (or per user and client in [OAuth mode](#oauth-21-mode)), so that repeated requests reuse the same session: + +- When the session is created, it consumes a 4D license. If no license is available, the request gets a 503 status and no session is created. +- Its [`Session.info.type`](../API/SessionClass.md#info) is `"mcp"`. MCP sessions are shown with this type in the administration window of 4D Server, and in the results of the [`Process activity`](../commands/process-activity) and [`License usage`](../commands/license-usage) commands. +- Its privileges are those of the token. Then 4D calls the [`ds.mcpAuthenticated()`](../ORDA/ordaClasses.md#function-mcpauthenticated) function of your DataStore class, if defined, once per session: you can use it to fill [`Session.storage`](../API/SessionClass.md#storage) from the information stored with the token. +- The session closes after the [inactivity timeout of web sessions](sessions.md#session-lifetime), when its token is revoked or expires, or when the MCP server is disabled. Its license is then released. + +### OAuth 2.1 mode + +In OAuth mode, 4D is the OAuth authorization server: users log in from their AI client through a 4D login page, without any external identity provider. The OAuth mode is enabled when your DataStore class defines the [`mcpGrant()`](../ORDA/ordaClasses.md#function-mcpgrant) function. Fine-Grained Tokens remain accepted. + +The flow is the standard *authorization code* flow with PKCE (S256): + +1. A request without a valid token gets a 401 status with the `WWW-Authenticate: Bearer resource_metadata="/.well-known/oauth-protected-resource"` header. The client reads this metadata, then the metadata of the authorization server. +2. The client [registers](#client-registration) and opens the authorization URL in the browser. +3. 4D displays its login page. When the user submits it, 4D calls `ds.mcpGrant($user; $password; $clientId)`, which returns the privileges to give, or an empty value to refuse the login. +4. 4D redirects to the client with a one-time code, which the client exchanges for an access token (JWT) and a refresh token. +5. The client sends the access token with every `/mcp` request. 4D checks it and applies the privileges returned by `ds.mcpGrant()`. + +4D serves the following endpoints, under the [public base URL](#proxies-and-public-url): + +|Endpoint|Description| +|---|---| +|`/.well-known/oauth-protected-resource`|Protected resource metadata (RFC 9728)| +|`/.well-known/oauth-authorization-server`|Authorization server metadata (RFC 8414). The issuer is the `/mcp` URL| +|`/mcp/oauth/authorize`|Login page (GET) and login (POST)| +|`/mcp/oauth/token`|Code exchange and token refresh| +|`/mcp/oauth/register`|[Dynamic client registration](#client-registration), when `mcp.oauthDynamicRegistration` is True| + +The metadata URLs are also served with `/mcp` appended (for example `/.well-known/oauth-protected-resource/mcp`). These endpoints answer 404 when the OAuth mode is disabled, and over plain HTTP outside loopback and trusted proxies, whatever the [`mcp.allowInsecureHTTP`](../API/WebServerClass.md#mcp) value. + +**Tokens and grants** + +Each login of a user in a client creates a **grant**, which holds the privileges returned by `ds.mcpGrant()`: + +- The access token is a JWT signed by 4D (HS256), valid 15 minutes. It does not contain the privileges, only the id of its grant: 4D checks at every request that the grant still exists. +- The refresh token is valid 30 days after it is issued, and 90 days after the login at the latest. Each refresh issues a new refresh token. If an already used refresh token is presented again, the whole grant is revoked. +- The authorization code is valid 60 seconds and can be used once. +- OAuth sessions are identified by the user (`sub` claim) and the client, and their user name is the `sub` claim. + +You list the grants with [`ds.listOAuthGrants()`](../API/DataStoreClass.md#listoauthgrants) and revoke them with [`ds.revokeOAuthGrant()`](../API/DataStoreClass.md#revokeoauthgrant): the grant's access tokens get a 401 status from the next request, and its refresh token is refused. When you deactivate a user of your application, revoke their grants and Fine-Grained Tokens. + +:::warning + +The signing key of the access tokens and the grants are stored in the data folder (`fgt.json` file). A copy of this file lets its holder use the existing grants: protect the backups of the data folder like the data itself. + +::: + +:::note + +The login page checks a user name and a password with `ds.mcpGrant()`: single sign-on and multi-factor authentication are not supported in this mode. If you need them, authenticate users your own way and generate [Fine-Grained Tokens](#fine-grained-tokens). + +::: + +### Client registration + +In OAuth mode, a client is identified either by the HTTPS URL of a **Client ID Metadata Document** (CIMD) or by an id issued by **dynamic client registration** (DCR, RFC 7591). This client id is passed to `ds.mcpGrant()` in *$clientId*. + +- **Client ID Metadata Documents**: 4D downloads the document over HTTPS only, from a host name (not an IP address) that resolves to public addresses only (no loopback, private, link-local or multicast address), without following redirects, within 5 seconds and 5 KB. The `client_id` of the document must be its URL. 4D keeps the document in cache according to its HTTP cache headers, between 5 minutes and 24 hours. +- **Dynamic client registration**: available when [`mcp.oauthDynamicRegistration`](../API/WebServerClass.md#mcp) is **True** (default). 4D accepts 10 registrations per caller IP address per hour (429 status beyond), and 1000 dynamic clients in total (503 status beyond). A dynamic client that is not used for 30 days is deleted. +- **Redirect URIs** must be HTTPS URLs, or `http://127.0.0.1` / `http://localhost` URLs on any port. Any other redirect URI is refused, at registration or at authorization. + +The login page displays the name of the client and the domain of its metadata document, or the host of its redirect URI, so that users can check who asks for access. + +To protect the login page against password guessing: + +- after 10 failed logins from one caller IP address within 15 minutes, this address gets a 429 status for 15 minutes, +- after 20 failed logins for one user name within 15 minutes, this user name is refused for 15 minutes, with the same message as a wrong password. + +## Authorization + +The MCP server uses the [`roles.json`](../ORDA/privileges.md) file of the project, exactly as the REST server. There is nothing specific to MCP to configure: + +- a custom tool requires the **execute** permission on its function (and benefits from its **promote** permission), +- the built-in CRUD tools require the **read**, **create**, **update**, or **drop** permission on the dataclass and its attributes, +- `restrictedByDefault` applies to the tools as to REST requests. + +The tool catalog only lists the tools that the session can call, but every call is checked again. A tool that the session cannot call gets the same "Unknown tool" error as a tool that does not exist (the reason is logged on the server). + +Data accessed through the tools goes through ORDA, so [restricted entity selections](../ORDA/entities.md#restricting-entity-selections) (`Function event restrict`) apply. You can filter differently for MCP sessions by testing `Session.info.type`. + +#### Example + +MCP clients only see the orders of the user whose ID was stored in `Session.storage` by [`ds.mcpAuthenticated()`](../ORDA/ordaClasses.md#function-mcpauthenticated): + +```4d +// cs.Order class +Class extends DataClass + +Function event restrict() : cs.OrderSelection + If (Session#Null) && (Session.info.type="mcp") + return This.query("ownerID = :1"; Session.storage.user.ID) + End if + return Null // no filter for other sessions +``` + +## Custom tools + +You publish a class function as an MCP tool by declaring it with the `exposed` and `MCP` keywords: + +```4d +exposed MCP Function () : +``` + +Functions of the following classes can be published: + +- the DataStore class, +- DataClass classes, +- Entity classes, +- shared singleton classes. + +Functions declared without `exposed` or without `MCP`, and functions of EntitySelection classes, are not published. See [`exposed MCP Function`](../ORDA/ordaClasses.md#exposed-mcp-function). + +The [comment block](../Concepts/classes.md#function-comments) written above the declaration provides the description of the tool, of its parameters, and its behavior tags. A function without description is published, with a warning in the diagnostic log. + +#### Example + +You publish a function of a shared singleton class as a read-only tool: + +```4d +// cs.OrderManager shared singleton class +shared singleton Class constructor() + +// Returns the total amount of the orders of a customer for a year +// $customerID: ID of the customer +// $year: year of the orders +// MCP: @readOnly @idempotent +exposed MCP Function getYearTotal($customerID : Integer; $year : Integer) : Real + return ds.Order.query("customer.ID = :1 and year = :2"; $customerID; $year).sum("amount") +``` + +This function is published as the `OrderManager-getYearTotal` tool. + +### Tool catalog + +The `tools/list` method returns the custom tools for which the session has the **execute** permission, and the [built-in CRUD tools](#built-in-crud-tools) when the session has a data permission. Tools are sorted by name, in pages of 100 tools (`cursor` / `nextCursor`). + +The catalog is built from the running code: in interpreted mode, a function you add or modify appears at the next `tools/list`, without restarting. Each page contains a `cacheScope: "private"` property and a `ttlMs` property (`0` in interpreted mode, `300000` in compiled mode) that tells the client how long it can keep the catalog. + +Each tool is described as follows: + +- **name**: `ClassName-functionName`, or the function name for a DataStore class function. The name must match `^[A-Za-z0-9_-]{1,64}$` and must not be the name of another tool, including a built-in CRUD tool. Otherwise, the function is not published and 4D logs a message. +- **description**: the `MCP:` description lines of the comment block, or its description lines. +- **inputSchema**: an object with one property per parameter, named without the `$`, with the types converted to JSON Schema as described in [MCP tool metadata](../Concepts/classes.md#mcp-tool-metadata), and `"additionalProperties": false`: + - every parameter is required, except those documented with `{$name}`, + - typed variadic parameters (`... : Type`) are an optional `args` array (a function that declares both `$args` and variadic parameters is not published), + - a function of an Entity class gets a required `key` property (string or integer): the primary key of the entity on which the function is called. A function of an Entity class that declares a `$key` parameter is not published. +- **outputSchema**, derived from the return type: + +|Return type|outputSchema| +|---|---| +|`cs.Entity`|Schema of the entity, with the attributes the session can read| +|`cs.Selection`|`{entities, total, truncated}`| +|User class|Properties declared with the `property` keyword| +|Collection|`{result: array}`| +|Object, Variant, scalar types, no return|No output schema| + +- **annotations**: the hints of the [behavior tags](../Concepts/classes.md#mcp-tool-metadata). `openWorldHint` is `false` unless the function uses `@openWorld`. Contradictory hints are omitted. Annotations are hints for the client: they do not protect anything (see [Asking the user for confirmation](#asking-the-user-for-confirmation)). + +### Calling a custom tool + +When a client calls a custom tool (`tools/call`), 4D checks the **execute** permission, then the arguments: + +- An argument that is missing, unknown, or whose type does not match the schema gives an `isError` result "Invalid parameters", and the function does not run. +- Arguments are converted: a `YYYY-MM-DD` string to a Date, a number of seconds to a Time, a base64 string to a `4D.Blob` or a Picture, and a number to a Real for a Variant parameter. +- Arguments are passed in the order of the parameters, up to the last one provided: trailing omitted parameters are not passed ([`Count parameters`](../commands/count-parameters) returns the number of arguments provided), and an omitted parameter followed by a provided one gets the default value of its type. The `args` items are passed after the declared parameters. +- For an Entity class function, `This` is the entity of `key`, loaded with the **read** permission of the dataclass and its restriction filter. An unknown, filtered, or invisible key gives the "Entity not found" error. + +The function runs in the MCP session, with the same permissions as a REST call. The value it returns is converted into a tool result: + +|Returned value|Result| +|---|---| +|Text, number, Boolean, Date, Time|Text content (dates as `YYYY-MM-DD`, times in seconds)| +|Object|`structuredContent` with the object, and its text rendering| +|Collection|`structuredContent` with `{result: [...]}`| +|Entity|The entity, serialized as by the [CRUD tools](#entities-in-results) with the attributes the session can read (`null` if the session cannot read it)| +|Entity selection|`{entities, total, truncated}`: at most [`mcp.maxResults`](../API/WebServerClass.md#mcp) entities| +|Blob, Picture|A download URL, valid 10 minutes (see [Binary attributes](#binary-attributes))| + +In returned objects and collections, dates are in ISO format, binary values are download URLs, entities are `{__KEY, __DATACLASS}` and entity selections are `{__DATACLASS, __COUNT}`. + +If the function throws an error, the result is an `isError` result with the error message. If the client disconnects during the call, the function runs to its end and its result is discarded. + +:::caution + +Data read with a **promote** permission and returned in an object or a collection built by your code is returned as is, whatever the privileges of the session. + +::: + +#### Example + +You call the `OrderManager-getYearTotal` tool with: + +```json +{"name": "OrderManager-getYearTotal", "arguments": {"customerID": 120, "year": 2026}} +``` + +The result contains a text content with the amount, for example `"15240.5"`. If the function throws an error, the client gets it as a tool error: + +```4d +exposed MCP Function getYearTotal($customerID : Integer; $year : Integer) : Real + If ($year>Year of(Current date)) + throw(1; "The year cannot be in the future") + End if + return ds.Order.query("customer.ID = :1 and year = :2"; $customerID; $year).sum("amount") +``` + +## Asking the user for confirmation + +A custom tool can ask the user to confirm an action or to provide values before running it. The [`MCP`](../commands/mcp) command returns the [`4D.MCPContext`](../API/MCPContextClass.md) object of the current call: + +1. The function calls [`MCP.requireInput()`](../API/MCPContextClass.md#requireinput) with the fields to display, and returns. 4D answers the call with `resultType: "input_required"`, a form (`elicitation/create`), and a `requestState` signed by 4D. +2. The client displays the form to the user, then calls the tool again with the same arguments, the answers (`inputResponses`), and the `requestState`. +3. 4D checks the `requestState` and runs the function again **from the top**. [`MCP.hasInput()`](../API/MCPContextClass.md#hasinput) now returns **True** and [`MCP.input`](../API/MCPContextClass.md#input) contains the answers. + +The `requestState` is signed by 4D for the token (or OAuth grant), the tool, the converted arguments, the requested fields, and the *bind* value passed to `requireInput()`. It is valid 10 minutes, and until the MCP server is disabled. If it is missing, modified, expired, or if the arguments changed, the answers are ignored and the input is asked again. The confirmation is therefore enforced by 4D, whatever the client. + +- If the client does not support forms (no `elicitation` capability), `MCP.requireInput()` asks nothing and the call returns the `isError` result "This action requires a confirmation your client cannot display": the action never runs. +- Do not ask for secrets such as passwords with `MCP.requireInput()`. +- The *bind* value is signed, not encrypted: the client can read it. + +#### Example + +You want the user to confirm the cancellation of an invoice: + +```4d +// cs.InvoiceEntity class +Class extends Entity + +// Cancels the invoice +exposed MCP Function cancel() : Text + If (Not(MCP.hasInput("confirm"))) + MCP.requireInput({message: "Cancel invoice "+String(This.number)+"?"; confirm: {type: "boolean"; title: "Cancel the invoice"}}; This.getStamp()) + return + End if + If (MCP.bound#This.getStamp()) // the invoice was modified after the confirmation was asked + MCP.error("The invoice was modified, please try again") + return + End if + If (MCP.input.confirm) + This.status:="cancelled" + This.save() + End if + return This.status +``` + +## Built-in CRUD tools + +The built-in CRUD tools let a client read and write the data of the datastore without custom code. They are listed when the session has at least one data permission (**read**, **create**, **update**, or **drop**) on a dataclass, and each call requires the corresponding permission: + +|Tool|Arguments|Result|Permission| +|---|---|---|---| +|`describeModel`|None|The dataclasses the session can access, their readable or writable attributes, and their relations to these dataclasses|Any data permission| +|`getEntity`|`dataClass`, `key`, `attributes`|The entity|read| +|`queryEntities`|`dataClass`, `filter`, `params`, `attributes`, `orderBy`, `limit`, `skip`|`{entities, total, skip, nextSkip}`|read| +|`aggregateEntities`|`dataClass`, `attribute`, `filter`, `params`|`count`, and with `attribute`: `countNotNull`, `sum`, `average`, `min`, `max`|read| +|`addEntity`|`dataClass`, `data`|The created entity|create| +|`updateEntity`|`dataClass`, `key`, `data`, `stamp`|The updated entity|update| +|`dropEntity`|`dataClass`, `key`, `stamp`|Drops the entity after a confirmation of the user|drop| +|`getBinaryAttribute`|`dataClass`, `key`, `attribute`|A picture, or a download URL|read| +|`setBinaryAttribute`|`dataClass`, `key`, `attribute`, `data`, `mimeType`|Stores the value, or returns an upload URL|update| + +- `key` is the primary key of the entity, as a string or an integer. +- `attributes` is a collection of attribute paths to return (dotted paths for related attributes, for example `["lastName"; "employer.name"]`). By default, all the attributes the session can read are returned. +- `limit` is the maximum number of entities to return: 20 by default, between 1 and [`mcp.maxResults`](../API/WebServerClass.md#mcp). `skip` is the number of entities to skip (0 by default): to read the next page, pass the `nextSkip` value of the previous page. `nextSkip` is `null` on the last page. +- `orderBy` contains attribute paths followed by `asc` or `desc` (for example `"lastName asc, salary desc"`). Entities are sorted by `orderBy`, then by primary key, so that pages neither skip nor repeat entities. +- In `aggregateEntities`, `average` is `sum/countNotNull`. `sum` and `average` are `null` for non-numeric attributes. +- In `data`, attributes are given by name. Dates are `YYYY-MM-DD` strings and times are numbers of seconds. An N-to-1 relation is set with the primary key of the related entity: `{"employer": {"__KEY": "12"}}` (an optional `__DATACLASS` must match the related dataclass, and the related entity must be readable). Binary attributes (use `setBinaryAttribute`), 1-to-N relations, read-only attributes, `__KEY` and `__STAMP` are refused. +- `addEntity` always creates a new entity. +- In `updateEntity` and `dropEntity`, pass in `stamp` the `__STAMP` value you read: the operation is refused if the entity was modified since. +- `dropEntity` always asks the user to confirm the deletion (a `confirm` boolean field, see [Asking the user for confirmation](#asking-the-user-for-confirmation)). The entity is dropped only when the confirmation comes from the user's answers, never from the arguments. + +You can restrict the available tools with the [`mcp.crudTools`](../API/WebServerClass.md#mcp) setting (all nine tools by default). A tool that is not in this collection is not listed and gets the "Unknown tool" error. An unknown name in this collection is ignored, and 4D logs a message. + +The CRUD tools use the same permissions, restriction filters, and attribute permissions as REST requests. A dataclass or an attribute that the session cannot see gets the same error as one that does not exist, while a visible one with a forbidden operation gets the "Insufficient privileges for \ on \" error. + +#### Example + +You only want to publish the read tools: + +```4d +var $mcp:={enabled: True; crudTools: ["describeModel"; "getEntity"; "queryEntities"; "aggregateEntities"]} +var $status:=WEB Server.start({mcp: $mcp}) +``` + +### Filters + +The `filter` argument of `queryEntities` and `aggregateEntities` uses the [ORDA query syntax](../API/DataClassClass.md#query), with placeholders (`:1`, `:2`...) whose values are passed in the `params` collection. For example: `"lastName = :1 AND employer.name = :2"`. + +- Operators are `=`, `!=`, `>`, `>=`, `<`, `<=`, `AND`, `OR`, `NOT`, and `@` is the wildcard. Dates are written `YYYY-MM-DD`. +- Each `params` item is a scalar value, `null`, a collection of scalar values, or a vector comparison object `{vector; metric; threshold}`. +- Formulas (including `eval()`) are refused with the "Formulas are not allowed in filter" error. `order by` is refused in `filter` (use `orderBy`). +- Every attribute of a path, including relation attributes, requires the **read** permission. + +### Entities in results + +Entities returned by the tools contain: + +- `__KEY`: the primary key, always as a string, +- `__STAMP`: the stamp of the entity, +- the attributes the session can read. An N-to-1 relation is returned as `{__KEY, __DATACLASS}`, or as an object with the requested attributes when it is projected with `attributes`. 1-to-N relations and binary attributes are not returned. Dates are `YYYY-MM-DD` strings and times are numbers of seconds. + +The tools return their result in `structuredContent`, or an `isError` result with one of the following messages: + +|Message|Case| +|---|---| +|Invalid parameters: ...|Missing, unknown, or invalid argument| +|Formulas are not allowed in filter|`filter` contains a formula| +|Entity not found|Unknown key, entity filtered by a restriction, or invisible dataclass| +|Insufficient privileges for \ on \|The operation is not allowed on a visible dataclass| +|Entity was modified since it was read|The `stamp` does not match (the current stamp is returned)| +|Entity is locked, retry later|The entity is locked by another process| + +### Binary attributes + +Binary contents (pictures and blobs) do not go through the model's context: + +- `getBinaryAttribute` returns a PNG, JPEG, GIF, or WebP picture of 1 MB or less as an `image` content. For any other value, it returns a download URL `{url, method, expiresAt}`: a `GET` request on this URL returns the value with its MIME type. +- `setBinaryAttribute` with base64 `data` of 64 KB or less (once decoded) stores the value directly (`mimeType` is required for a picture). Without `data`, it returns an upload URL: a `PUT` request on this URL with the raw value as body and its `Content-Type` stores the value. Larger inline `data` gets the "Invalid parameters" error. + +Binary URLs have the form `/mcp/binary/`. They are signed by 4D, valid 10 minutes, and do not contain any session id: the URL is the credential, and it remains valid until it expires, even if the token of the session is revoked. An upload URL can be used only once. An invalid, expired, or already used URL gets a 403 status without body. Binary URLs are no longer valid once the MCP server is disabled. The [secure connection](#secure-connections) rules apply to these URLs. + +## Quotas + +MCP requests are web server requests: the [web server quotas](quotas.md) apply to them, and requests over a quota get a 429 status before any code runs. Each MCP session counts in the session quotas. + +#### Example + +You limit each MCP session (and each web session) to 60 requests per minute: + +```4d +var $webServer : 4D.WebServer:=WEB Server +$webServer.quotas.nbRequestsPerMinPerSession:=60 +``` + +## Claude Desktop bundle + +Claude Desktop runs local MCP servers over stdio and does not speak the `2026-07-28` revision. To let it reach a 4D server on the local network without exposing this server on the internet, 4D provides a reference **MCP Bundle** (`.mcpb` file). The bundle is a small Node.js adapter run by Claude Desktop: + +- it answers `initialize` and `ping` itself, and relays the other requests to the 4D `/mcp` URL, +- it authenticates with a Fine-Grained Token when one is entered, otherwise with the [OAuth mode](#oauth-21-mode) (dynamic client registration and login in the browser), +- it displays the forms of [confirmation requests](#asking-the-user-for-confirmation), such as the `dropEntity` confirmation, in a browser page on `127.0.0.1`, since Claude Desktop does not display them, +- when Claude Desktop cancels a request, it cancels the matching request to 4D. + +To install it, open the `.mcpb` file (or drag it in **Settings > Extensions** of Claude Desktop), then fill in the installation form: + +|Field|Description| +|---|---| +|4D MCP server URL|The `/mcp` URL of the 4D web server, for example `https://myserver.local/mcp`| +|Fine-Grained Token|A token generated by the application with [`ds.generateFineGrainedToken()`](../API/DataStoreClass.md#generatefinegrainedtoken). Claude Desktop stores it in the keychain of the system. Leave it empty to log in with OAuth| +|CA certificate|A PEM certificate to trust, for a server whose certificate is self-signed or issued by a private authority| +|Allow insecure connection|**For tests only.** Allows `http://` URLs to another machine and disables the certificate check| + +The bundle refuses to start, and logs why, when the URL is an `http://` URL to another machine and **Allow insecure connection** is not checked, or when no token is entered and the server does not offer OAuth login with dynamic client registration. + +In OAuth mode, the client and its tokens are stored in the `.4d-mcp-bundle` folder of the user's home folder: delete its subfolder to log out. + +Software editors can rebrand the bundle (name, icon, default server URL in its `manifest.json` file) and repackage it for their customers with the `mcpb` tool, as described in its README file. + +## See also + +- [`WebServer.mcp`](../API/WebServerClass.md#mcp) +- [`exposed MCP Function`](../ORDA/ordaClasses.md#exposed-mcp-function) +- [`MCP`](../commands/mcp) command +- [`4D.MCPContext` class](../API/MCPContextClass.md) +- [Roles and privileges](../ORDA/privileges.md) diff --git a/docs/WebServer/quotas.md b/docs/WebServer/quotas.md index 6a00b583f0e799..d168f50088bec2 100644 --- a/docs/WebServer/quotas.md +++ b/docs/WebServer/quotas.md @@ -12,6 +12,12 @@ Web server quotas let you control resource usage by limiting traffic, requests, ::: +:::tip Related Blog post + +[A 4D web server that knows when to say No](https://blog.4d.com/a-4d-web-server-that-knows-when-to-say-no/) + +::: + ## Requirements Quota configuration requires [scalable sessions](./sessions.md#enabling-web-sessions) to be enabled. @@ -101,6 +107,17 @@ If either quota is exceeded, the request is rejected with an **HTTP 429 Too Many If an output byte quota is exceeded while a response is being sent, the current request is interrupted. The preprocessing rules above apply to the next request in the same time window. +### MCP requests + +Requests to the [MCP server](mcp-server.md) (`/mcp` URL) are Web server requests: they count in the server global quotas, and each MCP session counts as a session in the session quotas. Requests over a quota get the **HTTP 429 Too Many Requests** response before any 4D code runs, including authentication code. + +For example, to limit each session, including MCP sessions used by AI agents, to 30 requests per minute: + +```4d +var $webServer : 4D.WebServer:=WEB Server +$webServer.quotas.nbRequestsPerMinPerSession:=30 +``` + ### Rate limiting responses Rate-limiting quotas use fixed time windows. When a quota is reached, subsequent requests are rejected until the current one-minute or one-hour window ends. The **HTTP 429 Too Many Requests** response includes a `Retry-After` header containing the time to wait before sending another request. diff --git a/docs/WebServer/webServerObject.md b/docs/WebServer/webServerObject.md index 7ef6da7f98a2fa..325cf1ecd41649 100644 --- a/docs/WebServer/webServerObject.md +++ b/docs/WebServer/webServerObject.md @@ -101,6 +101,19 @@ These properties are defined: > *isRunning*, *name*, *openSSLVersion*, and *perfectForwardSecrecy* are read-only properties that cannot be predefined in the `settings` object parameter for the [`start()`](API/WebServerClass.md#start) function. +### MCP server settings + +The [`mcp`](../API/WebServerClass.md#mcp) property contains the settings of the [MCP server](mcp-server.md) of the host application's web server: `enabled`, `serverName`, `serverVersion`, `instructions`, `maxResults`, `crudTools`, `allowInsecureHTTP`, `trustedProxies`, `publicURL`, and `oauthDynamicRegistration`. Unlike other properties: + +- `mcp.enabled` can be modified while the web server is running, to enable or disable the MCP server without restarting the web server, +- the `mcp` settings passed to the [`.start()`](../API/WebServerClass.md#start) function are kept when the web server is restarted. + +```4d +var webServer : 4D.WebServer:=WEB Server + //enable the MCP server of the running web server +webServer.mcp.enabled:=True +``` + ## Scope of the 4D Web commands diff --git a/docs/WritePro/commands-legacy/wp-get-view-properties.md b/docs/WritePro/commands-legacy/wp-get-view-properties.md index 4b817f1e149eee..cc878952cd4ed6 100644 --- a/docs/WritePro/commands-legacy/wp-get-view-properties.md +++ b/docs/WritePro/commands-legacy/wp-get-view-properties.md @@ -49,6 +49,7 @@ The returned object contains all view properties of the 4D Write Pro area, along | wk visible HTML WYSIWYG | htmlWYSIWIGEnabled | Enables the HTML WYSIWYG view by removing proprietary 4D Write Pro HTML/CSS tags. Possible values: True/False | | wk visible page frames | visiblePageFrames | Displays the page frames (visible effect in Page view mode only). Possible values: True/False | | wk visible references | visibleReferences | Displays or exports all 4D expressions inserted in the document as references. Possible values: True/False | +| wk visible table borders | visibleTableBorders | Displays internal and external table borders as dotted lines when these borders are partially or totally invisible. Possible values: True/False | | wk visible vertical ruler | visibleVerticalRuler | Displays the vertical ruler (visible effect in Page view mode only). Possible values: True/False | | wk zoom | zoom | Zoom percentage for displaying the contents of the 4D Write Pro area. Possible values: Number greater than 1 | diff --git a/docs/WritePro/commands-legacy/wp-set-view-properties.md b/docs/WritePro/commands-legacy/wp-set-view-properties.md index 222cae5ca2b352..70a3cb89295b6e 100644 --- a/docs/WritePro/commands-legacy/wp-set-view-properties.md +++ b/docs/WritePro/commands-legacy/wp-set-view-properties.md @@ -42,12 +42,13 @@ In *wpViewProps*, pass an object wherein each property is a view property that y | wk visible HTML WYSIWYG | htmlWYSIWIGEnabled | Enables the HTML WYSIWYG view by removing proprietary 4D Write Pro HTML/CSS tags. Possible values: True/False | | wk visible page frames | visiblePageFrames | Displays the page frames (visible effect in Page view mode only). Possible values: True/False | | wk visible references | visibleReferences | Displays or exports all 4D expressions inserted in the document as references. Possible values: True/False | +| wk visible table borders | visibleTableBorders | Displays internal and external table borders as dotted lines when these borders are partially or totally invisible. Possible values: True/False | | wk visible vertical ruler | visibleVerticalRuler | Displays the vertical ruler (visible effect in Page view mode only). Possible values: True/False | | wk zoom | zoom | Zoom percentage for displaying the contents of the 4D Write Pro area. Possible values: Number greater than 1 | All properties can be modified at any moment, but some are only taken into account if a compatible 4D Write Pro display mode is used. Therefore, even if a view property is modified, there may be no visible effect in the current display mode. -**Note:** For more information about view properties, please refer to the *Defining a 4D Write Pro area* page. +**Note:** For more information about view properties, please refer to the [View Properties](../configuring-4d-write-pro-areas#view-properties) section. Once view properties have been set for *wpArea* using this command, they are applied while the form area is used as long as they are not modified by another call. The property modifications are not saved with the document or the form. diff --git a/docs/WritePro/user-legacy/defining-a-4d-write-pro-area.md b/docs/WritePro/user-legacy/defining-a-4d-write-pro-area.md index 01c3bad18b464d..c8eee661eeb612 100644 --- a/docs/WritePro/user-legacy/defining-a-4d-write-pro-area.md +++ b/docs/WritePro/user-legacy/defining-a-4d-write-pro-area.md @@ -48,7 +48,10 @@ Document view settings are handled through specific items in the **Appearance** * **Show horizontal ruler**: Displays/hides the horizontal ruler. F * **Show vertical ruler**: Displays/hides the vertical ruler when the document is in Page mode. * **Show empty or unsupported images**: Displays/hides a black rectangle for images that cannot be loaded or computed (empty images or images in an unsupported format). -* **Display formula source as symbol**: Displays source text of formulas as ![](../../assets/en/WritePro/pict6013182.en.png) symbols when expressions are shown as references (see above). Displaying formulas as symbols makes template documents more compact and more *wysiwyg*. +* **Display formula source as symbol**: Displays source text of formulas as ![](../../assets/en/WritePro/pict6013182.en.png) symbols when expressions are shown as references (see above). Displaying formulas as symbols makes template documents more compact and more *wysiwyg*. +* **Show table borders**: Displays internal and external table borders as dotted lines when these borders are partially or totally invisible. This facilitates page layout (more accessible, more visual resizing) and data entry (convenient in the case of merged cells, for example). See also [this blog post](https://blog.4d.com/4d-write-pro-make-hidden-table-borders-visible-temporarily/). + + ## Context menu diff --git a/docs/assets/en/FormObjects/button_custom.png b/docs/assets/en/FormObjects/button_custom.png index 7779b50bc22c2a..08fe1a91182a5f 100644 Binary files a/docs/assets/en/FormObjects/button_custom.png and b/docs/assets/en/FormObjects/button_custom.png differ diff --git a/docs/assets/en/FormObjects/visible.png b/docs/assets/en/FormObjects/visible.png new file mode 100644 index 00000000000000..33d197b738d0d2 Binary files /dev/null and b/docs/assets/en/FormObjects/visible.png differ diff --git a/docs/assets/en/commands/set-rgb-colors-2.png b/docs/assets/en/commands/set-rgb-colors-2.png new file mode 100644 index 00000000000000..fffe9c591144a9 Binary files /dev/null and b/docs/assets/en/commands/set-rgb-colors-2.png differ diff --git a/docs/assets/en/commands/set-rgb-colors.png b/docs/assets/en/commands/set-rgb-colors.png new file mode 100644 index 00000000000000..943b18a6888d79 Binary files /dev/null and b/docs/assets/en/commands/set-rgb-colors.png differ diff --git a/docs/code-editor/write-class-method.md b/docs/code-editor/write-class-method.md index 9ac5beacd17d98..200b328e57304a 100644 --- a/docs/code-editor/write-class-method.md +++ b/docs/code-editor/write-class-method.md @@ -409,6 +409,8 @@ If the characters typed correspond to different types of objects, the list displ > For practical reasons, you can disable the automatic display of the list of suggestions for **constants**, **(local or interprocess) variables and object attributes**, **tables** and/or **prototypes**. These options are found in **Preferences** > **Methods** > **Options** +When a suggested class function or class constructor is documented with a [comment block above its declaration](../Concepts/classes.md#function-comments), its description and parameter comments are displayed with its signature in the suggestion details. + #### Object property names 4D automatically displays case-sensitive suggestions of all valid object property names in 4D code when you: @@ -570,6 +572,25 @@ The [status bar](#status-bar) also provides contextual information. - You can also create a **dedicated documentation file** named `.md` in the `/documentation` folder. See [Viewing documentation in the code editor](../Project/documentation.md#viewing-documentation-in-the-code-editor) +- **Class function and class constructor comments**: When you call a class function or a class constructor (`cs.MyClass.new()`), the help tip and the signature help display its signature along with the [comment block written right above its declaration](../Concepts/classes.md#function-comments): the description lines, then the `$name:` parameter lines. `MCP:` lines are not displayed. This applies to project classes, shared and singleton classes, and component classes, and works the same in VS Code. + + - The text is displayed as plain text: Markdown markers are shown as written. + - Only the saved code is used: an edited comment is displayed once the class is saved. + - If there is no comment block right above the declaration (for example, if a blank line separates them), only the signature is displayed. + + For example, with the following class function: + + ```4d + // Class: Invoice + + // Returns the price with taxes + // $rate: tax rate to apply (20 for 20%) + Function priceWithTaxes($rate : Real) : Real + return This.price*(1+($rate/100)) + ``` + + typing `$invoice.priceWithTaxes(` displays "Returns the price with taxes" and "$rate: tax rate to apply (20 for 20%)" below the signature. + ## Comment / Uncomment diff --git a/docs/commands/command-index.md b/docs/commands/command-index.md index cb3675b1be07fb..b9c42b169f3eec 100644 --- a/docs/commands/command-index.md +++ b/docs/commands/command-index.md @@ -641,6 +641,7 @@ title: Commands by name [`Match regex`](../commands/match-regex)
    [`Max`](../commands/max)
    [`MAXIMIZE WINDOW`](../commands/maximize-window)
    +[`MCP`](../commands/mcp) **new 4D 21 R6**
    [`MEMORY STATISTICS`](../commands/memory-statistics)
    [`Menu bar height`](../commands/menu-bar-height)
    [`Menu bar screen`](../commands/menu-bar-screen)
    diff --git a/docs/commands/theme/MCP.md b/docs/commands/theme/MCP.md new file mode 100644 index 00000000000000..f142bea24ed26c --- /dev/null +++ b/docs/commands/theme/MCP.md @@ -0,0 +1,11 @@ +--- +id: MCP_theme +title: MCP +sidebar_label: MCP +slug: /commands/theme/MCP +--- + + +|| +|---| +|[](../../commands/mcp)
    | diff --git a/docs/language-legacy/MCP/_category_.json b/docs/language-legacy/MCP/_category_.json new file mode 100644 index 00000000000000..2fe3278fd3625a --- /dev/null +++ b/docs/language-legacy/MCP/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "MCP", + "link": {"type": "doc", "id": "commands/theme/MCP_theme"}, + "key": "MCP-key" +} diff --git a/docs/language-legacy/MCP/mcp.md b/docs/language-legacy/MCP/mcp.md new file mode 100644 index 00000000000000..ab8a1f414a67bb --- /dev/null +++ b/docs/language-legacy/MCP/mcp.md @@ -0,0 +1,95 @@ +--- +id: mcp +title: MCP +slug: /commands/mcp +displayed_sidebar: docs +--- + +**MCP** : 4D.MCPContext + +
    + +| Parameter | Type | | Description | +| --- | --- | --- | --- | +| Function result | [4D.MCPContext](../../API/MCPContextClass.md) | ← | Context of the current MCP tool call | +
    + + +
    +
    History + +|Release|Changes| +|---|---| +|21 R6|Created| + +
    +
    + +## Description + +The `MCP` command returns the `4D.MCPContext` object of the current call of a tool of the MCP server. + +The [`4D.MCPContext`](../../API/MCPContextClass.md) object gives information about the call ([`.toolName`](../../API/MCPContextClass.md#toolname), [`.clientInfo`](../../API/MCPContextClass.md#clientinfo), [`.canElicit`](../../API/MCPContextClass.md#canelicit)) and lets the tool: + +- ask the user for a confirmation or for values before running an action ([`.requireInput()`](../../API/MCPContextClass.md#requireinput), [`.hasInput()`](../../API/MCPContextClass.md#hasinput), [`.input`](../../API/MCPContextClass.md#input), [`.bound`](../../API/MCPContextClass.md#bound)), +- return an error to the client ([`.error()`](../../API/MCPContextClass.md#error)). + +The context is available while an [`exposed MCP Function`](../../ORDA/ordaClasses.md#exposed-mcp-function) runs as a tool of the [MCP server](../../WebServer/mcp-server.md), including in the methods and functions it calls. + +Outside an MCP tool call (for example in a REST request or in a method run from the 4D environment), `MCP` returns an inert object: + +- `.hasInput()` returns **False**, +- `.requireInput()` asks nothing and returns *Null*, +- `.error()` does nothing, +- `.toolName` is an empty string, `.clientInfo` is *Null*, and `.canElicit` is **False**. + +For more information, see [Asking the user for confirmation](../../WebServer/mcp-server.md#asking-the-user-for-confirmation). + +## Example 1 + +You want the user to confirm the deletion of an order before it is dropped: + +```4d +// cs.OrderEntity class +Class extends Entity + +// Deletes the order +exposed MCP Function delete() : Text + If (Not(MCP.hasInput("confirm"))) + MCP.requireInput({message: "Delete order "+String(This.ID)+"?"; confirm: {type: "boolean"; title: "Delete"}}; This.getStamp()) + return + End if + If (MCP.bound#This.getStamp()) + MCP.error("The order was modified, please try again") + return + End if + If (MCP.input.confirm) + This.drop() + return "Order deleted" + End if + return "Deletion cancelled" +``` + +## Example 2 + +A method called both by an MCP tool and by other code checks whether it runs in an MCP tool call: + +```4d +var $context : 4D.MCPContext:=MCP +If ($context.toolName="") + // not called from an MCP tool: $context is inert +End if +``` + +## See also + +[MCPContext class](../../API/MCPContextClass.md) +[MCP server](../../WebServer/mcp-server.md) +[Session](../../commands/session) + +## Properties + +| | | +| --- | --- | +| Command number | 1872 | +| Thread safe | yes | diff --git a/docs/language-legacy/Objects (Forms)/object-get-border-style.md b/docs/language-legacy/Objects (Forms)/object-get-border-style.md index 0ce7616dd67a29..3e1f261a3fb13f 100644 --- a/docs/language-legacy/Objects (Forms)/object-get-border-style.md +++ b/docs/language-legacy/Objects (Forms)/object-get-border-style.md @@ -22,7 +22,7 @@ displayed_sidebar: docs |Release|Changes| |---|---| -|21 R5|New Border Custom` constant | +|21 R5|New `Border Custom` and `Border System Rounded` constant | |14|Created|
    @@ -38,16 +38,18 @@ Passing the optional *\** parameter indicates that the *object* parameter is an The command returns a value corresponding to the border line style. You can compare the value received with the following constants, found in the "*Form Objects (Properties)*" theme: -| Constant | Type | Value | Comment | -| ------------- | ------- | ----- | ----------------------------------------------------------------------------------------------- | +| Constant | Type | Value | Comment | +| ------------- | ------- | ----- | ------- | | Border Custom | Integer | 9 | (buttons only) Enables the inner frame design for buttons, supporting extra properties | -| Border Dotted | Integer | 2 | Objects appear framed with a dotted 1-pt. border line | +| Border Dotted | Integer | 2 | Objects appear framed with a dotted 1-pt. border line | | Border Double | Integer | 5 | Objects appear framed with a double line, i.e., two continuous 1-pt. lines separated by a pixel | -| Border None | Integer | 0 | Objects appear with no border | -| Border Plain | Integer | 1 | Objects appear framed with a continuous 1-pt. border line | -| Border Raised | Integer | 3 | Objects appear framed with a 3D effect (raised) | -| Border Sunken | Integer | 4 | Objects appear framed with a sunken 3D effect | -| Border System | Integer | 6 | The border line is drawn based on the graphic specifications of the system | +| Border None | Integer | 0 | Objects appear with no border | +| Border Plain | Integer | 1 | Objects appear framed with a continuous 1-pt. border line | +| Border Raised | Integer | 3 | Objects appear framed with a 3D effect (raised) | +| Border Sunken | Integer | 4 | Objects appear framed with a sunken 3D effect | +| Border System | Integer | 6 | The border line is drawn based on the graphic specifications of the system | +| Border System Rounded | Integer | 8 | On macOS, the border line is drawn with "Liquid Glass" graphic appearance. On Windows, the rendering is similar to `Border System` | + ## See also diff --git a/docs/language-legacy/Objects (Forms)/object-get-rgb-colors.md b/docs/language-legacy/Objects (Forms)/object-get-rgb-colors.md index 0cc2f282ce3f3a..d04436454a7742 100644 --- a/docs/language-legacy/Objects (Forms)/object-get-rgb-colors.md +++ b/docs/language-legacy/Objects (Forms)/object-get-rgb-colors.md @@ -5,7 +5,7 @@ slug: /commands/object-get-rgb-colors displayed_sidebar: docs --- -**OBJECT GET RGB COLORS** ( * ; *object* : Text ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; borderColor : Text, Integer}}} )
    **OBJECT GET RGB COLORS** ( *object* : Variable, Field ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; borderColor : Text, Integer}}} ) +**OBJECT GET RGB COLORS** ( * ; *object* : Text ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; *borderColor* : Text, Integer}}} )
    **OBJECT GET RGB COLORS** ( *object* : Variable, Field ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; *borderColor* : Text, Integer}}} )
    @@ -25,7 +25,7 @@ displayed_sidebar: docs |Release|Changes| |---|---| -|21 R6|Support of *borderColor* parameter| +|21 R5|Support of *borderColor* parameter| |17 R6|Modified| |12|Created| @@ -34,18 +34,27 @@ displayed_sidebar: docs ## Description -The OBJECT GET RGB COLORS command returns the foreground and background colors of the object or group of objects designated by *object*. +The **OBJECT GET RGB COLORS** command returns the foreground, background, and optionally alternate background and border colors of the object or group of objects designated by *object*. If you pass the optional *\** parameter, you indicate that the *object* parameter is an object name (string). If you do not pass this parameter, you indicate that the *object* parameter is a field or a variable. In this case, you pass a field or variable reference (object field or variable only) instead of a string. When the command is applied to a list box type object, the alternating background color for the rows can be returned in the *altBackgrndColor* parameter. In this case, the value of *backgroundColor* is used for the background of odd-numbered rows only. -The RGB color values returned in the *foregroundColor*, *backgroundColor*, and *altBackgrndColor* parameters depend on the parameter type: +When the command is applied to an object that supports the [`borderColor` property]((../../FormObjects/properties_BackgroundAndBorder.md#border-color)), the border color can be returned in the *borderColor* parameter. -* if a parameter of [text](# "A character string that may contain from 0 to 2 GB of text") type is passed, the color is returned in CSS format with "#rrggbb" syntax (ex: "#0000FF") -* if a parameter of [longint](# "Number between -2^31..(2^31)-1 (4-byte Integer)") type is passed, the color can be 4-byte Long Integer of the format (0x00RRGGBB) or negative values corresponding to the "system" colors. +:::note -For more information about the format of the *foregroundColor*, *backgroundColor*, and *altBackgrndColor* parameters, refer to the description of the [OBJECT SET RGB COLORS](../commands/object-set-rgb-colors) command. +The *borderColor* parameter is not available in binary databases. + +::: + + +The RGB color values returned in the *foregroundColor*, *backgroundColor*, *altBackgrndColor*, and *borderColor* parameters depend on the parameter type: + +* if a parameter of text type is passed, the color is returned in CSS format with "#rrggbb" syntax (ex: "#0000FF") +* if a parameter of integer type is passed, the color can be 4-byte Long Integer of the format (0x00RRGGBB) or negative values corresponding to the "system" colors. + +For more information about the format of the *foregroundColor*, *backgroundColor*, *altBackgrndColor*, and *borderColor* parameters, refer to the description of the [OBJECT SET RGB COLORS](../commands/object-set-rgb-colors) command. ## See also diff --git a/docs/language-legacy/Objects (Forms)/object-set-border-style.md b/docs/language-legacy/Objects (Forms)/object-set-border-style.md index 05d73830d5923b..a4940c02f04f6c 100644 --- a/docs/language-legacy/Objects (Forms)/object-set-border-style.md +++ b/docs/language-legacy/Objects (Forms)/object-set-border-style.md @@ -22,7 +22,7 @@ displayed_sidebar: docs |Release|Changes| |---|---| -|21 R5|New Border Custom` constant | +|21 R5|New `Border Custom` and `Border System Rounded` constant | |14|Created| @@ -38,16 +38,18 @@ Passing the optional *\** parameter indicates that the *object* parameter is an In the *borderStyle* parameter, pass the value of the border line style that you want to apply to the object. You can pass one of the following constants, found in the "*Form Objects (Properties)*" theme: -| Constant | Type | Value | Comment | -| ------------- | ------- | ----- | ----------------------------------------------------------------------------------------------- | +| Constant | Type | Value | Comment | +| ------------- | ------- | ----- | ------------------ | | Border Custom | Integer | 9 | (buttons only) Enables the inner frame design for buttons, supporting extra properties | -| Border Dotted | Integer | 2 | Objects appear framed with a dotted 1-pt. border line | +| Border Dotted | Integer | 2 | Objects appear framed with a dotted 1-pt. border line | | Border Double | Integer | 5 | Objects appear framed with a double line, i.e., two continuous 1-pt. lines separated by a pixel | -| Border None | Integer | 0 | Objects appear with no border | -| Border Plain | Integer | 1 | Objects appear framed with a continuous 1-pt. border line | -| Border Raised | Integer | 3 | Objects appear framed with a 3D effect (raised) | -| Border Sunken | Integer | 4 | Objects appear framed with a sunken 3D effect | -| Border System | Integer | 6 | The border line is drawn based on the graphic specifications of the system | +| Border None | Integer | 0 | Objects appear with no border| +| Border Plain | Integer | 1 | Objects appear framed with a continuous 1-pt. border line | +| Border Raised | Integer | 3 | Objects appear framed with a 3D effect (raised) | +| Border Sunken | Integer | 4 | Objects appear framed with a sunken 3D effect | +| Border System | Integer | 6 | The border line is drawn based on the graphic specifications of the system | +| Border System Rounded | Integer | 8 | On macOS, the border line is drawn with "Liquid Glass" graphic appearance. Note that the "Liquid Glass" appearance is *not* used in a multiline input object if the [scroll bars property](../../FormObjects/properties_Appearance.md#vertical-scroll-bar) is enabled (`Border System` is used in this case). On Windows, the rendering is similar to `Border System` | + ## See also diff --git a/docs/language-legacy/Objects (Forms)/object-set-rgb-colors.md b/docs/language-legacy/Objects (Forms)/object-set-rgb-colors.md index 438ff2c4539d1a..9887a6f0614072 100644 --- a/docs/language-legacy/Objects (Forms)/object-set-rgb-colors.md +++ b/docs/language-legacy/Objects (Forms)/object-set-rgb-colors.md @@ -5,7 +5,7 @@ slug: /commands/object-set-rgb-colors displayed_sidebar: docs --- -**OBJECT SET RGB COLORS** ( * ; *object* : Text ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; borderColor : Text, Integer}}} )
    **OBJECT SET RGB COLORS** ( *object* : Variable, Field ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; borderColor : Text, Integer}}} ) +**OBJECT SET RGB COLORS** ( * ; *object* : Text ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; *borderColor* : Text, Integer}}} )
    **OBJECT SET RGB COLORS** ( *object* : Variable, Field ; *foregroundColor* : Text, Integer {; *backgroundColor* : Text, Integer {; *altBackgrndColor* : Text, Integer {; *borderColor* : Text, Integer}}} )
    @@ -16,7 +16,7 @@ displayed_sidebar: docs | foregroundColor | Text, Integer | → | RGB color value for foreground ("" = unchanged)| | backgroundColor | Text, Integer | → | RGB color value for background ("" = unchanged)| | altBackgrndColor | Text, Integer | → | RGB color value for alternating background ("" = unchanged)| -| borderColor | Text, Integer | → | RGB color value for border color | +| borderColor | Text, Integer | → | RGB color value for border color ("" = unchanged)|
    @@ -25,7 +25,7 @@ displayed_sidebar: docs |Release|Changes| |---|---| -|21 R6|Support of *borderColor* parameter| +|21 R5|Support of *borderColor* parameter| |17 R6|Modified| |14|Modified| |12|Renamed| @@ -37,17 +37,27 @@ displayed_sidebar: docs ## Description -The **OBJECT SET RGB COLORS** command changes the foreground and background colors of the objects specified by the *object* parameter and the optional *\** parameter. When the command is applied to a list box object, an additional parameter lets you modify the alternating color of the rows. +The **OBJECT SET RGB COLORS** command changes the foreground and background colors of the objects specified by the *object* parameter and the optional *\** parameter. Two other color parameters can be available, depending on which object the command is applied to. + +If you specify the optional *\** parameter, you indicate an object name (a string) in *object*. If you omit the optional \* parameter, you indicate a field or a variable in *object*. In this case, you specify a field or variable reference (field or variable objects only) instead of a string. -If you specify the optional *\** parameter, you indicate an object name (a string) in *object*. If you omit the optional \* parameter, you indicate a field or a variable in *object*. In this case, you specify a field or variable reference (field or variable objects only) instead of a string. For more information about object names, see the *Object Properties* section. The optional *altBackgrndColor* parameter lets you set an alternate background color for even-numbered rows. This parameter is only used when the object specified is a list box or a column of the list box. When this parameter is used, the *backgroundColor* parameter is only used for odd-numbered rows. Using alternating colors makes lists easier to read. If *object* specifies a list box object, alternating colors are used for the entire list box. If *object* specifies a column of the list box, only that column will use the colors set. -You can use "" (empty string) in *foregroundColor*, *backgroundColor*, and/or *altBackgrndColor* to let it unchanged. + +The optional *borderColor* parameter allows you to change the color of the border at runtime. This parameter can only be applied to objects that support the `borderColor` property, and requires that the border style be "plain" or "dotted" (except for custom-styled buttons). See detailed explanations in the ["Border Color" section](../../FormObjects/properties_BackgroundAndBorder.md#border-color). + +:::note + +The *borderColor* parameter is not available in binary databases. + +::: + +You can use "" (empty string) in *foregroundColor*, *backgroundColor*, *altBackgrndColor*, and/or *borderColor* to let it unchanged. **Definition of colors** -You indicate RGB color values in *foregroundColor* and, optionally, *backgroundColor*, and *altBackgrndColor* parameters. The following formats are supported: +You indicate RGB color values in *foregroundColor* and, optionally, *backgroundColor*, *altBackgrndColor*, and *borderColor* parameters. The following formats are supported: | **Format name** | **Type** | **Description** | **Examples** | | ------------ | -------- | --------------- | ---------------------- | @@ -117,6 +127,24 @@ Changing to transparent background with a light font color: ![](../../assets/en/commands/pict1210702.en.png) + +## Example 3 + +Changing the list box border color only: + +![](../../assets/en/commands/set-rgb-colors.png) + + +```4d + //change the border style to plain (default is system) +OBJECT SET BORDER STYLE(*; "listOfDays"; Border Plain) + //set the border color to red +OBJECT SET RGB COLORS(*; "listOfDays"; ""; ""; ""; "#ff0000") + +``` + +![](../../assets/en/commands/set-rgb-colors-2.png) + ## See also [OBJECT GET RGB COLORS](../commands/object-get-rgb-colors) diff --git a/docs/language-legacy/Objects (Language)/ob-entries.md b/docs/language-legacy/Objects (Language)/ob-entries.md index 50bee9c70619a1..ed3acdb38ea754 100644 --- a/docs/language-legacy/Objects (Language)/ob-entries.md +++ b/docs/language-legacy/Objects (Language)/ob-entries.md @@ -72,6 +72,6 @@ Using an object as an hash map (key / value system) provides a quick and direct | | | | --- | --- | | Command number | 1720 | -| Thread safe | no | +| Thread safe | yes | | diff --git a/docs/language-legacy/Objects (Language)/ob-keys.md b/docs/language-legacy/Objects (Language)/ob-keys.md index 53667444dda9b8..7b38f172ee2842 100644 --- a/docs/language-legacy/Objects (Language)/ob-keys.md +++ b/docs/language-legacy/Objects (Language)/ob-keys.md @@ -62,6 +62,6 @@ You want a collection with all first-level property names of an object: | | | | --- | --- | | Command number | 1719 | -| Thread safe | no | +| Thread safe | yes | diff --git a/docs/language-legacy/Objects (Language)/ob-values.md b/docs/language-legacy/Objects (Language)/ob-values.md index 87ce3795c309b0..bc290377a57f96 100644 --- a/docs/language-legacy/Objects (Language)/ob-values.md +++ b/docs/language-legacy/Objects (Language)/ob-values.md @@ -62,6 +62,6 @@ You want a collection with all property values of an object: | | | | --- | --- | | Command number | 1718 | -| Thread safe | no | +| Thread safe | yes | diff --git a/docs/preprocessing.conf b/docs/preprocessing.conf index 964d8ab9ae72e6..3b8110d6550273 100644 --- a/docs/preprocessing.conf +++ b/docs/preprocessing.conf @@ -19,6 +19,7 @@ IMAPTransporter IncomingMessage MailAttachment +MCPContext Method OutgoingMessage POP3Transporter diff --git a/i18n/es/docusaurus-plugin-content-docs/current.json b/i18n/es/docusaurus-plugin-content-docs/current.json index 1b6f01f1d32b89..bd78cd90460600 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current.json +++ b/i18n/es/docusaurus-plugin-content-docs/current.json @@ -12,7 +12,7 @@ "description": "The label for category 'Core Development' in sidebar 'docs'" }, "sidebar.docs.category.Project Management": { - "message": "Gestión de proyectos", + "message": "Gestión del proyecto", "description": "The label for category Project Management in sidebar docs" }, "sidebar.docs.category.Data Types": { diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/CollectionClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/CollectionClass.md index 6efed8c62af40d..6c8c482f75ecfd 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/CollectionClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/CollectionClass.md @@ -2207,7 +2207,7 @@ También puede pasar un parámetro de criterios para definir cómo deben ordenar Esta sintaxis sólo ordena los valores escalares de la colección (otros tipos de elementos, como objetos o colecciones, se devuelven desordenados). -Si la colección contiene elementos de diferentes [tipos](../Concepts/data-types.md), se ordenarán según los [principios de ordenación de 4D](../Concepts/ordering.md). +Si la colección contiene elementos de diferentes [tipos](../Concepts/data-types.md), se ordenarán según los [principios de ordenación 4D](../Concepts/ordering.md). #### Ejemplo 1 diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/CryptoKeyClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/CryptoKeyClass.md index 544cacc4d62f3d..504b76a599bf12 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/CryptoKeyClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/CryptoKeyClass.md @@ -57,12 +57,12 @@ La función `4D.CryptoKey.new()` crea un #### *settings* -| Propiedad | Tipo | Descripción | -| --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [type](#type) | text | Define el tipo de clave a crear:
  • "RSA": genera un par de llaves RSA, utilizando [.size](#size) como tamaño.
  • "ECDSA": genera un par de llaves Elliptic Curve Digital Signature Algorithm, utilizando [.curve](#curve) como curva. Tenga en cuenta que las llaves ECDSA no pueden utilizarse para cifrar, sino sólo para firmar.
  • "PEM": carga una definición de par de llaves en formato PEM, utilizando [.pem](#pem).
  • | -| [curve](#curve) | text | Nombre de la curva ECDSA | -| [pem](#pem) | text | Definición PEM de una llave de cifrado a cargar | -| [size](#size) | integer | Tamaño de la llave RSA en bits | +| Propiedad | Tipo | Descripción | +| --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [type](#type) | text | Define el tipo de llave a crear:
  • "RSA": genera un par de llaves RSA, utilizando [.size](#size) como tamaño.
  • "ECDSA": genera un par de llaves Elliptic Curve Digital Signature Algorithm, utilizando [.curve](#curve) como curva. Tenga en cuenta que las llaves ECDSA no pueden utilizarse para el cifrado, sino solo para la firma.
  • "PEM": carga una definición de par de llaves en formato PEM, utilizando [.pem](#pem).
  • | +| [curve](#curve) | text | Nombre de la curva ECDSA | +| [pem](#pem) | text | Definición PEM de una llave de cifrado a cargar | +| [size](#size) | integer | Tamaño de la llave RSA en bits | #### *CryptoKey* @@ -142,7 +142,7 @@ ASSERT($status.success) **.curve** : Text -Definido sólo para las llaves ECDSA: el nombre de la curva normalizada de la llave. . . +Definido sólo para las llaves ECDSA: el nombre de la curva normalizada de la llave. . diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/DataClassClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/DataClassClass.md index 536159d4e255c9..39ac7b3942ebde 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/DataClassClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/DataClassClass.md @@ -16,6 +16,7 @@ Una [DataClass](ORDA/dsMapping.md#dataclass) ofrece un objeto de interfaz a una | [](#get)
    | | [](#getcount)
    | | [](#getdatastore)
    | +| [](#getindexes)
    | | [](#getinfo)
    | | [](#getremotecache)
    | | [](#new)
    | @@ -50,24 +51,24 @@ Los objetos devueltos tienen propiedades que puede leer para obtener informació Los objetos de atributo devueltos contienen las siguientes propiedades: -| Propiedad | Tipo | Descripción | -| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| autoFilled | Boolean | True si el valor del atributo es rellenado automáticamente por 4D. Corresponde a las siguientes propiedades de campo 4D: "Autoincremento" para campos de tipo numérico y "Auto UUID" para campos UUID (alfa). No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | -| exposed | Boolean | True si el atributo está expuesto en REST | -| fieldNumber | integer | Número de campo 4D interno del atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | -| fieldType | Integer | Tipo de campo de base de datos 4D del atributo. Depende del atributo `kind`. Valores posibles:
  • si `.kind` = "storage": tipo de campo 4D correspondiente, ver [`Value type`](../commands/value-type)
  • si `.kind` = "relatedEntity": 38 (`is object`)
  • si `.kind` = "relatedEntities": 42 (`is collection`)
  • si `.kind` = "calculated" o "alias" = igual que arriba, dependiendo del valor resultante (tipo de campo, relatedEntity o relatedEntities)
  • | -| indexed | Boolean | True si hay un índice B-tree o Cluster B-tree en el atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | -| inverseName | Text | Nombre del atributo que se encuentra al otro lado de la relación. Sólo se devuelve cuando `.kind` = "relatedEntity" o "relatedEntities". | -| keywordIndexed | Boolean | True si existe un índice de palabras clave en el atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | -| kind | Text | Categoría del atributo. Valores posibles:
  • "storage": atributo de almacenamiento (o escalar), es decir, un atributo que almacena un valor, no una referencia a otro atributo
  • "calculated": atributo calculado, es decir, definido a través de una [`función get`](../ORDA/ordaClasses.md#function-get-attributename)
  • "alias": atributo construido sobre [otro atributo](../ORDA/ordaClasses.md#alias-attributes-1)
  • "relatedEntity": atributo de relación N -> 1 (referencia a una entidad)
  • "relatedEntities": atributo de relación 1 -> N (referencia a una selección de entidades)
  • | -| mandatory | Boolean | True si se rechaza la entrada de valores null para el atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". Nota: esta propiedad corresponde a la propiedad de campo "Rechazar entrada de valor NULL" a nivel de base de datos 4D. No tiene relación con la propiedad "Obligatorio" existente, que es una opción de control de entrada de datos para una tabla. | -| name | Text | Nombre del atributo como cadena | -| path | Text | Ruta de [un atributo alias](../ORDA/ordaClasses.md#alias-attributes-1) basada en una relación | -| readOnly | Boolean | True si el atributo es de sólo lectura. Por ejemplo, los atributos calculados sin la [función `set`](../ORDA/ordaClasses.md#function-set-attributename) son de solo lectura. | -| relatedDataClass | Text | Nombre del dataclass relacionado con el atributo. Sólo se devuelve cuando `.kind` = "relatedEntity" o "relatedEntities". | -| type | Text | Tipo de valor conceptual del atributo, útil para la programación genérica. Depende del atributo `kind`. Valores posibles:
  • si `.kind` = "storage": "blob", "bool", "date", "image", "number", "object" o "string". "number" se devuelve para todo tipo numérico, incluyendo duración; "string" se devuelve para los tipos de atributos uuid, alfa y texto; los atributos "blob" son [objetos blob](../Concepts/dt_blob.md#blob-types).
  • si `.kind` = "relatedEntity": nombre de la clase de datos relacionada
  • si `.kind` = "relatedEntities": nombre de la clase de datos relacionada + sufijo "Selection"
  • si `.kind` = "calculated" o "alias": igual que en los casos anteriores, dependiendo del resultado
  • | -| unique | Boolean | True si el valor del atributo debe ser único. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | -| classID | Text | Disponible sólo si `.type = "object"` y se ha especificado una clase en el editor de estructuras.
    Devuelve el nombre de la clase utilizada para instanciar el objeto. | +| Propiedad | Tipo | Descripción | +| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| autoFilled | Boolean | True si el valor del atributo es rellenado automáticamente por 4D. Corresponde a las siguientes propiedades de campo 4D: "Autoincremento" para campos de tipo numérico y "Auto UUID" para campos UUID (alfa). No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | +| exposed | Boolean | True si el atributo está expuesto en REST | +| fieldNumber | integer | Número de campo 4D interno del atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | +| fieldType | Integer | Tipo de campo de base de datos 4D del atributo. Depende del atributo `kind`. Valores posibles:
  • si `.kind` = "storage": tipo de campo 4D correspondiente, ver [`Value type`](../commands/value-type)
  • si `.kind` = "relatedEntity": 38 (`is object`)
  • si `.kind` = "relatedEntities": 42 (`is collection`)
  • si `.kind` = "calculated" o "alias" = igual que arriba, dependiendo del valor resultante (tipo de campo, relatedEntity o relatedEntities)
  • | +| indexed | Boolean | True si hay un índice B-tree o Cluster B-tree en el atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | +| inverseName | Text | Nombre del atributo que se encuentra al otro lado de la relación. Sólo se devuelve cuando `.kind` = "relatedEntity" o "relatedEntities". | +| keywordIndexed | Boolean | True si existe un índice de palabras clave en el atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | +| kind | Text | Categoría del atributo. Valores posibles:
  • "storage": atributo de almacenamiento (o escalar), es decir, un atributo que almacena un valor, no una referencia a otro atributo
  • "calculated": atributo calculado, es decir, definido a través de una [`función get`](../ORDA/ordaClasses.md#function-get-attributename)
  • "alias": atributo construido sobre [otro atributo](../ORDA/ordaClasses.md#alias-attributes-1)
  • "relatedEntity": atributo de relación N -> 1 (referencia a una entidad)
  • "relatedEntities": atributo de relación 1 -> N (referencia a una selección de entidades)
  • | +| mandatory | Boolean | True si se rechaza la entrada de valores null para el atributo. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". Nota: esta propiedad corresponde a la propiedad de campo "Rechazar entrada de valor NULL" a nivel de base de datos 4D. No tiene relación con la propiedad "Obligatorio" existente, que es una opción de control de entrada de datos para una tabla. | +| name | Text | Nombre del atributo como cadena | +| path | Text | Ruta de [un atributo alias](../ORDA/ordaClasses.md#alias-attributes-1) basada en una relación | +| readOnly | Boolean | True si el atributo es de sólo lectura. Por ejemplo, los atributos calculados sin la [función `set`](../ORDA/ordaClasses.md#function-set-attributename) son de solo lectura. | +| relatedDataClass | Text | Nombre del dataclass relacionado con el atributo. Sólo se devuelve cuando `.kind` = "relatedEntity" o "relatedEntities". | +| type | Text | Tipo de valor conceptual del atributo, útil para la programación genérica. Depende del atributo `kind`. Valores posibles:
  • si `.kind` = "storage": "blob", "bool", "date", "image", "number", "object" o "string". "number" se devuelve para todo tipo numérico, incluida la duración; "string" se devuelve para los tipos de atributo uuid, alpha y text; los atributos "blob" son [objetos blob](../Concepts/dt_blob.md#blob-types).
  • si `.kind` = "relatedEntity": nombre de la dataClass relacionada
  • si `.kind` = "relatedEntities": nombre de la dataClass relacionada + sufijo "Selection
  • si `.kind` = "calculated" o "alias": lo mismo que arriba, dependiendo del resultado
  • | +| unique | Boolean | True si el valor del atributo debe ser único. No se devuelve si `.kind` = "relatedEntity" o "relatedEntities". | +| classID | Text | Disponible sólo si `.type = "object"` y se ha especificado una clase en el editor de estructuras.
    Devuelve el nombre de la clase utilizada para instanciar el objeto. | :::tip @@ -623,6 +624,77 @@ El método proyecto ***SearchDuplicate*** busca valores duplicados en cualquier + + +## .getIndexes() + +
    Historia + +| Lanzamiento | Modificaciones | +| ----------- | -------------- | +| 21 R5 | Añadidos | + +
    + +**.getIndexes()** : Collection + + + +
    + +| Parámetros | Tipo | | Descripción | +| ---------- | ---------- | --------------------------- | --------------------------- | +| Resultado | Collection | <- | Colección de objetos índice | + +
    + + +#### Descripción + +The `.getIndexes()` function returns a collection of all indexes related to the dataclass. + +Each index is an object of the collection. Indexes are returned in the creation/modification order. An empty collection is returned if there is no index in the dataclass. + +**Colección devuelta** + +Each object of the returned collection has the following properties: + +| Propiedad | Tipo | Descripción | +| ---------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| type | Integer | Index type: -1 = Keywords, 0 = default, 1 = Standard B-Tree, 3 = Cluster B-Tree, 4 = Cosine, 5 = Dot, 6 = Euclidean. If the index is set to Automatic, the type property represents the type of the indexing algorithm used | +| automatic | Boolean | True if "automatic" index is selected | +| name | Text | Index name if defined | +| kind | Text | "keywords" if *keyword index* checked, otherwise "regular" | +| attributes | Collection | Index attribute or list of attributes (for composite index) | +| UUID | Text | Índice UUID | +| uniqueKey | Boolean | True if index has the Unique key property | + +:::tip Entrada de blog relacionada + +[Managing 4D Indexes Programmatically with getIndexes()](https://blog.4d.com/managing-4d-indexes-programmatically-with-getindexes) + +::: + +#### Ejemplo + +Considering the following table: + +![table-indexes](../assets/en/API/table-index.png) + +```4d + +var $colIndex:=ds.Products.getIndexes() + +//$colIndex[0]={"automatic":true,"kind":"regular","type":1,"uniqueKey":true,"UUID":"ADE...","attributes":["ID"]} +//$colIndex[1]={"automatic":true,"kind":"regular","type":1,"uniqueKey":false,"UUID":"00D...","attributes":["name"]} +//$colIndex[2]={"name":"Description","automatic":false,"kind":"keywords","type":-1,"uniqueKey":false,"UUID":"37B...","attributes":["description"]} +//$colIndex[3]={"automatic":false,"kind":"regular","type":5,"uniqueKey":false,"UUID":"618...","attributes":["embedding"]} +//$colIndex[4]={"automatic":true,"kind":"regular","type":3,"uniqueKey":false,"UUID":"297...","attributes":["embedding"]} +//$colIndex[5]={"automatic":false,"kind":"regular","type":4,"uniqueKey":false,"UUID":"EA8...","attributes":["embedding"]} +``` + + + ## .getInfo() @@ -727,7 +799,7 @@ La función `.getInfo()` devuelve #### Descripción -La función `.getRemoteCache()` devuelve un objeto que contiene el contenido de la caché ORDA para una clase de datos. +La función `.setRemoteCacheSettings()` define el tiempo de espera y el tamaño máximo de la caché ORDA para una dataclass.. Llamar a esta función desde una aplicación monopuesto de 4D devuelve `Null`. @@ -893,12 +965,12 @@ Cuando se crea, la selección de entidades no contiene ninguna entidad (`mySelec
    Historia -| Lanzamiento | Modificaciones | -| ----------- | ------------------------------------------------------ | -| 21 | Soporte de los objetos 4D.Vector | -| 17 R6 | Soporte de los parámetros Formula | -| 17 R5 | Soporte de los marcadores de posición para los valores | -| 17 | Añadidos | +| Lanzamiento | Modificaciones | +| ----------- | ------------------------------------------------ | +| 21 | Soporte de los objetos 4D.Vector | +| 17 R6 | Soporte de los parámetros Formula | +| 17 R5 | Soporte de los marcadores para los valores | +| 17 | Añadidos |
    @@ -1030,18 +1102,18 @@ El uso de marcadores de posición en las búsquedas **se recomienda** por las si 1. Evita la inserción de código malicioso: si utiliza directamente variables completadas por el usuario dentro de la cadena de búsqueda, un usuario podría modificar las condiciones de búsqueda introduciendo argumentos de búsqueda adicionales. Por ejemplo, imagine una cadena de búsqueda como: -```4d - $vquery:="status = 'public' & name = "+myname //el usuario introduce su nombre - $result:=$col.query($vquery) -``` + ```4d + $vquery:="status = 'public' & name = "+myname //el usuario introduce su nombre + $result:=$col.query($vquery) + ``` Esta búsqueda parece segura ya que se filtran los datos no públicos. Sin embargo, si el usuario introduce en el área *myname* algo como *"smith OR status='private'*, la cadena de consulta se modificaría en el paso de interpretación y podría devolver datos privados. Cuando se utilizan marcadores de posición, no es posible anular las condiciones de seguridad: -```4d - $result:=$col.query("status='public' & name=:1";myname) -``` + ```4d + $result:=$col.query("status='public' & name=:1";myname) + ``` En este caso, si el usuario introduce *smith OR status='private'* en el área *myname*, no se interpretará en la cadena de búsqueda, sino que sólo se pasará como valor. La búsqueda de una persona llamada "smith OR status='private'" simplemente fallará. @@ -1049,10 +1121,10 @@ En este caso, si el usuario introduce *smith OR status='private'* en el área *m 3. Permite el uso de variables o expresiones en los argumentos de búsqueda. Ejemplos: -```4d -$result:=$col.query("address.city = :1 & name =:2";$city;$myVar+"@") -$result2:=$col.query("company.name = :1";"John's Pizzas") -``` + ```4d + $result:=$col.query("address.city = :1 & name =:2";$city;$myVar+"@") + $result2:=$col.query("company.name = :1";"John's Pizzas") + ``` ### Búsqueda de valores null @@ -1222,11 +1294,11 @@ Si *attributePath* designa un atributo que almacena [**objetos vectores**](../AP En este caso, el parámetro *value* debe ser un **objeto vectorial de comparación** que contenga las siguientes propiedades: -| Propiedad | Tipo | Descripción | -| --------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| vector | [4D.Vector](../API/VectorClass.md) | Obligatorio. El vector a comparar | -| metric | Text | Opcional. [Cálculo vectorial](../API/VectorClass.md#understanding-the-different-vector-computations) a utilizar para la consulta. Puede utilizar una de las siguientes constantes (de texto):
  • `mk cosine` (valor por defecto si no se especifica): calcula la [similitud coseno](./VectorClass.md#cosinesimilarity) entre vectores.
  • `mk dot`: calcula la [similitud escalar](VectorClass.md#dotsimilarity) de los vectores.
  • `mk euclidean`: calcula la [distancia euclidiana](./VectorClass.md#euclideandistance) entre vectores. | -| threshold | Real | Opcional (por defecto: 0,5). Un valor umbral utilizado para filtrar las comparaciones de vectores en función de su puntuación de similitud coseno, punto o euclídea según la "métrica" seleccionada. Es altamente recomendable elegir una similitud que se adapte mejor a su caso de uso específico para obtener resultados óptimos. | +| Propiedad | Tipo | Descripción | +| --------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| vector | [4D.Vector](../API/VectorClass.md) | Obligatorio. El vector a comparar | +| metric | Text | Opcional. [Cálculo vectorial](../API/VectorClass.md#understanding-the-different-vector-computations) a utilizar para la consulta. Puede utilizar una de las siguientes constantes (Texto):
  • `mk cosine` (valor por defecto si no se especifica): calcula la [similitud coseno](./VectorClass.md#cosinesimilarity) entre vectores.
  • `mk dot`: calcula la [similitud escalar](VectorClass.md#dotsimilarity) entre vectores.
  • `mk euclidean`: calcula la [distancia euclidiana](./VectorClass.md#euclideandistance) entre vectores. | +| threshold | Real | Opcional (por defecto: 0,5). Un valor umbral utilizado para filtrar las comparaciones de vectores en función de su puntuación de similitud coseno, punto o euclídea según la "métrica" seleccionada. Es altamente recomendable elegir una similitud que se adapte mejor a su caso de uso específico para obtener resultados óptimos. | Sólo se admite un subconjunto de símbolos **comparadores**. Tenga en cuenta que comparan los resultados con el valor umbral: @@ -1700,7 +1772,7 @@ var $results := ds.MyTable.query("myVectorField <= :1 AND salary>100000 order by #### Descripción -La función `.setRemoteCacheSettings()` define el tiempo de espera y el tamaño máximo de la caché ORDA para una dataclass.. +La función `.getRemoteCache()` devuelve un objeto que contiene el contenido de la caché ORDA para una clase de datos.. En el parámetro *settings*, pase un objeto con las siguientes propiedades: diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/DataStoreClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/DataStoreClass.md index 5e26815a43b39b..58003eb5d415be 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/DataStoreClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/DataStoreClass.md @@ -457,7 +457,7 @@ La función `.getInfo()` devuelve | Propiedad | Tipo | Descripción | | ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | type | string |
  • "4D": datastore principal, disponible a través de ds
  • "4D Server": datastore remoto, abrir con Open datastore
  • | -| networked | boolean |
  • True: el datastore se alcanza a través de una conexión de red.
  • False: el datastore no se alcanza a través de una conexión de red (base de datos local)
  • | +| networked | boolean |
  • True: el almacén de datos se alcanza a través de una conexión de red.
  • False: no se llega al almacén de datos a través de una conexión de red (base de datos local)
  • | | localID | text | ID del almacén de datos en la máquina. ID del almacén de datos en la máquina. Cadena vacía ("") para el almacén de datos principal. | | connection | object | Objeto que describe la conexión del almacén de datos remoto (no se devuelve para el almacén de datos principal). Propiedades disponibles:
    PropiedadTipoDescripción
    nombre de hosttextoDirección IP o nombre del datastore remoto + ":" + número de puerto
    tlsbooleanoTrue si se utiliza una conexión segura con el datastore remoto
    idleTimeoutnúmeroTiempo de inactividad de la sesión (en minutos)
    usuariotextoUsuario autenticado en el almacén de datos remoto
    | @@ -524,7 +524,7 @@ En un almacén de datos remoto: #### Descripción -La función `.getRemoteContextInfo()` devuelve un objeto que contiene información sobre el contexto de optimización *contextName* en el datastore. +La función `.getRemoteContextInfo()` devuelve un objeto que contiene información sobre el contexto de optimización *contextName* en el datastore.. Para obtener más información sobre cómo se pueden crear contextos de optimización, consulte [optimización cliente/servidor](../ORDA/client-server-optimization.md#optimization-context). @@ -1063,13 +1063,13 @@ Para una descripción del formato del registro de peticiones ORDA, por favor con Para crear un registro de peticiones ORDA del lado del cliente, llame a esta función en una máquina remota. El registro puede enviarse a un archivo o a la memoria, según el tipo de parámetro: -- Si se pasa un objeto *file* creado con el comando `File`, los datos de registro se escriben en este archivo como una colección de objetos (formato JSON). Cada objeto representa una petición.
    Si el archivo no existe ya, se crea. En caso contrario, si el archivo ya existe, los nuevos datos de registro se añaden a él. +- Si se pasa un objeto *file* creado con el comando `File`, los datos de registro se escriben en este archivo como una colección de objetos (formato JSON). Cada objeto representa una petición.
    Si el archivo no existe, se crea. En caso contrario, si el archivo ya existe, los nuevos datos de registro se añaden a él. En caso contrario, si el archivo ya existe, los nuevos datos de registro se añaden a él. Si se llama a `.startRequestLog()` con un archivo mientras se inició previamente un registro en memoria, el registro en memoria se detiene y se vacía. > Debe añadirse manualmente un carácter \N al final del archivo para realizar una validación JSON -- Si se pasa un entero *reqNum*, se vacía el registro en memoria (si lo hay) y se inicializa un nuevo registro. Mantendrá *reqNum* en memoria las peticiones hasta que se alcance el número, en cuyo caso se vacían las entradas más antiguas (pila FIFO).
    Si se llama a `.startRequestLog()` con un *reqNum* mientras se ha iniciado previamente un registro en un archivo, se detiene el registro en el archivo. +- Si se pasa un entero *reqNum*, se vacía el registro en memoria (si lo hay) y se inicializa un nuevo registro. Si se pasa un entero *reqNum*, se vacía el registro en memoria (si lo hay) y se inicializa un nuevo registro.Conserva las peticiones *reqNum* en memoria hasta que se alcance el número, en cuyo caso se vacían las entradas más antiguas (pila FIFO).
    - Si no ha pasado ningún parámetro, el registro se inicia en la memoria. Si `.startRequestLog()` fue llamado previamente con un *reqNum* (antes de una `.stopRequestLog()`), los datos del registro se apilan en memoria hasta la próxima vez que se vacíe el registro o se llame a `.stopRequestLog()`. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/EntityClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/EntityClass.md index fd1014aee84737..be8d499e33398e 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/EntityClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/EntityClass.md @@ -107,7 +107,7 @@ Esta función permite actualizar las entidades por separado. Sin embargo, tenga > Tenga en cuenta que toda modificación realizada a las entidades se guardará en el registro referenciado sólo cuando se ejecute la función [`.save()`](#save). -Esta función sólo puede utilizarse con entidades ya guardadas en la base de datos. La función `.touched()` devuelve True si al menos un atributo de la entidad ha sido modificado desde que la entidad fue cargada en memoria o guardada. +Esta función sólo puede utilizarse con entidades ya guardadas en la base de datos. No se puede llamar a una entidad recién creada (para la que [`isNew()`](#isnew) devuelve **True**). #### Ejemplo 1 @@ -402,15 +402,15 @@ El objeto devuelto por `.drop()` contiene las siguientes propiedades: (\*) Los siguientes valores pueden ser devueltos en las propiedades *status* y *statusText* del objeto *Result* en caso de error: -| Constante | Valor | Comentario | -| ----------------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `dk status entity does not exist anymore` | 5 | La entidad ya no existe en los datos. Este error puede ocurrir en los siguientes casos:
  • la entidad ha sido eliminada (el marcador ha cambiado y ahora el espacio de memoria está libre)
  • la entidad ha sido eliminada y reemplazada por otra con otra clave primaria (el marcador ha cambiado y una nueva entidad ahora utiliza el espacio memoria). Cuando se utiliza entity.drop(), este error puede ser devuelto cuando se utiliza la opción dk force drop if stamp changed. Cuando se utiliza entity.lock(), se puede devolver este error cuando la opción dk reload if stamp changed es utilizada.
  • **statusText asociado**: "Entity does not exist anymore" | -| `dk status locked` | 3 | La entidad está bloqueada por un bloqueo pesimista.
    **statusText asociado**: "Already locked" | -| `dk status validation failed` | 7 | Error no crítico enviado por el desarrollador para un [evento de validación](../ORDA/orda-events.md). **statusText asociado**: "Mild Validation Error" | -| `dk status serious error` | 4 | Un error grave es un error de base de datos de bajo nivel (por ejemplo, una llave duplicada), un error de hardware, etc.
    **statusText asociado**: "Other error" | -| `dk status serious validation error` | 8 | Error crítico enviado por el desarrollador para un [evento de validación](../ORDA/orda-events.md). **statusText asociado**: "Serious Validation Error" | -| `dk status stamp has changed` | 2 | El valor del marcador interno de la entidad no coincide con el de la entidad almacenada en los datos (bloqueo optimista).
  • con `.save()`: error solo si no se utiliza la opción `dk auto merge`
  • con `.drop()`: error solo si no se utiliza la opción `dk force drop if stamp changed`
  • con `.lock()`: error solo si no se utiliza la opción `dk reload if stamp changed`
  • **statusText asociado**: "Stamp has changed"
  • | -| `dk status wrong permission` | 1 | Los privilegios actuales no permiten suprimir la entidad. **StatusText asociado**: "Permission Error" | +| Constante | Valor | Comentario | +| ----------------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dk status entity does not exist anymore` | 5 | La entidad ya no existe en los datos. Este error puede ocurrir en los siguientes casos:
  • la entidad ha sido eliminada (el marcador ha cambiado y ahora el espacio de memoria está libre)
  • la entidad ha sido eliminada y reemplazada por otra con otra clave primaria (el marcador ha cambiado y una nueva entidad ahora utiliza el espacio memoria). Cuando se utiliza entity.drop(), este error puede ser devuelto cuando se utiliza la opción dk force drop if stamp changed. Cuando se utiliza entity.lock(), este error puede ser devuelto cuando se utiliza la opción dk reload if stamp changed
  • **statusText asociado**: "La entidad ya no existe" **statusText asociado**: "La entidad ya no existe" | +| `dk status locked` | 3 | La entidad está bloqueada por un bloqueo pesimista.
    **statusText asociado**: "Already locked" | +| `dk status validation failed` | 7 | Error no crítico enviado por el desarrollador para un [evento de validación](../ORDA/orda-events.md). **statusText asociado**: "Mild Validation Error" | +| `dk status serious error` | 4 | Un error crítico es un error de bajo nivel de la base de datos (por ejemplo, una llave duplicada), un error de hardware, etc.
    ***statusText asociado***: "Other error" | +| `dk status serious validation error` | 8 | Error crítico enviado por el desarrollador para un [evento de validación](../ORDA/orda-events.md). **statusText asociado**: "Serious Validation Error" | +| `dk status stamp has changed` | 2 | El valor del marcador interno (stamp) de la entidad no coincide con el de la entidad almacenada en los datos (bloqueo optimista).
  • con `.save()`: error sólo si no se utiliza la opción `dk auto merge`.
  • con `.drop()`: error sólo si no se usa la opción `dk force drop if stamp changed`
  • con `.lock()`: error sólo si no se utiliza la opción `dk reload if stamp changed`.
  • **statusText asociado**: "Stamp has changed"
  • | +| `dk status wrong permission` | 1 | Los privilegios actuales no permiten suprimir la entidad. **StatusText asociado**: "Permission Error" | #### Ejemplo 1 @@ -915,7 +915,7 @@ El valor resultante se incluye entre 0 y la longitud de la selección de entidad #### Descripción -True si la entidad acaba de ser creada y aún no se ha guardado. . +La función `.isNew()` devuelve True si la entidad a la que se aplica acaba de ser creada y aún no ha sido guardada en el datastore. En caso contrario, devuelve False. #### Ejemplo @@ -1061,8 +1061,8 @@ El objeto devuelto por `.lock()` contiene las siguientes propiedades: | ----------------------------------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `dk status entity does not exist anymore` | 5 | La entidad ya no existe en los datos. Este error puede ocurrir en los siguientes casos:
  • la entidad ha sido eliminada (el marcador ha cambiado y ahora el espacio de memoria está libre)
  • la entidad ha sido eliminada y reemplazada por otra con otra clave primaria (el marcador ha cambiado y una nueva entidad ahora utiliza el espacio memoria). Cuando se utiliza `.drop()`, este error puede devolverse cuando se utiliza la opción dk force drop if stamp changed. Cuando se utiliza `.lock()`, este error puede ser devuelto cuando se utiliza la opción `dk reload if stamp changed`

  • **statusText asociado**: "Entity does not exist anymore" | | `dk status locked` | 3 | La entidad está bloqueada por un bloqueo pesimista. **statusText asociado**: "Already locked" | -| `dk status serious error` | 4 | Un error grave es un error de base de datos de bajo nivel (por ejemplo, una llave duplicada), un error de hardware, etc.
    **statusText asociado**: "Other error" | -| `dk status stamp has changed` | 2 | El valor del marcador interno de la entidad no coincide con el de la entidad almacenada en los datos (bloqueo optimista).
  • con `.save()`: error solo si no se utiliza la opción `dk auto merge`
  • con `.drop()`: error solo si no se utiliza la opción `dk force drop if stamp changed`
  • con `.lock()`: error solo si no se utiliza la opción `dk reload if stamp changed`

  • **Estado asociado**: "Stamp has changed" | +| `dk status serious error` | 4 | Un error crítico es un error de bajo nivel de la base de datos (por ejemplo, una llave duplicada), un error de hardware, etc.
    ***statusText asociado***: "Other error" | +| `dk status stamp has changed` | 2 | El valor del sello interno de la entidad no coincide con el de la entidad almacenada en los datos (bloqueo optimista).con `.save()`: error sólo si no se utiliza la opción `dk auto merge`
  • con `.drop()`: error sólo si no se usa la opción `dk force drop if stamp changed`
  • con `.lock()`: error sólo si no se utiliza la opción `dk reload if stamp changed`.

  • **statusText asociado**: "Stamp has changed" | #### Ejemplo 1 @@ -1236,7 +1236,7 @@ El objeto devuelto por `.reload( )` contiene las siguientes propiedades: | Constante | Valor | Comentario | | ----------------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `dk status entity does not exist anymore` | 5 | La entidad ya no existe en los datos. Este error puede ocurrir en los siguientes casos:
  • la entidad ha sido eliminada (el marcador ha cambiado y ahora el espacio de memoria está libre)
  • la entidad ha sido eliminada y reemplazada por otra con otra clave primaria (el marcador ha cambiado y una nueva entidad ahora utiliza el espacio memoria). Cuando se utiliza `.drop()`, este error puede devolverse cuando se utiliza la opción `dk force drop if stamp changed`. Cuando se utiliza `.lock()`, este error puede ser devuelto cuando se utiliza la opción `dk reload if stamp changed`

  • **statusText asociado**: "Entity does not exist anymore" | -| `dk status serious error` | 4 | Un error grave es un error de base de datos de bajo nivel (por ejemplo, una llave duplicada), un error de hardware, etc.
    ***statusText asociado***: "Other error" | +| `dk status serious error` | 4 | Un error crítico es un error de bajo nivel de la base de datos (por ejemplo, una llave duplicada), un error de hardware, etc.
    **statusText asociado**\*: "Other error" | #### Ejemplo @@ -1339,7 +1339,7 @@ Los siguientes valores pueden ser devueltos en las propiedades `status`y `status | `dk status validation failed` | 7 | Error no crítico enviado por el desarrollador para un [evento de validación](../ORDA/orda-events.md). **statusText asociado**: "Mild Validation Error" | | `dk status serious error` | 4 | Un error grave es un error de base de datos de bajo nivel (por ejemplo, una llave duplicada), un error de hardware, etc. **statusText asociado**: "Other error" | | `dk status serious validation error` | 8 | Error crítico enviado por el desarrollador para un [evento de validación](../ORDA/orda-events.md). **statusText asociado**: "Serious Validation Error" | -| `dk status stamp has changed` | 2 | El valor del marcador interno de la entidad no coincide con el de la entidad almacenada en los datos (bloqueo optimista).
  • con `.save()`: error solo si no se utiliza la opción `dk auto merge`
  • con `.drop()`: error solo si no se utiliza la opción `dk force drop if stamp changed`
  • con `.lock()`: error solo si no se utiliza la opción `dk reload if stamp changed`

  • **statusText asociado**: "Stamp has changed" | +| `dk status stamp has changed` | 2 | El valor del marcador interno (stamp) de la entidad no coincide con el de la entidad almacenada en los datos (bloqueo optimista).
  • con `.save()`: error sólo si no se utiliza la opción `dk auto merge`.
  • con `.drop()`: error sólo si no se usa la opción `dk force drop if stamp changed`
  • con `.lock()`: error sólo si no se utiliza la opción `dk reload if stamp changed`.

  • **statusText asociado**: "Stamp has changed" | | `dk status wrong permission` | 1 | Los privilegios actuales no permiten guardar la entidad. **StatusText asociado**: "Permission Error" | #### Ejemplo 1 diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/FileHandleClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/FileHandleClass.md index fad94d0a7b6cb1..6ebb4240874f44 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/FileHandleClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/FileHandleClass.md @@ -278,7 +278,7 @@ Esta propiedad es **lectura-escritura**. :::caution -Cuando se crea un file handle, el valor `.offset` es un número de bytes. Sin embargo, la unidad de medida del offset difiere según la función de lectura: con [`readBlob()`](#readblob), `.offset` es un número de bytes, mientras que con [`readText()`](#readtext)/[`readLine()`](#readline) es un número de caracteres. Según el conjunto de caracteres del archivo, un caracter corresponde a uno o varios bytes. Según el conjunto de caracteres del archivo, un caracter corresponde a uno o varios bytes. Por lo tanto, si comienza a leer con `readBlob()` y luego llama a `readText()`, la lectura de texto comenzará en una posición inconsistente. Por ejemplo: +Cuando se crea un file handle, el valor `.offset` es un número de bytes. Sin embargo, la unidad de medida del offset difiere según la función de lectura: con [`readBlob()`](#readblob), `.offset` es un número de bytes, mientras que con [`readText()`](#readtext)/[`readLine()`](#readline) es un número de caracteres. Según el conjunto de caracteres del archivo, un caracter corresponde a uno o varios bytes. Por lo tanto, si comienza a leer con `readBlob()` y luego llama a `readText()`, la lectura de texto comenzará en una posición inconsistente. Por eso, es esencial que establezca usted mismo la propiedad `.offset` si pasa de leer/escribir blob a leer/escribir texto en el mismo filehandle. Por ejemplo: ```4d // Abrir un fichero de texto europeo con codificación utf-16 (dos bytes por caracter) diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/IMAPTransporterClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/IMAPTransporterClass.md index bdcfe1c3ab1725..c7982688db4f67 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/IMAPTransporterClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/IMAPTransporterClass.md @@ -683,7 +683,7 @@ End if #### Descripción -La función `.expunge()` elimina todos los mensajes con el marcador "deleted" del servidor de correo IMAP. El marcador "deleted" puede definirse con los métodos [`delete()`](#delete) o [`addFlags()`](#addflags). +La función `.expunge()` elimina todos los mensajes con la bandera "eliminada" del servidor de correo IMAP. La bandera "deleted" puede definirse con los métodos [`.delete()`](#delete) o [`.addFlags()`](#addflags). **Objeto devuelto** @@ -830,16 +830,16 @@ En el parámetro opcional `parameters`, pase un objeto que contenga valores para Cada objeto de la colección devuelta contiene las siguientes propiedades: -| Propiedad | Tipo | Descripción | -| ------------------------------------------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| \[].name | Text | Nombre del buzón. Devuelto si withBoxProperties=true o withBoxInfo=true | -| \[].selectable | Boolean | Indica si los derechos de acceso permiten o no seleccionar el buzón de correo: Devuelto si withBoxProperties=true | -| \[].inferior | Boolean | Indica si los derechos de acceso permiten o no crear una jerarquía inferior en el buzón: Se devuelve si withBoxProperties=true | -| \[].interesting | Boolean | Indica si el buzón ha sido marcado como "interesante" por el servidor: Devuelto si withBoxProperties=true | -| [].mailCount | Number | Número de mensajes en el buzón. Devuelto si withBoxInfo=true | -| [].mailRecent | Number | Número de mensajes marcados como "recent" (indicando nuevos mensajes). Devuelto si withBoxInfo=true | -| [].mailUnseen | Number | Número de mensajes marcados como "unseen". Devuelto si withBoxInfo=true | -| [].id | Text | Identificador único del buzón. Devuelto si withBoxInfo=true | +| Propiedad | Tipo | Descripción | +| ------------------------------------------------------------------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| \[].name | Text | Nombre del buzón. Devuelto si withBoxProperties=true o withBoxInfo=true | +| \[].selectable | Boolean | Indica si los derechos de acceso permiten o no seleccionar el buzón de correo: Devuelto si withBoxProperties=true | +| \[].inferior | Boolean | Indica si los derechos de acceso permiten o no crear una jerarquía inferior en el buzón: Se devuelve si withBoxProperties=true | +| \[].interesting | Boolean | Indica si el buzón ha sido marcado como "interesante" por el servidor: Se devuelve si withBoxProperties=true | +| [].mailCount | Number | Número de mensajes en el buzón. Devuelto si withBoxInfo=true | +| [].mailRecent | Number | Número de mensajes marcados como "recent" (indicando nuevos mensajes). Devuelto si withBoxInfo=true | +| [].mailUnseen | Number | Número de mensajes marcados como "unseen". Devuelto si withBoxInfo=true | +| [].id | Text | Identificador único del buzón. Devuelto si withBoxInfo=true | Si la cuenta no contiene buzones, se devuelve una colección vacía. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/IncomingMessageClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/IncomingMessageClass.md index 399b1a09dca59d..efc698389ff3cb 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/IncomingMessageClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/IncomingMessageClass.md @@ -101,7 +101,7 @@ Un objeto 4D.IncomingMessage es un objeto [no compartible](../Concepts/shared.md ## .getBlob() -**.getBlob**() : Blob +**.getBlob**(): Blob @@ -222,7 +222,7 @@ Si el cuerpo no se recibe como una imagen válida, la función devuelve null. ## .getText() -**.getText**() : Text +**.getText**(): Text @@ -301,7 +301,7 @@ La propiedad `.urlPath` es de sólo lectura. ## .urlQuery -**urlQuery** : Object +**urlQuery**: Object #### Descripción @@ -334,10 +334,10 @@ Los caracteres especiales, como las comillas simples o los retornos de carro, de Ejemplo: `http://127.0.0.1:8044/syntax/?mdcode=%60%60%604d` -````4d +```4d //urlQuery.mdcode = ```4d $test:=Length($r.urlQuery.mdcode) //5 -```` +``` :::note diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/QuotaManagerClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/QuotaManagerClass.md index 69b486d8500728..5a1a2846fc5303 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/QuotaManagerClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/QuotaManagerClass.md @@ -65,7 +65,7 @@ Los objetos 4D.QuotaManager ofrecen las siguientes propiedades: #### Descripción -The `.currentValues` property contains current usage values for the quota manager. 4D lo actualiza automáticamente y es de solo lectura. +La propiedad `.currentValues` contiene los valores actuales utilizado para el gestor de cuotas. 4D lo actualiza automáticamente y es de solo lectura. El objeto tiene las mismas propiedades que el objeto `4D.QuotaManager`, pero solo las siguientes propiedades indican el uso actual: @@ -123,7 +123,7 @@ Session.quotas.defaultEntitySetTimeout:=1200 #### Descripción -The `.inBytesPerHour` property contains the maximum total number of bytes that the Web server can receive in one hour. +La propiedad `.inBytesPerHour` contiene el número total máximo de bytes que el servidor web puede recibir en una hora. Alcance: [servidor global](./WebServerClass.md#scope-levels) @@ -151,7 +151,7 @@ Alcance: [sesión por defecto](./WebServerClass.md#scope-levels) #### Descripción -The `.inBytesPerMin` property contains the maximum total number of bytes that the Web server can receive in one minute. +La propiedad `.inBytesPerMin` contiene el número total máximo de bytes que el servidor web puede recibir en un minuto. Alcance: [servidor global](./WebServerClass.md#scope-levels) @@ -276,7 +276,7 @@ Alcance: [sesión por defecto](./WebServerClass.md#scope-levels) #### Descripción -The `.nbGuestSessions` property contains the maximum total number of active [Guest sessions](./SessionClass.md#isguest) on the Web server. +La propiedad `.nbGuestSessions` contiene el número total máximo de [sesiones de invitado](./SessionClass.md#isguest) activas en el servidor web. Alcance: [servidor global](./WebServerClass.md#scope-levels) @@ -346,7 +346,7 @@ Alcance: [sesión por defecto](./WebServerClass.md#scope-levels) #### Descripción -The `.nbSessions` property contains the maximum total number of active sessions on the Web server. +La propiedad `.nbSessions` contiene el número total máximo de sesiones activas en el servidor web. Alcance: [servidor global](./WebServerClass.md#scope-levels) @@ -360,7 +360,7 @@ Alcance: [servidor global](./WebServerClass.md#scope-levels) #### Descripción -The `.outBytesPerHour` property contains the maximum total number of bytes that the Web server can send in one hour. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. +La propiedad `.outBytesPerHour` contiene el número total máximo de bytes que el servidor web puede enviar en una hora. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. Alcance: [servidor global](./WebServerClass.md#scope-levels) @@ -374,7 +374,7 @@ Alcance: [servidor global](./WebServerClass.md#scope-levels) #### Descripción -The `.outBytesPerHourPerSession` property contains the maximum total number of bytes that the Web server can send for a session in one hour. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. +La propiedad `.outBytesPerHourPerSession` contiene el número máximo total de bytes que el servidor web puede enviar durante una sesión en una hora. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. Alcance: [sesión por defecto](./WebServerClass.md#scope-levels) @@ -388,7 +388,7 @@ Alcance: [sesión por defecto](./WebServerClass.md#scope-levels) #### Descripción -The `.outBytesPerMin` property contains the maximum total number of bytes that the Web server can send in one minute. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. +La propiedad `.outBytesPerMin` contiene el número máximo total de bytes que el servidor web puede enviar en un minuto. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. Alcance: [servidor global](./WebServerClass.md#scope-levels) @@ -402,7 +402,7 @@ Alcance: [servidor global](./WebServerClass.md#scope-levels) #### Descripción -The `.outBytesPerMinPerSession` property contains the maximum total number of bytes that the Web server can send for a session in one minute. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. +La propiedad `.outBytesPerMinPerSession` contiene el número máximo total de bytes que el servidor web puede enviar durante una sesión en un minuto. La cuota se calcula en función del tamaño de la carga útil de la respuesta sin comprimir, independientemente de la configuración de compresión del servidor web. Alcance: [sesión por defecto](./WebServerClass.md#scope-levels) diff --git a/i18n/es/docusaurus-plugin-content-docs/current/API/SessionClass.md b/i18n/es/docusaurus-plugin-content-docs/current/API/SessionClass.md index 8fe4123abf4b88..091bba5277db66 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/API/SessionClass.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/API/SessionClass.md @@ -20,7 +20,7 @@ Los siguientes tipos de sesiones están soportados por esta clase: - [**Sesiones usuario web**](WebServer/sessions.md): las sesiones usuario web están disponibles cuando [las sesiones escalables están activas en su proyecto](WebServer/sessions.md#enabling-web-sessions). Se utilizan para las conexiones Web (incluidos los accesos REST) y se controlan mediante los [privilegios](../ORDA/privileges.md) asignados. - [**Sesiones usuario remoto**](../Desktop/sessions.md#remote-user-sessions): en las aplicaciones cliente/servidor, los usuarios remotos tienen sus propias sesiones gestionadas desde el cliente y el servidor. -- [**Sesiones procedimientos almacenados**](../Desktop/sessions.md#stored-procedure-sessions): sesión usuario virtual para todos los procedimientos almacenados ejecutados en el servidor. +- [Sesiones procedimientos almacenados\*\*](../Desktop/sessions.md#stored-procedure-sessions): sesión usuario virtual para todos los procedimientos almacenados ejecutados en el servidor. - [**Sesiones autónomas**](../Desktop/sessions.md#standalone-sessions): sesión local devuelta en una aplicación mono usuario (útil en las fases de desarrollo y de prueba de las aplicaciones cliente/servidor). :::warning Acerca de los privilegios de sesión @@ -522,8 +522,8 @@ El objeto `.info` contiene las siguientes propiedades: | ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | type | Text | Tipo de sesión: "remote", "storedProcedure", "standalone", "rest", "web" | | userName | Text | Nombre de usuario 4D (mismo valor que [`.userName`](#username)) | -| machineName | Text | | -| systemUserName | Text |