Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
** xref:dataweave-memory-management.adoc[Memory Management]
** xref:dataweave-logging-configuration.adoc[Logging Configuration]
** xref:dataweave-versioning-behavior.adoc[Versioning Behavior in DataWeave]
** xref:dataweave-scope-visibility.adoc[Scope Visibility in DataWeave]
* xref:dataweave-cookbook.adoc[DataWeave Examples]
** xref:dataweave-cookbook-extract-data.adoc[Extract Data]
** xref:dataweave-cookbook-select-xml-elements.adoc[Select XML Elements]
Expand Down
2 changes: 2 additions & 0 deletions modules/ROOT/pages/_partials/nav-dw.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@
** xref:dw-dataformat.adoc[dw::extension::DataFormat]
*** xref:dw-dataformat-types.adoc[DataFormat Types]
*** xref:dw-dataformat-annotations.adoc[DataFormat Annotations]
** xref:dw-component.adoc[dw::meta::Component]
*** xref:dw-component-types.adoc[Component Types]
** xref:dw-mime.adoc[dw::module::Mime]
*** xref:dw-mime-functions-fromstring.adoc[fromString]
*** xref:dw-mime-functions-ishandledby.adoc[isHandledBy]
Expand Down
16 changes: 16 additions & 0 deletions modules/ROOT/pages/dataweave-extension-plugin.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,22 @@ To check the logs, follow these steps:

image::dataweave-extension-logs.png[Mule DX DataWeave LS option to select in the drop-down menu of the Output]

== Scope Visibility (DataWeave 2.12.0 and Later)

When you author DataWeave *libraries* — `.dwl` files that other DataWeave code imports — the DataWeave extension recognizes the new visibility model added in 2.12.0:

* The keywords `private` and `internal` are highlighted as language keywords.
* The `@VisibleTo` annotation is recognized when applied to `internal` directives.
* The editor reports visibility violations inline, with the same wording the compiler uses (`... cannot be accessed from ... as it is private to the module ...`, `... is internal to the component ...`).
* Auto-completion filters out directives that are not visible from the current file. For example, `private` helpers from another file will not appear in the suggestion list.
* `Go to definition` continues to work, but the editor warns when you navigate to a directive that is not accessible from the current file.

These features apply to library projects only. If you are writing a Mule *transformation mapping* inline (a `%dw 2.0` expression in a Transform Message component, a Set Variable expression, or a DataWeave expression embedded in a connector), the `internal` keyword and `@VisibleTo` annotation have no practical effect: an inline mapping is a self-contained script that cannot be imported from another inline mapping, so there is nothing to constrain. The keywords are still parsed, but you do not need them in mapping code.

The same applies to `.dwl` modules defined inside the Mule application. Every inline mapping and application-level module belongs to an "unnamed" component, so they can freely reference each other's `internal` directives. The `private` keyword still applies — it restricts a directive to its declaring file regardless of component.

For the full visibility model — what `private` and `internal` mean, what a *component* is, and how the component descriptor is generated by the DataWeave Maven plugin — see xref:dataweave::dataweave-scope-visibility.adoc[Scope Visibility in DataWeave].

== See Also

* xref:dataweave-extension.adoc[]
Expand Down
47 changes: 47 additions & 0 deletions modules/ROOT/pages/dataweave-maven-plugin.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,53 @@ include::dataweave::partial$dataweave-maven-plugin-config.adoc[tag=config]
</plugin>
----

== Configure Cryptographic Taint Analysis

The Maven plugin for DataWeave can run cryptographic taint analysis at compile time to help identify potential security vulnerabilities in your DataWeave code. The analysis tracks literal algorithm values that flow into parameters annotated with xref:dataweave::dw-crypto-annotations.adoc[`@CryptographicSink`] and fails the build when an algorithm matches the configured insecure list. See xref:dataweave::dw-crypto-annotations.adoc[Crypto Annotations] for details on the underlying annotation.

Inside the `plugin` configuration, add a `cryptoTaintAnalysisSettings` element configured to use parameters that meet your security needs:

[%header%autowidth.spread,cols=".^a,.^a,.^a,.^a"]
|===
|Name |Type |Default |Description

|`enabled`
|`boolean`
|`false`
|When this property is set to `true`, the plugin runs cryptographic taint analysis during compilation.

