Giter Club home page Giter Club logo

wsdl-tsclient's Introduction

WSDL TSClient

travis-status license Known Vulnerabilities npm-version

Example how to generate and use wsdl-tsclient: wsdl-tsclient-example

Generate a soap client with typescript definitions from a WSDL file.

This library uses ts-morph to generate typescript code and soap for runtime. Inspired by Java wsimport and openapi-generator.

NOTE: Add soap to your npm runtime dependencies (npm i soap).

Install

npm i wsdl-tsclient

or install it with -g to have CLI globally available.

npm i -g wsdl-tsclient

Usage

You can check example repository wsdl-tsclient-example

Generate client using CLI

Easiest way to generate client from is to use CLI. You need to provide only path to .wsdl file and path to output directory (-o param). If you want to generate only typescript types (no runtime code) for node-soap, you can pass --emitDefinitionsOnly param.

wsdl-tsclient ./soap.wsdl -o ./generated

wsdl-tsclient ./resources/**/*.wsdl -o ./generated - using glob

you can also use npx

npx wsdl-tsclient ./soap.wsdl -o ./generated

wsdl-tsclient [options] [path]

Options:
      --help                        Show help                          [boolean]
  -v, --version                                                        [boolean]
  -o                                Output directory         [string] [required]
      --emitDefinitionsOnly         Generate only Definitions          [boolean]
      --modelNamePreffix            Prefix for generated interface names[string]
      --modelNameSuffix             Suffix for generated interface names[string]
      --caseInsensitiveNames        Case-insensitive name while parsing
                                    definition names                   [boolean]
      --maxRecursiveDefinitionName  Maximum count of definition's with same name
                                    but increased suffix. Will throw an error if
                                    exceed                              [number]
      --quiet                       Suppress all logs                  [boolean]
      --verbose                     Print verbose logs                 [boolean]
      --no-color                    Logs without colors                [boolean]

Examples:
    wsdl-tsclient file.wsdl -o ./generated/
    wsdl-tsclient ./res/**/*.wsdl -o ./generated/

Generate client programmatically

import { generateClient } from "wsdl-tsclient";

parseAndGenerate("./path/to/MyWsdl.wsdl", "./generated/");

Using generated client in your project

Note: Make sure you have soap package in your runtime dependencies (npm i soap)

import { createClientAsync } from "./generated/MyWsdl";

const client = await createClientAsync("./path/to/wsdl.wsdl");
client.CallSoapMethodAsync();

Setting basic auth

import soap from "soap";
import { createClientAsync } from "./generated/MyWsdl";

const client = await createClientAsync("./path/to/wsdl.wsdl");

const basicAuth = new soap.BasicAuthSecurity(auth.username, auth.password);
client.setSecurity(basicAuth);

client.CallSoapMethodAsync();

for more information about the use of the client, read more about soap

How it works

overview

License

The source code is licensed under the MIT license

Contributors

Contributors

wsdl-tsclient's People

Contributors

aesweeting avatar dderevjanik avatar eden-leverate avatar edenk avatar icholy avatar jakethagle avatar mike-marcacci avatar mtranter avatar simenandre avatar taylorreece avatar vekexasia avatar xseman avatar zimgil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

wsdl-tsclient's Issues

Filename globbing is not working

My wsdl -> typescript script in package.json is this:

"generate": "npx wsdl-tsclient ./wsdl/**/*.wsdl -o ./generated"

Adapted from the example in the readme. But I get the message:

Generating soap client from "*.wsdl"
Error occured while generating client "*.wsdl"
        Error: ENOENT: no such file or directory, open 'C:\Users\taagyha1\edu\sap-client-tests\wsdl\**\*.wsdl'
1 Errors occured!

Specifying a single WSDL file without globbing works.
I'm using Node version 16.16.0 on Windows 10.

Wrong import path

Hello,

It seems the generator produces the import path according to the operating system.
Node is supposed to abstract this point so import should be always like ../../../file (using slash separator).

Mac (compile):
import { MyRequest } from "../definitions/MyRequest";

