Skip to content

Commit 9935eba

Browse files
khode-mxclaude
andcommitted
feat: import consumed REST client from OpenAPI 3.0 spec (closes #207)
Add `OpenAPI: 'path/or/url'` property to `CREATE REST CLIENT` that auto-generates a consumed REST service document from an OpenAPI 3.0 spec (JSON or YAML). Operations, path/query parameters, request bodies, response types, resource groups (tags), and Basic auth are all derived from the spec. The spec content is stored in OpenApiFile for Studio Pro parity. Also adds `DESCRIBE CONTRACT OPERATION FROM OPENAPI` for previewing the import without writing to the project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent e765498 commit 9935eba

27 files changed

Lines changed: 9406 additions & 8429 deletions

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

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,52 @@
22

33
Use this skill when integrating with external REST APIs from Mendix.
44

5-
## Two Approaches
5+
## Three Approaches
66

7-
Mendix offers two ways to call REST APIs from microflows. Choose based on the use case:
7+
Mendix offers three ways to call REST APIs from microflows. Choose based on the use case:
88

99
| Approach | When to Use | Artifacts |
1010
|----------|-------------|-----------|
11-
| **REST Client + SEND REST REQUEST** | Structured APIs with multiple operations, reusable across microflows, Studio Pro UI support | REST client document + microflow |
11+
| **OpenAPI import** | API has an OpenAPI 3.0 spec — auto-generate from the spec | REST client document generated in one command |
12+
| **REST Client (manual)** | No spec available, or need fine-grained control | REST client document + microflow |
1213
| **REST CALL (inline)** | One-off calls, quick prototyping, dynamic URLs, low-level HTTP control | Microflow only |
1314

14-
Both can be combined with **Data Transformers** (Mendix 11.9+) and **Import/Export Mappings** to map between JSON and entities.
15+
Both REST Client approaches can be combined with **Data Transformers** (Mendix 11.9+) and **Import/Export Mappings** to map between JSON and entities.
1516

1617
---
1718

18-
## Approach 1: REST Client (Recommended)
19+
## Approach 0: OpenAPI Import (Fastest)
20+
21+
If the API has an OpenAPI 3.0 spec (JSON or YAML), generate the REST client in one command:
22+
23+
```sql
24+
-- From a local file (relative to the .mpr file)
25+
create or modify rest client CapitalModule.CapitalAPI (
26+
OpenAPI: 'specs/capital.json'
27+
);
28+
29+
-- From a URL
30+
create or modify rest client PetStoreModule.PetStoreAPI (
31+
OpenAPI: 'https://petstore3.swagger.io/api/v3/openapi.json'
32+
);
33+
```
34+
35+
This generates:
36+
- All operations with correct HTTP method, path, parameters, headers, body, and response type
37+
- Resource groups based on OpenAPI `tags`
38+
- Basic auth if the spec declares it at the top level
39+
- The spec stored inside the document for Studio Pro parity
40+
41+
**Preview without writing:**
42+
```sql
43+
describe contract operation from openapi 'specs/capital.json';
44+
```
45+
46+
**After import:** the REST client is ready to use with `SEND REST REQUEST`. No manual operation definition needed.
47+
48+
---
49+
50+
## Approach 1: REST Client (Manual)
1951

2052
Define the API once as a REST client document, then call its operations from microflows.
2153

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
1313
- **Path normalization** — Relative paths in `MetadataUrl` are automatically converted to absolute `file://` URLs for Studio Pro compatibility
1414
- **ServiceUrl validation**`ServiceUrl` parameter must now be a constant reference (e.g., `@Module.ConstantName`) to enforce Mendix best practice
1515
- **Shared URL utilities**`internal/pathutil` package with `NormalizeURL()`, `URIToPath()`, and `PathFromURL()` for reuse across components
16+
- **OpenAPI import for REST clients**`CREATE REST CLIENT` now accepts `OpenAPI: 'path/or/url'` to auto-generate a consumed REST service document from an OpenAPI 3.0 spec (JSON or YAML); operations, path/query parameters, request bodies, response types, resource groups (tags), and Basic auth are derived automatically; spec content is stored in `OpenApiFile` for Studio Pro parity (#207)
17+
- **DESCRIBE CONTRACT OPERATION FROM OPENAPI** — Preview what would be generated from an OpenAPI spec without writing to the project
18+
1619
## [0.7.0] - 2026-04-21
1720

1821
### Added

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.

cmd/mxcli/syntax/features_integration.go

Lines changed: 34 additions & 34 deletions
Large diffs are not rendered by default.

docs-site/src/examples/rest-integration.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,31 @@ CREATE IMPORT MAPPING Integration.IMM_Order
182182

183183
## Consuming a REST API
184184

185+
### From an OpenAPI Spec (Recommended)
186+
187+
If the API has an OpenAPI 3.0 spec (JSON or YAML), generate the REST client in one command:
188+
189+
```sql
190+
-- From a local file (relative to the .mpr file)
191+
CREATE OR MODIFY REST CLIENT CapitalModule.CapitalAPI (
192+
OpenAPI: 'specs/capital.json'
193+
);
194+
195+
-- From a URL
196+
CREATE OR MODIFY REST CLIENT PetStoreModule.PetStoreAPI (
197+
OpenAPI: 'https://petstore3.swagger.io/api/v3/openapi.json'
198+
);
199+
```
200+
201+
Operations, path/query parameters, request bodies, response types, resource groups (from `tags`), and Basic auth are all derived automatically from the spec.
202+
203+
**Preview without writing:**
204+
```sql
205+
DESCRIBE CONTRACT OPERATION FROM OPENAPI 'specs/capital.json';
206+
```
207+
208+
### Manual Definition
209+
185210
Define a reusable REST client with typed operations using `CREATE REST CLIENT`. Each operation declares its method, path, optional parameters, headers, body, and response mapping.
186211

187212
```sql

docs-site/src/reference/capabilities.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Everything mxcli can do, organized by use case.
8484
| Capability | Command | Status |
8585
|---|---|---|
8686
| REST clients | `CREATE REST CLIENT` | Consumed REST services |
87+
| OpenAPI import | `CREATE REST CLIENT (OpenAPI: '...')` | Generate REST client from OpenAPI 3.0 spec |
8788
| Business events | `CREATE BUSINESS EVENT SERVICE` | Event definitions |
8889
| Database connections | `CREATE DATABASE CONNECTION` | External SQL |
8990
| OData services | `LIST ODATA CLIENTS/SERVICES` | Read-only browsing |

docs/01-project/MDL_QUICK_REFERENCE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ Respond in {{Language}}.$$,
557557
| Create client | See syntax below | Property-based `{}` syntax |
558558
| Create or modify | `create or modify rest client ...` | Replaces existing |
559559
| Drop client | `drop rest client Module.Name;` | |
560+
| Import from OpenAPI | See OpenAPI import below | Auto-generate from spec |
561+
| Preview OpenAPI | `describe contract operation from openapi 'path';` | Preview without writing |
560562

561563
```sql
562564
create rest client Module.Api (
@@ -594,6 +596,27 @@ create rest client Module.Api (
594596
**Response types:** `json as $var`, `string as $var`, `file as $var`, `status as $var`, `none`, `mapping entity { attr = jsonField, ... }`
595597
**Authentication:** `none`, `basic (username: '...', password: '...')`
596598

599+
### OpenAPI Import
600+
601+
Generate a consumed REST service document directly from an OpenAPI 3.0 spec (JSON or YAML):
602+
603+
```sql
604+
-- From a local file (relative to the .mpr file)
605+
create or modify rest client CapitalModule.CapitalAPI (
606+
OpenAPI: 'specs/capital.json'
607+
);
608+
609+
-- From a URL
610+
create or modify rest client PetStoreModule.PetStoreAPI (
611+
OpenAPI: 'https://petstore3.swagger.io/api/v3/openapi.json'
612+
);
613+
614+
-- Preview without writing to the project
615+
describe contract operation from openapi 'specs/capital.json';
616+
```
617+
618+
Operations, path/query parameters, headers, request body, response type, resource groups (from OpenAPI `tags`), and Basic auth are all derived automatically. The spec is stored inside the REST client document for Studio Pro parity.
619+
597620
## Published REST Services
598621

599622
| Statement | Syntax | Notes |
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
-- SPDX-License-Identifier: Apache-2.0
2+
--
3+
-- OpenAPI import examples for CREATE REST CLIENT (OpenAPI: '...').
4+
-- These examples verify syntax and roundtrip behavior.
5+
6+
-- ============================================================================
7+
-- DESCRIBE CONTRACT OPERATION FROM OPENAPI
8+
-- Reads a spec file and outputs the MDL that would be generated.
9+
-- No project connection required.
10+
-- ============================================================================
11+
12+
describe contract operation from openapi 'https://petstore3.swagger.io/api/v3/openapi.json';
13+
14+
-- ============================================================================
15+
-- CREATE REST CLIENT with OpenAPI source
16+
-- ============================================================================
17+
18+
-- Minimal: spec drives everything (operations, BaseUrl, auth)
19+
create or modify rest client ClaudeKhodeLab.PetStoreMinimal (
20+
OpenAPI: 'https://petstore3.swagger.io/api/v3/openapi.json'
21+
);
22+
23+
-- With BaseUrl override: replaces servers[0].url from the spec
24+
create or modify rest client ClaudeKhodeLab.PetStoreV4 (
25+
OpenAPI: 'https://petstore3.swagger.io/api/v3/openapi.json',
26+
BaseUrl: 'https://petstore3.swagger.io/api/v4'
27+
);
28+
29+
-- Verify the created service is visible
30+
show rest clients in ClaudeKhodeLab;
31+
32+
-- Describe the created service (roundtrip)
33+
describe rest client ClaudeKhodeLab.PetStoreMinimal;

mdl/ast/ast_rest.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type CreateRestClientStmt struct {
1515
Documentation string
1616
Folder string // Folder path within module
1717
CreateOrModify bool // True if CREATE OR MODIFY was used
18+
OpenApiPath string // Non-empty = spec-driven; operations come from spec not OPERATION blocks
1819
}
1920

2021
func (s *CreateRestClientStmt) isStatement() {}
@@ -85,6 +86,14 @@ type DropRestClientStmt struct {
8586

8687
func (s *DropRestClientStmt) isStatement() {}
8788

89+
// DescribeContractFromOpenAPIStmt represents: DESCRIBE CONTRACT OPERATIONS FROM OPENAPI '/path/to/spec.json'
90+
// No project connection required; outputs the MDL that would be generated from the spec.
91+
type DescribeContractFromOpenAPIStmt struct {
92+
SpecPath string
93+
}
94+
95+
func (s *DescribeContractFromOpenAPIStmt) isStatement() {}
96+
8897
// ============================================================================
8998
// Published REST Service Statements
9099
// ============================================================================

mdl/executor/cmd_misc_mock_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package executor
55
import (
66
"testing"
77

8+
"github.com/mendixlabs/mxcli/mdl/ast"
89
"github.com/mendixlabs/mxcli/mdl/backend/mock"
910
"github.com/mendixlabs/mxcli/mdl/types"
1011
)
@@ -64,7 +65,7 @@ func TestShowVersion_NoSchemaHash(t *testing.T) {
6465

6566
func TestHelp_Mock(t *testing.T) {
6667
ctx, buf := newMockCtx(t)
67-
assertNoError(t, execHelp(ctx))
68+
assertNoError(t, execHelp(ctx, &ast.HelpStmt{}))
6869

6970
out := buf.String()
7071
assertContainsStr(t, out, "MDL Commands")

0 commit comments

Comments
 (0)