Skip to content

Commit

Permalink
[WTF-1882] Add support for reference sets(beta) to the typings genera…
Browse files Browse the repository at this point in the history
…tor (#93)

## Checklist

-   Contains unit tests   ✅
-   Contains breaking changes  ❌
-   Compatible with: MX 10
-   Did you update version and changelog? ✅ ❌
-   PR title properly formatted (`[XX-000]: description`)? ✅ ❌

## This PR contains

-   [ ] Bug fix
-   [ ] Feature
-   [ ] Refactor
-   [ ] Documentation
-   [ ] Other (describe)

## What is the purpose of this PR?
Add support to the typings generator to be able to specify the
association types allowed in attribute properties. Since the feature is
still in beta, we are omitting it from the changelog for now.
_..._

## Relevant changes

Depending on the configuration of the association types, the typings
generator will now emit:

A client prop of (union) type ListAtrributeValue and/or
ListAttributeListValue if the attribute property has a data source. A
client prop of (union) type EditableValue and/or EditableListValue if
not.
  • Loading branch information
legio-vi-ferrata authored Jun 25, 2024
2 parents b572e26 + 7ec7bc7 commit 5a3585b
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 12 deletions.
4 changes: 4 additions & 0 deletions packages/pluggable-widgets-tools/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Changed

- We updated the Mendix package to version 10.12.38909.

### Fixed

- We fixed an issue where the rollup process would sometimes hang and prevent the widget build/release script from completing.
Expand Down
18 changes: 9 additions & 9 deletions packages/pluggable-widgets-tools/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/pluggable-widgets-tools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mendix/pluggable-widgets-tools",
"version": "10.7.3",
"version": "10.12.0",
"description": "Mendix Pluggable Widgets Tools",
"engines": {
"node": ">=16"
Expand Down Expand Up @@ -80,7 +80,7 @@
"jest-junit": "^13.0.0",
"jest-react-hooks-shallow": "^1.5.1",
"make-dir": "^3.1.0",
"mendix": "^10.7.26214",
"mendix": "^10.12.38909",
"metro-react-native-babel-preset": "^0.74.1",
"mime": "^3.0.0",
"node-fetch": "^2.6.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { expressionInput, expressionInputNative } from "./inputs/expression";
import { expressionWebOutput, expressionNativeOutput } from "./outputs/expression";
import { selectionInput, selectionInputNative } from "./inputs/selection";
import { selectionNativeOutput, selectionWebOutput } from "./outputs/selection";
import { listAttributeNativeInput, listAttributeWebInput } from "./inputs/list-attribute-refset";
import { listAttributeNativeOutput, listAttributeWebOutput } from "./outputs/list-attribute-refset";

describe("Generating tests", () => {
it("Generates a parsed typing from XML for native", () => {
Expand Down Expand Up @@ -170,6 +172,16 @@ describe("Generating tests", () => {
const newContent = generateNativeTypesFor(selectionInputNative);
expect(newContent).toBe(selectionNativeOutput);
});

it("Generates a parsed typing from XML for web using ref sets in linked attribute", () => {
const newContent = generateFullTypesFor(listAttributeWebInput);
expect(newContent).toBe(listAttributeWebOutput);
});

it("Generates a parsed typing from XML for native using ref sets in linked attribute", () => {
const newContent = generateNativeTypesFor(listAttributeNativeInput);
expect(newContent).toBe(listAttributeNativeOutput);
});
});

function generateFullTypesFor(xml: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
export const listAttributeWebInput = `<?xml version="1.0" encoding="utf-8"?>
<widget id="mendix.mywidget.MyWidget" needsEntityContext="true" offlineCapable="true" pluginWidget="true"
xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../xsd/widget.xsd">
<properties>
<propertyGroup caption="General">
<property key="dataSource" type="datasource" isList="true" required="false">
<caption>Data source</caption>
<description />
</property>
<property key="referenceDefault" type="attribute" dataSource="dataSource">
<caption>Reference</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
</property>
<property key="reference" type="attribute" dataSource="dataSource">
<caption>Reference</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
<associationTypes>
<associationType name="Reference"/>
</associationTypes>
</property>
<property key="referenceSet" type="attribute" dataSource="dataSource">
<caption>Reference Set</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
<associationTypes>
<associationType name="ReferenceSet"/>
</associationTypes>
</property>
<property key="referenceOrSet" type="attribute" dataSource="dataSource">
<caption>Reference or Set</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
<associationTypes>
<associationType name="Reference"/>
<associationType name="ReferenceSet"/>
</associationTypes>
</property>
</propertyGroup>
</properties>
</widget>`;

export const listAttributeNativeInput = `<?xml version="1.0" encoding="utf-8"?>
<widget id="mendix.mywidget.MyWidget" needsEntityContext="true" offlineCapable="true" pluginWidget="true" supportedPlatform="Native"
xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../xsd/widget.xsd">
<properties>
<propertyGroup caption="General">
<property key="dataSource" type="datasource" isList="true" required="false">
<caption>Data source</caption>
<description />
</property>
<property key="referenceDefault" type="attribute" dataSource="dataSource">
<caption>Reference</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
</property>
<property key="reference" type="attribute" dataSource="dataSource">
<caption>Reference</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
<associationTypes>
<associationType name="Reference"/>
</associationTypes>
</property>
<property key="referenceSet" type="attribute" dataSource="dataSource">
<caption>Reference Set</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
<associationTypes>
<associationType name="ReferenceSet"/>
</associationTypes>
</property>
<property key="referenceOrSet" type="attribute" dataSource="dataSource">
<caption>Reference or Set</caption>
<description/>
<attributeTypes>
<attributeType name="String" />
</attributeTypes>
<associationTypes>
<associationType name="Reference"/>
<associationType name="ReferenceSet"/>
</associationTypes>
</property>
</propertyGroup>
</properties>
</widget>`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export const listAttributeWebOutput = `/**
* This file was generated from MyWidget.xml
* WARNING: All changes made to this file will be overwritten
* @author Mendix Widgets Framework Team
*/
import { CSSProperties } from "react";
import { ListValue, ListAttributeValue, ListAttributeListValue } from "mendix";
export interface MyWidgetContainerProps {
name: string;
class: string;
style?: CSSProperties;
tabIndex?: number;
dataSource?: ListValue;
referenceDefault?: ListAttributeValue<string>;
reference?: ListAttributeValue<string>;
referenceSet?: ListAttributeListValue<string>;
referenceOrSet?: ListAttributeValue<string> | ListAttributeListValue<string>;
}
export interface MyWidgetPreviewProps {
/**
* @deprecated Deprecated since version 9.18.0. Please use class property instead.
*/
className: string;
class: string;
style: string;
styleObject?: CSSProperties;
readOnly: boolean;
dataSource: {} | { caption: string } | { type: string } | null;
referenceDefault: string;
reference: string;
referenceSet: string;
referenceOrSet: string;
}
`;

export const listAttributeNativeOutput = `export interface MyWidgetProps<Style> {
name: string;
style: Style[];
dataSource?: ListValue;
referenceDefault?: ListAttributeValue<string>;
reference?: ListAttributeValue<string>;
referenceSet?: ListAttributeListValue<string>;
referenceOrSet?: ListAttributeValue<string> | ListAttributeListValue<string>;
}`;
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ const mxExports = [
"ActionValue",
"DynamicValue",
"EditableValue",
"EditableListValue",
"FileValue",
"ListValue",
"NativeIcon",
"NativeImage",
"ListActionValue",
"ListAttributeValue",
"ListAttributeListValue",
"ListExpressionValue",
"ListReferenceValue",
"ListReferenceSetValue",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,16 @@ function toClientPropType(
.flatMap(ats => ats.attributeType)
.map(at => toAttributeClientType(at.$.name));
const unionType = toUniqueUnionType(types);
return prop.$.dataSource ? `ListAttributeValue<${unionType}>` : `EditableValue<${unionType}>`;

if (!prop.associationTypes?.length) {
return prop.$.dataSource ? `ListAttributeValue<${unionType}>` : `EditableValue<${unionType}>`;
}
else {
const reftypes = prop.associationTypes
.flatMap(ats => ats.associationType)
.map(at => toAttributeOutputType(at.$.name, !!prop.$.dataSource, unionType));
return toUniqueUnionType(reftypes);
}
}
case "association": {
if (!prop.associationTypes?.length) {
Expand Down Expand Up @@ -278,6 +287,17 @@ export function toAssociationOutputType(xmlType: string, linkedToDataSource: boo
}
}

export function toAttributeOutputType(xmlType: string, linkedToDataSource: boolean, unionAttributeType: string) {
switch (xmlType) {
case "Reference":
return linkedToDataSource ? `ListAttributeValue<${unionAttributeType}>` : `EditableValue<${unionAttributeType}>`;
case "ReferenceSet":
return linkedToDataSource ? `ListAttributeListValue<${unionAttributeType}>` : `EditableListValue<${unionAttributeType}>`;
default:
return "any";
}
}

function toSelectionClientType(xmlType: string) {
switch (xmlType) {
case "Single":
Expand Down

0 comments on commit 5a3585b

Please sign in to comment.