|`insecureAlgorithms`
|`String`
|`""`
|Comma-separated list of cryptographic algorithms considered insecure. The plugin reports a compilation error when one of these algorithms reaches a `@CryptographicSink` parameter. For example, `MD5,SHA1,DES,RC4`.

|`sensitiveModules`
|`String`
|`""`
|Comma-separated list of DataWeave modules to flag as sensitive. Use DataWeave module notation with the `::` separator. For example, `dw::crypto::CryptoModule,dw::security::HashModule`.
|===

=== Cryptographic Taint Analysis Example

The following example enables taint analysis and configures both the insecure algorithms and the sensitive modules to track:

.Example `pom.xml` file
[source,xml,linenums]
----
<plugin>
include::dataweave::partial$dataweave-maven-plugin-config.adoc[tag=config]
<configuration>
...
<cryptoTaintAnalysisSettings>
<enabled>true</enabled>
<insecureAlgorithms>MD5,SHA1,DES,RC4</insecureAlgorithms>
<sensitiveModules>dw::crypto::CryptoModule,dw::security::HashModule,dw::util::SecurityModule</sensitiveModules>
</cryptoTaintAnalysisSettings>
...
</configuration>
</plugin>
----

== Generate Documentation for a DataWeave Library

Run the `data-weave:generate-docs` goal to auto-generate the documentation for your DataWeave library, for example:
Expand Down
236 changes: 236 additions & 0 deletions modules/ROOT/pages/dataweave-scope-visibility.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
= Scope Visibility in DataWeave
:page-aliases: dataweave::dataweave-scope-visibility.adoc

DataWeave 2.12.0 introduces *scope visibility*: a way to control which directives in a DataWeave file can be referenced from other files. Visibility rules apply to module-level declarations: `fun`, `var`, `type`, `ns`, and `annotation`.

Scope visibility is intended primarily for *DataWeave library authors*. If you write Mule transformation mappings (the `%dw 2.0` script in a Transform Message component), you can ignore this feature: a mapping is a single, self-contained file that does not export anything to other files. Visibility becomes useful only when you publish a `.jar` that other DataWeave code imports.

== Visibility Levels

DataWeave 2.12.0 supports three visibility levels:

[%header%autowidth.spread]
|===
| Level | Keyword | Accessible from
| Public | _(none)_ | Anywhere. Default and only behavior in versions before 2.12.0.
| Private | `private` | The same file only.
| Internal | `internal` | Any file in the same xref:#components[component]. Can be widened with `@VisibleTo`.
|===

[NOTE]
====
Visibility checks run only at *compile time*. Once a script is compiled, no runtime visibility check is performed. This keeps execution overhead at zero and ensures pre-compiled (`.bdwl`) modules behave the same as source modules.
====

== Syntax

Place the visibility keyword before the directive keyword (`fun`, `var`, `type`, `ns`, `annotation`).

[source,dataweave]
----
%dw 2.0

// Public (default) — accessible from anywhere
fun greet(name: String) = "Hello, $(name)!"

// Private — accessible only inside this file
private fun normalize(name: String) = upper(name)

// Internal — accessible from any file in the same component
internal var defaultGreeting = "Hello"

// Type and namespace declarations also support visibility
private type UserName = String
internal ns http https://schemas.example.org/http
----

The `@VisibleTo` annotation widens an `internal` directive to a fixed list of additional components:

[source,dataweave]
----
%dw 2.0
import * from dw::Core

@VisibleTo(components = ["analytics", "reporting"])
internal fun computeStats(records: Array) = sizeOf(records)
----

`@VisibleTo` is only valid on `internal` directives. Applying it to a `private` directive or to a directive without a visibility keyword raises a compile-time error: `The @VisibleTo annotation can only be applied to 'internal' directives`.

