Skip to content

Commit f65f573

Browse files
committed
feat: add openapi contract import for consumed rest services (closes mendixlabs#207 )
1 parent 19f6b23 commit f65f573

46 files changed

Lines changed: 15582 additions & 13271 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/mendix/rest-client.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,49 @@ CREATE OR MODIFY REST CLIENT Module.ClientName ... -- idempotent
131131

132132
---
133133

134+
## Importing from OpenAPI
135+
136+
When an OpenAPI 3.0 JSON spec is available, use `IMPORT REST CLIENT` instead of writing
137+
`CREATE REST CLIENT` by hand. The spec is parsed automatically and stored in the service
138+
document — exactly as Studio Pro does.
139+
140+
```sql
141+
-- Import from an OpenAPI 3.0 JSON spec file
142+
IMPORT REST CLIENT Module.YourAPI FROM OPENAPI '/path/to/openapi.json';
143+
144+
-- Idempotent: replace an existing service with the same name
145+
IMPORT OR REPLACE REST CLIENT Module.YourAPI FROM OPENAPI '/path/to/openapi.json';
146+
147+
-- Override BaseUrl (use when spec has no servers array)
148+
IMPORT REST CLIENT Module.YourAPI FROM OPENAPI '/path/to/openapi.json'
149+
SET BaseUrl: 'https://api.example.com';
150+
151+
-- Override BaseUrl and Authentication together
152+
IMPORT OR REPLACE REST CLIENT Module.YourAPI FROM OPENAPI '/path/to/openapi.json'
153+
SET BaseUrl: 'https://api.example.com',
154+
Authentication: BASIC (Username: '$Module.ApiUser', Password: '$Module.ApiPass');
155+
156+
-- Preview what will be generated (no project connection needed)
157+
DESCRIBE OPENAPI FILE '/path/to/openapi.json';
158+
```
159+
160+
**What gets set from the spec:**
161+
- `BaseUrl``servers[0].url` (trailing slash stripped)
162+
- One operation per `paths[path][method]` entry
163+
- `Name``operationId` (sanitized to valid identifier; fallback: `METHOD_path_slug`)
164+
- `Path` ← OpenAPI path (same `{param}` placeholder format as Mendix)
165+
- `Parameters``in: path` parameters (type mapped to Mendix types)
166+
- `QueryParameters``in: query` parameters
167+
- `BodyType: JSON` ← when `requestBody` is present
168+
- `ResponseType: JSON` ← when a 200/201 response exists; otherwise `NONE`
169+
- `Timeout: 300` ← Mendix default
170+
- `Tags` ← OpenAPI tags (stored on operation; informational)
171+
- `OpenApiFile.Content` ← raw spec JSON (stored as-is, same as Studio Pro)
172+
173+
**Requirements:** Mendix 10.1+.
174+
175+
---
176+
134177
## Approach 2: REST CALL (Inline HTTP)
135178

136179
Call an HTTP endpoint directly from a microflow — no REST client document needed. Best for one-off calls, dynamic URLs, or low-level control.

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@ All notable changes to mxcli will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [Unreleased]
8+
9+
### Added
10+
11+
- **IMPORT REST CLIENT FROM OPENAPI** — Create a consumed REST service from an OpenAPI 3.0 JSON spec: `IMPORT REST CLIENT Module.Name FROM OPENAPI '/path/spec.json'`
12+
- **IMPORT OR REPLACE REST CLIENT** — Idempotent variant that replaces an existing service with the same name
13+
- **DESCRIBE OPENAPI FILE** — Preview an OpenAPI spec as MDL without a project connection: `DESCRIBE OPENAPI FILE '/path/spec.json'`
14+
- **IMPORT REST CLIENT … SET** — Optional `SET BaseUrl: '...'` and `SET Authentication: BASIC (...)` overrides for specs without servers or securitySchemes
15+
16+
### Fixed
17+
18+
- **DELETE/HEAD body stripping** — Specs with a `requestBody` on DELETE or HEAD operations (e.g. `deleteTask`) now correctly produce `Rest$RestOperationMethodWithoutBody`, matching Studio Pro's behavior
19+
720
## [0.6.0] - 2026-04-09
821

922
### Added

cmd/mxcli/docker/detect.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
// CDN downloads are the primary source for mxbuild and runtime.
1414
//
1515
// Resolution priority (all platforms):
16-
// 1. Explicit path (--mxbuild-path)
17-
// 2. PATH lookup
18-
// 3. OS-specific known locations (Studio Pro on Windows)
19-
// 4. Cached CDN downloads (~/.mxcli/mxbuild/)
16+
// 1. Explicit path (--mxbuild-path)
17+
// 2. PATH lookup
18+
// 3. OS-specific known locations (Studio Pro on Windows)
19+
// 4. Cached CDN downloads (~/.mxcli/mxbuild/)
2020
//
2121
// Path discovery on Windows must NOT hardcode drive letters. Use environment
2222
// variables (PROGRAMFILES, PROGRAMW6432, SystemDrive) to locate install dirs.

cmd/mxcli/help_topics/rest.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@ CREATE REST CLIENT
5050
CREATE OR MODIFY REST CLIENT Module.Api ( ... ) { ... }; -- Update existing
5151
DROP REST CLIENT Module.Api;
5252

53+
IMPORT REST CLIENT FROM OPENAPI
54+
--------------------------------
55+
56+
-- Import a consumed REST service from an OpenAPI 3.0 JSON spec:
57+
IMPORT REST CLIENT Module.YourAPI FROM OPENAPI '/specs/openapi.json';
58+
59+
-- Idempotent: replace an existing service with the same name:
60+
IMPORT OR REPLACE REST CLIENT Module.YourAPI FROM OPENAPI '/specs/openapi.json';
61+
62+
-- Preview what will be created (no project needed):
63+
DESCRIBE OPENAPI FILE '/specs/openapi.json';
64+
65+
The raw spec is stored in the service document (Rest$OpenApiFile.Content),
66+
matching Studio Pro's import behavior. Requires Mendix 10.1+.
67+
5368
Authentication: NONE | BASIC (Username: '...', Password: '...')
5469
Body: JSON FROM $var | TEMPLATE '...' | MAPPING Entity { jsonField = Attr, ... }
5570
Response: JSON AS $var | STRING AS $var | FILE AS $var | STATUS AS $var | NONE

cmd/mxcli/lsp_completions_gen.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs-site/src/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@
250250
- [Workflow Statements](reference/workflow/README.md)
251251
- [CREATE WORKFLOW](reference/workflow/create-workflow.md)
252252
- [DROP WORKFLOW](reference/workflow/drop-workflow.md)
253+
- [REST Client Statements](reference/rest-client/README.md)
254+
- [IMPORT REST CLIENT FROM OPENAPI](reference/rest-client/import-rest-client.md)
253255
- [OData and Integration Statements](reference/odata/README.md)
254256
- [Business Event Statements](reference/business-event/README.md)
255257
- [CREATE BUSINESS EVENT SERVICE](reference/business-event/create-business-event-service.md)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# REST Client Statements
2+
3+
Statements for creating and managing consumed REST services (REST clients).
4+
5+
A REST client document defines a third-party HTTP API — its base URL, authentication, and operations — once. Microflows then call its operations using `SEND REST REQUEST` without repeating connection details.
6+
7+
## Import from OpenAPI
8+
9+
| Statement | Description |
10+
|-----------|-------------|
11+
| [IMPORT REST CLIENT FROM OPENAPI](import-rest-client.md) | Create a consumed REST service from an OpenAPI 3.0 JSON spec |
12+
| [DESCRIBE OPENAPI FILE](import-rest-client.md#describe-openapi-file) | Preview what an OpenAPI spec would generate — no project needed |
13+
14+
## Create / Modify / Drop
15+
16+
| Statement | Description |
17+
|-----------|-------------|
18+
| `CREATE REST CLIENT Module.Name ( ... ) { ... }` | Create a REST client manually |
19+
| `CREATE OR MODIFY REST CLIENT Module.Name ( ... ) { ... }` | Idempotent create/update |
20+
| `DROP REST CLIENT Module.Name` | Remove a REST client |
21+
22+
## Show / Describe
23+
24+
| Statement | Description |
25+
|-----------|-------------|
26+
| `SHOW REST CLIENTS [IN Module]` | List all consumed REST services |
27+
| `DESCRIBE REST CLIENT Module.Name` | Show full MDL definition (re-executable) |
28+
29+
## Catalog Tables
30+
31+
After `REFRESH CATALOG`, the following tables are available:
32+
33+
| Table | Contents |
34+
|-------|----------|
35+
| `CATALOG.REST_CLIENTS` | Consumed REST services |
36+
| `CATALOG.REST_OPERATIONS` | Operations per service (method, path, parameters) |
37+
38+
## Requirements
39+
40+
REST client documents require **Mendix 10.1+**.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# IMPORT REST CLIENT FROM OPENAPI
2+
3+
Import a consumed REST service from an OpenAPI 3.0 JSON specification in one step. The spec is parsed automatically and stored in the service document — exactly as Mendix Studio Pro does when you use its built-in OpenAPI import.
4+
5+
**Requires Mendix 10.1+.**
6+
7+
## Syntax
8+
9+
```sql
10+
IMPORT REST CLIENT Module.Name FROM OPENAPI '/path/to/openapi.json';
11+
12+
-- Idempotent: replace an existing service with the same name
13+
IMPORT OR REPLACE REST CLIENT Module.Name FROM OPENAPI '/path/to/openapi.json';
14+
15+
-- Override base URL (use when spec has no servers array)
16+
IMPORT REST CLIENT Module.Name FROM OPENAPI '/path/to/openapi.json'
17+
SET BaseUrl: 'https://api.example.com';
18+
19+
-- Override base URL and authentication
20+
IMPORT OR REPLACE REST CLIENT Module.Name FROM OPENAPI '/path/to/openapi.json'
21+
SET BaseUrl: 'https://api.example.com',
22+
Authentication: BASIC (Username: '$Module.ApiUser', Password: '$Module.ApiPass');
23+
```
24+
25+
## Parameters
26+
27+
| Parameter | Description |
28+
|-----------|-------------|
29+
| `Module.Name` | Qualified name for the new REST client. Module must already exist. |
30+
| `'/path/to/openapi.json'` | Absolute or relative path to the OpenAPI 3.0 JSON spec file. |
31+
| `OR REPLACE` | If a REST client with the same name already exists, replace it. Without this clause the command fails if the service already exists. |
32+
| `SET BaseUrl` | Override the base URL from the spec's `servers[0].url`. Required when the spec has no `servers` array. |
33+
| `SET Authentication` | Override the authentication. Supported values: `NONE`, `BASIC (Username: '...', Password: '...')`. |
34+
35+
## What Gets Imported
36+
37+
| OpenAPI Field | REST Client Field |
38+
|---------------|-------------------|
39+
| `servers[0].url` | `BaseUrl` (trailing slash stripped) |
40+
| `paths[path][method].operationId` | Operation name (sanitized to valid identifier) |
41+
| `paths[path]` | `Path` (same `{param}` placeholder format as Mendix) |
42+
| `paths[path][method]` | `Method` (uppercased: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`) |
43+
| `parameters[*].in = "path"` | `Parameters` |
44+
| `parameters[*].in = "query"` | `Query` |
45+
| `requestBody` (non-DELETE/HEAD) | `Body: JSON` |
46+
| `responses["200"/"201"/"2XX"]` | `Response: JSON` |
47+
| `responses["204"]` / no 2xx | `Response: NONE` |
48+
| Raw spec bytes | `OpenApiFile.Content` (stored as-is, enables "View OpenAPI" in Studio Pro) |
49+
50+
**Note:** duplicate parameter names within a single operation (a spec authoring error) are preserved as-is, matching Studio Pro behaviour. Studio Pro will surface these as warnings when you open the project.
51+
52+
### Type Mapping
53+
54+
| OpenAPI Type | Format | Mendix Type |
55+
|--------------|--------|-------------|
56+
| `string` || `String` |
57+
| `integer` | `int32` (or none) | `Integer` |
58+
| `integer` | `int64` | `Long` |
59+
| `number` || `Decimal` |
60+
| `boolean` || `Boolean` |
61+
62+
## Examples
63+
64+
### Basic import
65+
66+
```sql
67+
-- Create the module first
68+
CREATE MODULE PetStoreIntegration;
69+
70+
-- Import all endpoints from the spec
71+
IMPORT REST CLIENT PetStoreIntegration.PetStoreAPI FROM OPENAPI '/specs/petstore.json';
72+
```
73+
74+
### Spec without servers array
75+
76+
```sql
77+
IMPORT REST CLIENT MyModule.YourAPI FROM OPENAPI '/specs/openapi.json'
78+
SET BaseUrl: 'https://api.example.com/v1';
79+
```
80+
81+
### Idempotent re-import after spec update
82+
83+
```sql
84+
IMPORT OR REPLACE REST CLIENT MyModule.YourAPI FROM OPENAPI '/specs/openapi.json';
85+
```
86+
87+
## DESCRIBE OPENAPI FILE
88+
89+
Preview what `IMPORT REST CLIENT` would generate without modifying the project. No project connection is needed.
90+
91+
```sql
92+
DESCRIBE OPENAPI FILE '/path/to/openapi.json';
93+
```
94+
95+
Output is a complete `CREATE REST CLIENT` statement — re-executable MDL showing all operations that would be created.
96+
97+
## Studio Pro Compatibility
98+
99+
The raw spec is stored in the service document's `OpenApiFile.Content` field. When you open the project in Studio Pro, the REST client shows a **View OpenAPI** button and validates operations against the spec, exactly as if you had used Studio Pro's built-in import.
100+
101+
## Related
102+
103+
- [REST Client Statements](README.md) — overview of all REST client commands
104+
- [SEND REST REQUEST](../../language/microflow/send-rest-request.md) — call an operation from a microflow
105+
- `SHOW REST CLIENTS` / `DESCRIBE REST CLIENT Module.Name` — list and inspect imported services

docs/01-project/MDL_QUICK_REFERENCE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ CREATE OR REPLACE NAVIGATION Responsive
448448
| Create client | See syntax below | Property-based `{}` syntax |
449449
| Create or modify | `CREATE OR MODIFY REST CLIENT ...` | Replaces existing |
450450
| Drop client | `DROP REST CLIENT Module.Name;` | |
451+
| Import from OpenAPI | `IMPORT REST CLIENT Module.Name FROM OPENAPI '/path/spec.json';` | Creates service from OpenAPI 3.0 JSON spec; requires 10.1+ |
452+
| Import or replace | `IMPORT OR REPLACE REST CLIENT Module.Name FROM OPENAPI '/path/spec.json';` | Idempotent — replaces existing service |
453+
| Preview OpenAPI spec | `DESCRIBE OPENAPI FILE '/path/spec.json';` | No project needed; outputs CREATE preview |
451454

452455
```sql
453456
CREATE REST CLIENT Module.Api (

0 commit comments

Comments
 (0)