Windows (doesn't compile):
import { MyRequest } from "..\definitions\MyRequest";

What do you think ?

Thank you
Stephane

NestJS Injection of generated client

right now it is not possible to import the generated MyClient in NestJS directly.

To be able to do this we would need to export a Symbol with the same name like:

export const MyClient = Symbol('MyClient')

export interface MyClient extends SoapClient {}

Some type declarations are missing

I generate a SOAP client from WSDL files. Archive with wsdl files here

Run it as:
npx wsdl-tsclient ./resources/elhub_wsdl/v2/wsdl/PollMeteringValues.wsdl -o ./generated/ --verbose

A SOAP client is generated successfully but not all the type definitions are generated.

For example, there is a PollForData interface where all properties are strings, but I expect to have real types instead (they are declared in comments above the property).

/**
 * PollForData
 * @targetNSAlias `rsm`
 * @targetNamespace `urn:no:elhub:emif:PollForData:v2`
 */
export interface PollForData {
  /** Elhub_HeaderType */
  Header?: string;
  /** Elhub_EnergyContextType */
  ProcessEnergyContext?: string;
  /** Elhub_PollForData */
  Payload?: string;
}

There is a chain of includes/imports in WSDL to bring these types in.

  • PollMeteringValues.wsdl include xsd/PollMeteringValues.xsd
  • xsd/PollMeteringValues.xsd import ../../bim/PollForData.xsd
  • ../../bim/PollForData.xsd import common/Elhub_AggregatedBusinessInformationEntities.xsd

The last file has a declarations for Elhub_HeaderType, Elhub_EnergyContextType, Elhub_PollForData.

My colleague was able to generate .NET client based on these WSDL files, so they should be fine. Most likely something wrong with wsdl-tsclient or my configuration for it.

Does anyone have an idea how to solve it?

`wsdl_headers` not being passed to request

I've been trying to use a client generated by this library, but unfortunately I'm experiencing an issue where the wsdl_headers aren't being passed into the generated XML request body.

For example, with the node-soap library, I would do this:

soapClient.addSoapHeader({ AccessToken: { TokenValue: "some-access-token" } }, "", "tok");

The definition for this is:

addSoapHeader(soapHeader: any, name?: string, namespace?: any, xmlns?: string): number
add soapHeader to soap:Header node

In my example, this would produce a request that looks similar to this:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
   <soap:Header>
      <typ:AccessToken>
         <typ:TokenValue>some-access-token</typ:TokenValue>
      </typ:AccessToken>
   </soap:Header>
   <soap:Body>
      <!--- SOAP BODY REMOVED FOR THIS EXAMPLE -->
   </soap:Body>
</soap:Envelope>

I've tried a few different approaches, but I'm not able to get the same functionality with this library. For example, none of the following correctly output a <header> element in the request (which results in the target API rejecting the request with a 401 unauthorized response):

wsdl_headers: { AccessToken: "some-access-token"  }
wsdl_headers: { AccessToken: { TokenValue: "some-access-token" } }
wsdl_headers: { tok: { AccessToken: { TokenValue: "some-access-token" } } }

Could you advise if I should use a different approach or if this is a bug.

Thanks

[Question] How to handle "complex" types extending primitives?

We have a supplier's WSDL containing something like this:

  <xs:complexType name="StrasseType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="kurz" type="xs:string"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

Here, node-soap will either return a string (in case there's no kurz attribute) or something like:

{
  $value: "the string value",
  attributes: {
    kurz: "the value of the kurz attribute"
  }
}

Currently it seems to me that wsdl-tsclient emits this as a simple string, for example:

  <xs:complexType name="HausanschriftType">
    <xs:sequence>
      <xs:element form="qualified" minOccurs="0" name="Strasse" type="tns:StrasseType"/>
      <!-- ... more stuff ... -->
    </xs:sequence>
  </xs:complexType>

generates:

export interface Hausanschrift {
    /** xs:string */
    Strasse?: string;
    // ... more stuff ...
}

What am I doing wrong? Any idea?

Attributes not generated

Problem:

I have a WSDL file with attributes inside complexTypes, but they're not included in the generated typescript. For example:

<s:element name="RequestData">
	<s:complexType>
		<s:attribute name="name" type="s:string"/>
	</s:complexType>
</s:element>

What did you expect to see?

/** RequestData */
export interface RequestData {
	attributes?: {
		name?: string;
	},
}

What did you see instead?

/** RequestData */
export interface RequestData {
}

Minimal Complete WSDL:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://example.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://example.com/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://example.com/">
      <s:element name="RequestData">
        <s:complexType>
          <s:attribute name="name" type="s:string"/>
        </s:complexType>
      </s:element>
      <s:element name="ResponseData">
      </s:element>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="RequestMessage">
    <wsdl:part name="parameters" element="tns:RequestData"/>
  </wsdl:message>
  <wsdl:message name="ResponseMessage">
    <wsdl:part name="parameters" element="tns:ResponseData"/>
  </wsdl:message>
  <wsdl:portType name="MyServiceSoap">
    <wsdl:operation name="Submit">
      <wsdl:input message="tns:RequestMessage"/>
      <wsdl:output message="tns:ResponseMessage"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="MyServiceSoap" type="tns:MyServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
  </wsdl:binding>
  <wsdl:service name="MyService">
    <wsdl:port name="MyServiceSoap" binding="tns:MyServiceSoap">
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Cut a new release

Typescript declarations were added #3, which I really want for my implementation.

So I was hoping you could cut a release?

I hate the pesky declare module ... things ๐Ÿ˜…

`Delete` is a reserved word in Javascript

If a SOAP API uses Delete as method name (๐Ÿคทโ€โ™‚๏ธ), it seems it causes the build to fail (since it's a reserved word in Javascript?).

Anyway, these are the errors:

packages/24so-client/src/generated/FileInfoService/Client.ts:18:17 - error TS1138: Parameter declaration expected.

18     DeleteAsync(delete: Delete): Promise<DeleteResponse>;
                   ~~~~~~

packages/24so-client/src/generated/FileInfoService/Client.ts:18:31 - error TS1005: ';' expected.

18     DeleteAsync(delete: Delete): Promise<DeleteResponse>;
                                 ~

packages/24so-client/src/generated/FileInfoService/Client.ts:18:32 - error TS1131: Property or signature expected.

18     DeleteAsync(delete: Delete): Promise<DeleteResponse>;
                                  ~

packages/24so-client/src/generated/FileInfoService/Client.ts:18:57 - error TS1005: '(' expected.

18     DeleteAsync(delete: Delete): Promise<DeleteResponse>;
                                                           ~

packages/24so-client/src/generated/FileInfoService/ports/FileInfoServiceSoap.ts:15:12 - error TS1138: Parameter declaration expected.

15     Delete(delete: Delete, callback: (err: any, result: Delete, rawResponse: any, soapHeader: any, rawRequest: any) => void): DeleteResponse;
              ~~~~~~

packages/24so-client/src/generated/FileInfoService/ports/FileInfoServiceSoap.ts:15:124 - error TS1005: ';' expected.

15     Delete(delete: Delete, callback: (err: any, result: Delete, rawResponse: any, soapHeader: any, rawRequest: any) => void): DeleteResponse;
                                                                                                                              ~

packages/24so-client/src/generated/FileInfoService/ports/FileInfoServiceSoap.ts:15:125 - error TS1131: Property or signature expected.

15     Delete(delete: Delete, callback: (err: any, result: Delete, rawResponse: any, soapHeader: any, rawRequest: any) => void): DeleteResponse;
                                                                                                                               ~

packages/24so-client/src/generated/FileInfoService/ports/FileInfoServiceSoap12.ts:15:12 - error TS1138: Parameter declaration expected.

15     Delete(delete: Delete, callback: (err: any, result: Delete, rawResponse: any, soapHeader: any, rawRequest: any) => void): DeleteResponse;
              ~~~~~~

packages/24so-client/src/generated/FileInfoService/ports/FileInfoServiceSoap12.ts:15:124 - error TS1005: ';' expected.

15     Delete(delete: Delete, callback: (err: any, result: Delete, rawResponse: any, soapHeader: any, rawRequest: any) => void): DeleteResponse;
                                                                                                                              ~

packages/24so-client/src/generated/FileInfoService/ports/FileInfoServiceSoap12.ts:15:125 - error TS1131: Property or signature expected.

15     Delete(delete: Delete, callback: (err: any, result: Delete, rawResponse: any, soapHeader: any, rawRequest: any) => void): DeleteResponse;
                                                                                                                            

[BUG] Request Types do not get inferred

When trying to generate Types for the following API:
https://toggenburg.teamaxess.com:16350/DCI4WTP/DCI4WTPService.svc?wsdl

All the types which are generated are resolved as empty object {}. When I import the WSDL in SoapUI however, the different requests do have content with proper information attached.

Any idea why this happens?

error TS2440: Import declaration conflicts with local declaration of 'SoapClient'.

Building the client, it produces an error:

$ tsc
src/client/soap/client.ts(1,10): error TS2440: Import declaration conflicts with local declaration of 'SoapClient'.

In client.ts there is a line

export interface SoapClient extends SoapClient {

obviously a class cannot extend itself,

an easy fix will be to change the import statement to:

import { Client as SoapClientBase, createClientAsync as soapCreateClientAsync } from "soap";

and then use it like so:

export interface SoapClient extends SoapClientBase {

Is there something I might be missing here, or is it a bug ?

[Feature Request] Parsing Extension

Good day,
I have been using wsdl-tsclient with great success and love the concept.
So far it has been working great, with a few minor hick-ups.
The SOAP API I am converting offers extension types in their XSD Data.
Meaning, for instance I have an Item called OrderItem which is correctly inferred as part of a Request, however there is an extension of that item called TicketOrderItem which looks roughly like this:

	<complexType name="TicketOrderItem">
		<annotation>
			<documentation xml:lang="en">
				<h3>
					A ticket order item represents a ticket.
				</h3>
				Elements:
				<ol>
					<li>ValidFrom: The date from that on the ticket is valid</li>
					<li>Value: The Value of an ticket order item that defines the amount of a given value-unit elements.</li>
					<li>TicketItems: List of Ticket Items with detailed information to each item of this order item.</li>
				</ol>
			</documentation>
		</annotation>
		<complexContent>
			<extension base="salType:OrderItem">
				<sequence>
					<element name="ValidFrom" type="dateTime" minOccurs="0" />
					<element name="Value" type="commType:Value" minOccurs="0" />
					<element name="TicketItems" type="salType:TicketItemList" />
				</sequence>
			</extension>
		</complexContent>
	</complexType>

This type is then not recognized in TypeScript.
Is there any way to make the library infer this information?

It would be great if the Request would then show sth like

interface OrderRequest {
  OrderItem: OrderItem | TicketOrderItem
}

[BUG] Missing Attributes

As of the latest version 1.3.1 code generation now seems to be valid typescript but some attributes seem to be missing when using the generated types.

Example WSDL: https://community.workday.com/sites/default/files/file-hosting/productionapi/Human_Resources/v36.1/Human_Resources.wsdl

Assuming the client has been auto generated it should be possible to initiate a change work contact information which you can see an example below, but some attributes seem to be missing such as the Primary field which exists in the WSDL as an attribute on Type_Data but does not seem to exist in any of the types.

Change_Work_Contact_InformationAsync({
    Change_Work_Contact_Information_Data: {
        Universal_ID_Reference: {ID: ['123']},
        Person_Contact_Information_Data: {
            Person_Email_Information_Data: {
                Email_Information_Data: [{
                    Email_Data: [{
                        Email_Address: '[email protected]',
                    }],
                    Usage_Data: [{
                        Type_Data: [{
                            // Primary Field should be here
                        }]
                    }]
                }]
            }
        }
    }
});

Error: unable to get local issuer certificate

When i am trying the generate soap client from one of the wsdl. It throws me this error: Error: unable to get local issuer certificate
How to resolve this ? Any lead will be very much aappreciated.

node-soap parsed primitive types do not match

The code generator is pretty nice. Probably the only well maintained one in the typescript ecosystem.

Just noticed some type mismatch between generated typescript types and what we get as request out of the node-soap library.

I don't know why and it does not have a comprehensive coverage of primitive types in any shape or form but here are the primitive types node-soap parses:

https://github.com/vpulim/node-soap/blob/master/src/wsdl/index.ts#L439

I've fixed up the issues for my personal use with the following diff:

diff --git a/src/parser.ts b/src/parser.ts
index f830cde..e1fc04b 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -29,6 +29,20 @@ function findReferenceDefiniton(visited: Array<VisitedDefinition>, definitionPar
     return visited.find((def) => def.parts === definitionParts);
 }
 
+const NODE_SOAP_PARSED_TYPES: { [type: string]: string } = {
+    int: "number",
+    integer: "number",
+    short: "number",
+    long: "number",
+    double: "number",
+    float: "number",
+    decimal: "number",
+    bool: "boolean",
+    boolean: "boolean",
+    dateTime: "Date",
+    date: "Date",
+};
+
 /**
  * parse definition
  * @param parsedWsdl context of parsed wsdl
@@ -95,7 +109,7 @@ function parseDefinition(
                             name: stripedPropName,
                             sourceName: propName,
                             description: type,
-                            type: "string",
+                            type: NODE_SOAP_PARSED_TYPES[type] || "string",
                             isArray: true,
                         });
                     } else if (type instanceof ComplexTypeElement) {
@@ -155,7 +169,7 @@ function parseDefinition(
                             name: propName,
                             sourceName: propName,
                             description: type,
-                            type: "string",
+                            type: NODE_SOAP_PARSED_TYPES[type] || "string",
                             isArray: false,
                         });
                     } else if (type instanceof ComplexTypeElement) {

Thought I'd let you know

Support `overwrite`

It might be useful for some users (like myself) to override generated files, as such wsdl-tsclient can be used to generate files automatically even if they exist (e.g. in CI/CD workflow).

ts-morph supports this behavior natively. You have to pass overwrite: true in order to activate it.

AFAIK, the option needs to be added to the API/CLI, and passed to this:

const portFile = project.createSourceFile(portFilePath);

e.g.:

const portFile = project.createSourceFile(portFilePath, "", { overwrite: true }); 

Would you be interested in a pull request on this?

Related errors

  • Did you mean to provide the overwrite option? A source file already exists at the provided file path

Workaround

Before running wsdl-tsclient, delete your folder containing the files wsdl-tsclient has generated (e.g. generated).

Running into an issue with OpenBraceToken child on valid wsdl

Thank you for putting this project together! Really helpful :)

I'm trying to generate a ts-client for a valid wsdl and running into an error A child of the kind OpenBraceToken was expected

I've attached the wsdl file here, curious if I am missing something or what the bug might be. I'm pretty sure ts-morph is throwing the error but unsure if the error is how it is being called or something else.

Human_Resources.wsdl.zip

Need help to get started

I don't know if this is an issue or that I do know enough about wsdl. I'm trying to convert the onvif library , but I only get empty definitions.

First I can not get the glob to work with **/*.wsdl ( this may be a known issue #44 )
And If I target one file the definition emitted is empty. Is there something wrong with the wsdl files from onvif?

npx wsdl-tsclient --verbose .\wsdl\ver10\device\wsdl\devicemgmt.wsdl -o ./generated/

Generated Index Errors

When generating a new client and opening the index file

The errors I am seeing are of 3 different types

  1. Variable Names

export { OffPointDetails } from "./definitions/OffPointDetails";
but in my file, I have
export interface OffpointDetails {

  1. File Names
    export { OffpointDetails1 } from "./definitions/OffpointDetails1";
    I don't have a file with this name, I do have
    OffPointDetails1.ts
    Which is also imported 2 separate times

  2. Duplicate Import Export
    I have several duplicates of the same import happening in multiple places
    for example

export { Citypair } from "./definitions/Citypair";
export { CityPair } from "./definitions/CityPair";

Yes I see the different p && P, still this should not be happening
and this little gem

export { DocumentDetails5 } from "./definitions/DocumentDetails5";
export { DocumentDetails6 } from "./definitions/DocumentDetails6";
export { DocumentDetails6 } from "./definitions/DocumentDetails6";
export { ProcessDetails } from "./definitions/ProcessDetails";

Generated types clash and fail to compile

I've got the following WSDL spec which fails to compile with

gensrc/oil/salesorderv201901/definitions/ProductLineItemUpdateOrderRequest.ts:1:33 - error TS1149: File name 'gensrc/oil/salesorderv201901/definitions/ProductLineItem.ts' differs from already included file name 'gensrc/oil/salesorderv201901/definitions/ProductLineitem.ts' only in casing.

SalesOrder_v201901.txt

MethodAsync returns wrong type

Hello,

I had a generated method initiateSsoSessionAsync, returning a promise of InitiateSsoSessionResponse :

initiateSsoSessionAsync(initiateSsoSessionRequest: InitiateSsoSessionRequest): Promise<InitiateSsoSessionResponse>;

This InitiateSsoSessionResponse type is described below :

export interface InitiateSsoSessionResponse {
    /** ssoSessionIdType|tns:mandatoryStringType|pattern */
    ssoSessionId?: string;
};

So, when I called my method below, I was waiting for the response to be a InitiateSsoSessionResponse ( containing only a ssoSessionId attribute ) :

return client.initiateSsoSessionAsync(initiateSsoSessionRequest).then((response: InitiateSsoSessionResponse) => {  
        console.log(response);
        console.log("response.ssoSessionId = " + response.ssoSessionId);
})

But trying to retrieve ssoSessionId, I've got undefined. But it's normal in someways, I have got what node soap returns normally :

https://github.com/vpulim/node-soap#clientmethodasyncargs-options---call-method-on-the-soap-service

client.MyFunctionAsync({name: 'value'}).then((result) => {
    // result is a javascript array containing result, rawResponse, soapheader, and rawRequest
    // result is a javascript object
    // rawResponse is the raw xml response string
    // soapHeader is the response soap header as a javascript object
    // rawRequest is the raw xml request string
  })

The soap endpoint works, I retrieve data that I expected, but it's really confusing as the response typescript type is not the same as the node soap returned type...

What do you think about it ?

Thanks you very much in advance !

Frederic

Update to soap ^1.0.0

Hi there! Would it be possible to push an update that pins soap to ^1.0.0? Now that soap is 1.0, this should make future versioning easier to manage

Use type names instead of attribute names for types

Currently the place where a type is used determines what name it should have instead of the actual name of the type, which i think would be more helpful.

For example, if we have a wsdl file like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:wsdlauthority="http://minameddelanden.gov.se/Authority"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  name="Authority"
                  targetNamespace="http://minameddelanden.gov.se/Authority">
    <wsdl:types>
        <xsd:schema targetNamespace="http://minameddelanden.gov.se/Authority"
                    xmlns:dispatcher="http://minameddelanden.gov.se/schema/Dispatcher">

            <xsd:import schemaLocation="schema/Dispatcher.xsd" namespace="http://minameddelanden.gov.se/schema/Dispatcher"/>

            <xsd:element name="getDispatchers">
                <xsd:complexType>
                    <xsd:sequence/>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="getDispatchersResponse">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="return" type="dispatcher:Dispatcher" minOccurs="0" maxOccurs="unbounded"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="getDispatchersFault" >
                <xsd:complexType>
                    <xsd:sequence/>
                </xsd:complexType>
            </xsd:element>
        </xsd:schema>
    </wsdl:types>

    <wsdl:message name="getDispatchersRequest">
        <wsdl:part name="parameters" element="wsdlauthority:getDispatchers"/>
    </wsdl:message>
    <wsdl:message name="getDispatchersResponse">
        <wsdl:part name="parameters" element="wsdlauthority:getDispatchersResponse"/>
    </wsdl:message>
    <wsdl:message name="getDispatchersFault">
        <wsdl:part name="fault" element="wsdlauthority:getDispatchersFault"/>
    </wsdl:message>

    <wsdl:portType name="AuthorityPort">
        <wsdl:operation name="getDispatchers">
            <wsdl:input message="wsdlauthority:getDispatchersRequest"/>
            <wsdl:output message="wsdlauthority:getDispatchersResponse"/>
            <wsdl:fault name="fault" message="wsdlauthority:getDispatchersFault"/>
        </wsdl:operation>
    </wsdl:portType>
</wsdl:definitions>

with schema/Dispatcher.xsd containing

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://minameddelanden.gov.se/schema/Dispatcher"
  elementFormDefault="qualified"
  xmlns="http://www.w3.org/2001/XMLSchema">

  <complexType name="Dispatcher">
    <sequence>
      <element name="Id" type="string" minOccurs="1" maxOccurs="1" />
      <element name="Name" type="string minOccurs="1" maxOccurs="1"/>
    </sequence>
  </complexType>

</schema>

then the type dispatcher:Dispatcher, which is used by getDispatchersResponse will be generated under the name return instead of as the name Dispatcher which would be way more accurate and informative.

Current output

/**
 * return
 * @targetNSAlias `dispatcher`
 * @targetNamespace `http://minameddelanden.gov.se/schema/Dispatcher`
 */
export interface Return {
    Id?: string;
    Name?: string;
}

 /** getDispatchersResponse */
 export interface GetDispatchersResponse {
     /** return[] */
     return?: Array<Return>;
 }

Desired output

/**
 * Dispatcher
 * @targetNSAlias `dispatcher`
 * @targetNamespace `http://minameddelanden.gov.se/schema/Dispatcher`
 */
export interface Dispatcher {
    Id?: string;
    Name?: string;
}

 /** getDispatchersResponse */
 export interface GetDispatchersResponse {
     /** return[] */
     return?: Array<Dispatcher>;
 }

Here the attribute still has the correct name return, but the interface mirrors the original name of the type.

Missing support for xs:group type?

Hi!
It looks to me like the generator does not support xs:group element type. For example, a definition like

<xs:element name="PrimaryInsured">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="EmailAddress" type="EmailAddress"/>
<xs:element minOccurs="0" name="EmploymentInformation" type="EmploymentInformation"/>
<xs:element minOccurs="0" name="MailingAddress" type="MailingAddress"/>
<xs:group ref="PersonNameAndDateOfBirth"/>
</xs:sequence>
</xs:complexType>

yields

/** PrimaryInsured */
export interface PrimaryInsured {
    /** g */
    0?: string;
    /** r */
    1?: string;
    /** o */
    2?: string;
    /** u */
    3?: string;
    /** p */
    4?: string;
    /** EmailAddress|xs:string|pattern,maxLength */
    EmailAddress?: string;
    /** InsuranceScore|xs:string|VeryPoor,Poor,Fair,Average,AboveAverage,Good,Excellent */
    InsuranceScore?: string;
    /** MailingAddress */
    MailingAddress?: MailingAddress;
    /** PreviousAddress */
    PreviousAddress?: MailingAddress;
}

Is this intentional? Are groups on the roadmap anytime soon?

Thanks

M.

Can't generate a <fieldName xsi:nil="true" /> field in request payload

If an element is set to nillable="true, we should be able to set the element as null to get the following XML result

xsi:nil="true"

For now, the code generator indicates that the nillable="true field is either <fieldType> or undefined.

Setting the field to undefined makes the field disappear in the resulting request XML payload.

One could say that this should be managed by the server side, but that's implementation specific and not always possible when calling an external SOAP API.

Anyone have any insight on this ?

Module has no exported member 'xx'

There are multiple references that are not found.

Example files

filename: GetProjectList2.ts

import { Ps1 } from "./Ps1";

export interface GetProjectList {
    /** */
    ps1?: Ps1;
}

filename: Ps1.ts

export interface Ps {
    /** s:boolean */
    myProjects?: string;
    ... (more fields here)
}

Let me know if you want a simple reproduction repo :)

Sequences are not generating array types

I don't know WSDL but there is an ArrayOfstring fields that generates string instead of string[]. Isn't it wrong?

<xs:element minOccurs="0" name="Emails" nillable="true" type="q1:ArrayOfstring"/>
...
<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <xs:complexType name="ArrayOfstring">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="ArrayOfstring" nillable="true" type="tns:ArrayOfstring"/>
</xs:schema>

And this is the generated field:

    /** q1:ArrayOfstring */
    Emails?: string;

Version: 1.3.1

Type re-exporting problem with Next.js

First of all big thanks for great library!

My problem is: current types re-exporting in index.ts file break Next.js build because framework strict isolatedModules to be enabled. This issue can be solved with rewriting exports manually after client generation, but will be better if this will be solved on library level.

Types not generated when soap message contains more than 1 part

  <wsdl:message name="CreateCustomerOrderRequest">
    <wsdl:part name="request_header" element="tns:authentication"/>
    <wsdl:part name="parameters" element="tns:CreateCustomerOrder"/>
  </wsdl:message>

does not generate any types, just the one for the request_header.

Removing the request_header line fixes generation and generates all types.

missing message for soap:header

<wsdl:message name="tcRequest">
<wsdl:part name="tcinfo" element="t:Transaction" />
</wsdl:message>
......
<wsdl:binding
.....
<wsdl:input name="request">
<soap:header message="s0:tcRequest" part="tcinfo" use="literal" />
<soap:body use="literal" />
</wsdl:input>

missing "tcRequest"

Missing definition for simple wsdl

Hi, thx for awesome tool! But I get some problem.

I try to generate soap client for simple wsdl (example from https://www.tutorialspoint.com/wsdl/wsdl_example.htm):

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="HelloService" 
    targetNamespace="http://www.examples.com/wsdl/HelloService.wsdl"
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <message name="SayHelloRequest">
        <part name="firstName" type="xsd:string" />
    </message>
    <message name="SayHelloResponse">
        <part name="greeting" type="xsd:string" />
    </message>
    <portType name="Hello_PortType">
        <operation name="sayHello">
            <input message="tns:SayHelloRequest" />
            <output message="tns:SayHelloResponse" />
        </operation>
    </portType>
    <binding name="Hello_Binding" type="tns:Hello_PortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
        <operation name="sayHello">
            <soap:operation soapAction="sayHello" />
            <input>
                <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded" />
            </input>
            <output>
                <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice" use="encoded" />
            </output>
        </operation>
    </binding>
    <service name="Hello_Service">
        <documentation>WSDL File for HelloService</documentation>
        <port binding="tns:Hello_Binding" name="Hello_Port">
            <soap:address location="http://localhost:51515/SayHello/" />
        </port>
    </service>
</definitions>

But tool is generating only one definition - SayHelloRequest, definition for SayHelloResponse is missing. The HelloClient interface looks like:

export interface HelloClient extends SoapClient {
    HelloService: HelloService;
    sayHelloAsync(sayHelloRequest: SayHelloRequest, options?: ISoapExOptions): Promise<[result: SayHelloRequest, rawResponse: any, soapHeader: any, rawRequest: any]>;
}

where result promise return SayHelloRequest instead SayHelloResponse.

May be problem in https://github.com/dderevjanik/wsdl-tsclient/blob/master/src/parser.ts#L354, where paramName variable for output is the same as for input?

I generate using next command: npx wsdl-tsclient --verbose hello.wsdl -o ./src/client/generated/

Thx

Self recursive WSDL types attempt to import themselves in the generated Typescript

Where a WSDL type is self recursive, like this...

            <s:complexType name="PersonResponse">
                <s:sequence>
                    <s:element minOccurs="1" maxOccurs="1" name="Id" type="s:int" />
                    <s:element minOccurs="1" maxOccurs="1" name="Name" type="s:string" />
                    <s:element minOccurs="0" maxOccurs="1" name="mother" type="tns:PersonResponse" />
                    <s:element minOccurs="0" maxOccurs="1" name="father" type="tns:PersonResponse" />
                </s:sequence>
            </s:complexType>

The generated Typescript attempts to import itself. Like this..

import { Person } from './Person'  <---- Compilation error here.
/**
* Person
* @targetNSAlias `tns`
* @targetNamespace `http://recursive.com/account`
*/
export interface Person {
   /** s:int */
   Id?: string;
   /** s:string */
   Name?: string;
   /** mother */
   mother?: Person;
   /** father */
   father?: Person;
}

Ordering of elements in XSD Sequence not honoured

I have the following sequence as defined in a wsdl:

<xs:complexType name="Purchase">
    <xs:sequence>
        <xs:element name="Customer" nillable="true" type="xs:string" />
        <xs:element name="Quantity" type="xs:double" />
    </xs:sequence>
</xs:complexType>

When I have the following Purchase:

{
    Quantity: '1',
    Customer: "Test",
}

I expect it to be serialised as:

<Purchase>
    <Customer>Test</Customer>
    <Quantity>1</Quantity>
</Purchase>

However it is serialised in the order I defined the keys, which doesn't match the xsd:

<Purchase>
    <Quantity>1</Quantity>
    <Customer>Test</Customer>
</Purchase>

As a result the server rejects the message claiming that it doesn't understand the Quantity element and expects Customer instead. A xs:sequence must be serialised in the defined order.

[Question] Using the client in Angular

Hi!

I am currently tying to use the generated client inside my Angular web app.

However, the issue I am facing is that I am unable to correctly load/import the generated code.

Idk if anybody can help me on this but essentially the error is

core.mjs:6494 ERROR TypeError: (0 , ogdrisservice__WEBPACK_IMPORTED_MODULE_0__.createClientAsync) is not a function
    at new AppComponent (app.component.ts:15:22)
    at NodeInjectorFactory.AppComponent_Factory [as factory] (app.component.ts:21:4)
    at getNodeInjectable (core.mjs:3574:1)
    at instantiateRootComponent (core.mjs:10193:1)
    at createRootComponent (core.mjs:12297:1)
    at ComponentFactory.create (core.mjs:21654:1)
    at ApplicationRef.bootstrap (core.mjs:26538:1)
    at core.mjs:26219:1
    at Array.forEach (<anonymous>)
    at PlatformRef._moduleDoBootstrap (core.mjs:26219:1)

I am importing the client code in the package.json like so:

"ogdrisservice": "file:generated/ogdrisservice"

and I am referencing the directory in tsconfig.json

    "lib": [
      "es2018",
      "dom"
    ],
    "paths": {
      "ogdrisservice": ["./generated/ogdrisservice"]
    }
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  },
  "include": ["./generated/ogdrisservice"]
}

This is the code which is supposed to create the client:

import { Component } from '@angular/core';
import {createClientAsync} from "ogdrisservice";


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor() {
    console.log(createClientAsync);
    createClientAsync("")
      .then(
        (client) => {
          console.log(client);
        }
      );
  }
}

Skip folder name on destination dir

Hello,
I am experimenting with the library and noticed that inside the out dir, there is one more dir created by the name of the service. Is there a way to skip generating this folder as it influences my imports?

Thanks

Invalid generated TS type on schema with param case elements/attributes

TL;DR when the schema have param case (like-this), the generated TS types will be invalid.

Unfortunately I'm not allowed to share the full WSDL schema.
But I can provide an example.

For example, with this complex type:
image

The generated TS will look like this:
image

To make the generated TS valid, we just need to wrap the object property with quote mark like:
image

This issue is happening since v1.2.0.

This doesn't hapeen in v1.1.4.

Might be related to the changes happening in #17

Thanks for the great package by the way, you guys rock ๐Ÿค˜

[Featrure Request] Disable ESLint

It would be nice if generated files would have a /* eslint-disable */ line in the top of the file.

Could be options dependent but I guess it could also be default as IMO it would be the standard expected behavior.

Stack limit too low for giving unique names to elements with same name.

This is the same issue with wsdl-to-ts. They both can't handle recursive definitions.

edit: MAX_STACK constant that defines the max iterations to find a non colliding name before giving up, is set to only 30
while in my example there were hundreds of elements with the name "result". I chose a random high number that worked for me.

I will send a PR if I think about a way to find an optimal value for it.

TypeError: Cannot use 'in' operator to search for 'undefined'

When generating a client for the Domibus.wsdl, wsdl-tsclient throws the following error: TypeError: Cannot use 'in' operator to search for 'undefined'

I reduced the wsdl to isolate the issue. You can reproduce it with the following minimal wsdl:

<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:tns="http://org.ecodex.backend/1_1/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
                  name="BackendService_1_1"
                  targetNamespace="http://org.ecodex.backend/1_1/">
    <wsdl:types>
        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://org.ecodex.backend/1_1/"
                    targetNamespace="http://org.ecodex.backend/1_1/">
            <xsd:simpleType name="max255-non-empty-string">
                <xsd:restriction base="xsd:string">
                    <xsd:minLength value="1"/>
                    <xsd:maxLength value="255"/>
                </xsd:restriction>
            </xsd:simpleType>
            <xsd:element name="getStatusResponse" nillable="true" type="tns:max255-non-empty-string"/>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="getStatusResponse">
        <wsdl:part element="tns:getStatusResponse" name="getStatusResponse">
        </wsdl:part>
    </wsdl:message>
    <wsdl:portType name="BackendInterface">
        <wsdl:operation name="getStatus">
            <wsdl:input message="tns:getStatusResponse" name="getStatus">
            </wsdl:input>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="BackendService_1_1SoapBinding" type="tns:BackendInterface">
        <soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="getStatus">
            <soap12:operation soapAction="" style="document"/>
            <wsdl:output name="getStatusResponse">
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="BackendService_1_1">
        <wsdl:port binding="tns:BackendService_1_1SoapBinding" name="BACKEND_PORT">
            <soap12:address location="http://localhost:8081/domibus/services/backend"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

produces this compilation error:

TypeError: Cannot use 'in' operator to search for 'undefined' in max255-non-empty-string|xsd:string|minLength,maxLength

I tests it using "wsdl-tsclient": "1.3.1" and node v16.13.2

Way to do pre action before sending soap request

Is there a way where we can do something before sending the soap message?
In my use case, I need to get the soap body and then use this to generate an authorization header.

const client = await createClientAsync("wsdl path");
// get soap body
// do something
client.addHttpHeader('Authorization', 'something generated based on key and soap body') // add soap header
client.CallSoapMethodAsync();

wsdl_options not available in the generated interface methods

Hi, I started using this lib to generate soap contracts for a nest js project. The generated xxxAsync methods are not accepting wsdl_options in the contracts generated but in the actual soap object they are available. We specifically need the timeout option but would be great if we can access all options. Currently Im able to achieve this by manually changing the generated method and add the second parameter type to accept options but every time we generate we ahve to do this again. could you please make this available?

we are using "wsdl-tsclient": "^1.4.0"

[BUG] Error while parsing Subdefinition

I am trying to use the workday API and when trying to autogenerate code for the Human Resources service I get the below error.

Error occured while generating client "Human_Resources.wsdl"
        Error: Error while parsing Subdefinition for wd:Get_Political_Affiliations_ResponseType.wd:Get_Political_Affiliations_ResponseType
1 Errors occured!

WSDL File: https://community.workday.com/sites/default/files/file-hosting/productionapi/Human_Resources/v36.1/Human_Resources.wsdl

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.