[#components]
== What Is a Component?

DataWeave does not have a `module` or `package` keyword that groups files together. Until 2.12.0, every `.dwl` file lived in a single global namespace. To make `internal` meaningful, the language now uses the concept of a *component*: a named set of DataWeave resources (modules) that are compiled and packaged together.

A component is described by a *component descriptor* — a `.dwl` resource located at `META-INF/dw-components.dwl` inside a `.jar`. The descriptor is an array of components; each component lists the resources it owns:

[source,dataweave]
----
%dw 2.0
---
[
{
name: "wlang",
resources: {
"dw::Core": {},
"dw::Crypto": {},
"dw::core::Arrays": {},
"dw::core::Strings": {}
// ...
}
}
]
----

When the compiler resolves a reference to a symbol declared in another module, it looks up which component owns the *declaring* module and which component owns the *caller* module by consulting the descriptors on the classpath.

=== Generating the Descriptor

You don't write the descriptor by hand. The xref:dataweave::dataweave-maven-plugin.adoc[DataWeave Maven Plugin] generates it automatically:

* For a production build (`data-weave:package`), the plugin scans `src/main/dw`, derives the resource names of every `.dwl` file, and writes `target/generated-dataweave-metadata/dw-components.dwl`. The file is added to the produced JAR at `META-INF/dw-components.dwl`.
* For a test build (`data-weave:test`), the plugin scans both `src/main/dw` and `src/test/dw`, so test files belong to the same component as the production sources they exercise. This lets tests call `internal` directives without further configuration.

The component name defaults to the Maven `artifactId` of the project.

=== Component Resolution Algorithm

Given a reference from caller `A` to symbol `s` declared in module `B`:

. The compiler looks up `componentOf(B)` from the descriptors on the classpath.
. If `s` is `private`, access is allowed only when `A == B`.
. If `s` is `internal`, access is allowed when `componentOf(A) == componentOf(B)`, or when `componentOf(A)` appears in the `@VisibleTo` list on `s`.
. If `s` is `public`, access is always allowed.

If a module declares `internal` directives but no descriptor on the classpath claims it, the compiler emits the error `Module 'X' declares 'internal' members but has no component descriptor`. In that case, package the module with the DataWeave Maven Plugin or add a component descriptor that lists it.

== Compile-Time Validation

The compiler reports four new errors:

[%header%autowidth.spread]
|===
| Error kind | Triggered when
| `PrivateAccessViolation` | A reference targets a `private` directive declared in a different file.
| `InternalAccessViolation` | A reference targets an `internal` directive declared in a different component, when the caller's component is not in the directive's `@VisibleTo` list.
| `VisibleToRequiresInternal` | `@VisibleTo` is applied to a directive that is not `internal`.
| `MissingComponentForInternalDirective` | A module declares `internal` directives but no component descriptor on the classpath claims it.
|===

== Function Overloads and Visibility

Function overloads must share the same visibility. Mixing `internal fun foo(x: String) = ...` and `fun foo(x: Number) = ...` is rejected with an error indicating the expected visibility (taken from the first overload). This guarantees that callers see a single, consistent visibility for any given function name.

== Structural Types and Visibility Propagation

DataWeave is a *structural* type system. Visibility on a type controls who can reference the type *by name*; it does not propagate to functions or variables that use the type in their signature. A caller can invoke a function whose signature mentions a `private` type as long as the caller does not name that type.

[source,dataweave]
----
// In component A
private type Account = { id: String }

@VisibleTo(components = ["bat"])
internal fun createAccount(account: Account) = account

// In component B (bat)
import createAccount from componentA::Accounts

// OK — structural call, no explicit reference to `Account`
createAccount({ id: "abc" })

// Error — explicit reference to private type `Account`
createAccount({ id: "abc" }) as Account
----

The same rule applies to type annotations on variables (`var x: Account = ...`) and pattern matches that name a type.

== Examples

=== File-Local Helper

[source,dataweave]
----
// dw/core/Core.dwl

%dw 2.0

private fun isLegacyMode(): Boolean =
evaluateCompatibilityFlag("com.mulesoft.dw.legacyMode")

fun sizeOf(value) =
if (isLegacyMode()) legacyImpl(value) else newImpl(value)
----

`isLegacyMode` is reachable only inside `Core.dwl`.

=== Component-Internal Helper

[source,dataweave]
----
// dw/core/Internal.dwl (component: wlang)
%dw 2.0
internal fun dropFrame(): Boolean = ...

// dw/core/Core.dwl (component: wlang)
%dw 2.0
import dropFrame from dw::core::Internal
fun process() = if (dropFrame()) ... else ... // OK — same component

// com/acme/App.dwl (component: acme-app)
%dw 2.0
import dropFrame from dw::core::Internal // Error: internal to `wlang`
----

=== Sharing Internals With a Specific Component

[source,dataweave]
----
// dw/native/Native.dwl (component: wlang)
%dw 2.0

@VisibleTo(components = ["bat", "dataweave-io"])
internal fun nativeImpl() = ...

// bat/core/Runner.dwl (component: bat)
import nativeImpl from dw::native::Native // OK — bat is permitted

// com/paypal/Connector.dwl (component: paypal-connector)
import nativeImpl from dw::native::Native // Error — not permitted
----

== Migrating From `@Internal(permits=...)`

In versions before 2.12.0, the only way to constrain visibility was the experimental `@Internal(permits = [...])` annotation, which matched callers by `NameIdentifier` prefix. `@Internal` is still accepted in 2.12.0 but is deprecated in favor of the new keywords:

[%header%autowidth.spread]
|===
| Old form | Replacement
| `@Internal(permits = [])` | `private`
| `@Internal(permits = ["dw::"])` | `internal` (the consuming component must also be migrated to a 2.12.0 build so a descriptor exists)
| `@Internal(permits = ["bat::", "dw::"])` | `@VisibleTo(components = ["bat"])` `internal`
|===

Files that don't use any visibility keyword behave exactly as in earlier versions: every directive is public.

== Setting a Per-Component Language Level

When a host application embeds the DataWeave engine, it can pin a specific language level for each component using the new `componentLanguageLevels` parameter on `DWScriptingEngine.compileDWScript`:

[source,scala]
----
def compileDWScript(
script: String,
languageLevel: String,
componentLanguageLevels: util.Map[String, String] = new util.HashMap()
): DWScript
----

This is used together with `@Since` on function overloads to dispatch to the correct overload when a library evolves, ensuring backward compatibility for existing scripts.

== See Also

* xref:dataweave::dw-component.adoc[`dw::meta::Component` Module]
* xref:dataweave::dw-core-annotations.adoc[`@VisibleTo` Annotation]
* xref:dataweave::dataweave-maven-plugin.adoc[DataWeave Maven Plugin]
* xref:dataweave::dataweave-extension-plugin.adoc[DataWeave Extension Plugin]
47 changes: 47 additions & 0 deletions modules/ROOT/pages/dw-component-types.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
= Component Types (dw::meta::Component)

This module defines the DataWeave types for component descriptors.

[%header, cols="1,2a,3a"]
|===
| Type | Definition | Description

| ComponentDescriptor
| `type ComponentDescriptor = { name: ComponentName, resources: { &#40;NameIdentifier&#41;: ModuleDescriptor } }`
| Describes a single component. Contains the following fields:

* `name`: Component identifier referenced from `@VisibleTo`.
* `resources`: Modules owned by the component, keyed by `NameIdentifier`.

_Introduced in DataWeave version 2.12.0._


| ComponentName
| `type ComponentName = String`
| Identifier of a component, matching the `name` field of a `ComponentDescriptor`.

_Introduced in DataWeave version 2.12.0._


| ComponentsDescriptor
| `type ComponentsDescriptor = Array<ComponentDescriptor&#62;`
| Top-level type of a `dw-components.dwl` file: an array of components.

_Introduced in DataWeave version 2.12.0._


| ModuleDescriptor
| `type ModuleDescriptor = {}`
| Per-resource metadata. Reserved for future fields; emit `{}` for every entry.

_Introduced in DataWeave version 2.12.0._


| NameIdentifier
| `type NameIdentifier = String`
| Fully qualified DataWeave module name written with the `::` separator,
such as `"dw::core::Strings"`.

_Introduced in DataWeave version 2.12.0._

|===
12 changes: 12 additions & 0 deletions modules/ROOT/pages/dw-component.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
= Component (dw::meta::Component)

This module defines the schema of the DataWeave component descriptor.

The descriptor lives at `/META-INF/dw-components.dwl` inside a `.jar` and is
an `Array<ComponentDescriptor>`. The DataWeave Maven plugin generates it
automatically when packaging a `dw-library` artifact.


== Types

* xref:dw-component-types.adoc[Component Types]
Loading