ngx-soap-next
Version:
SOAP service for Angular
3,531 lines • 139 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, makeEnvironmentProviders, NgModule } from '@angular/core';
import * as sax from 'sax';
import * as _ from 'lodash';
import sha1 from 'crypto-js/sha1';
import Base64 from 'crypto-js/enc-base64';
import { Buffer } from 'buffer';
import * as url from 'url';
import * as assert from 'assert';
import { ok } from 'assert';
import debugBuilder from 'debug';
import { SignedXml } from 'xml-crypto';
import { from, throwError } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import * as i1 from '@angular/common/http';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
'use strict';
class NamespaceScope {
constructor(parent) {
this.getNamespaceURI = function (prefix, localOnly) {
switch (prefix) {
case 'xml':
return 'http://www.w3.org/XML/1998/namespace';
case 'xmlns':
return 'http://www.w3.org/2000/xmlns/';
default:
var nsUri = this.namespaces.get(prefix);
/*jshint -W116 */
if (nsUri != null) {
return nsUri.uri;
}
else if (!localOnly && this.parent) {
return this.parent.getNamespaceURI(prefix);
}
else {
return null;
}
}
};
this.getNamespaceMapping = function (prefix) {
switch (prefix) {
case 'xml':
return {
uri: 'http://www.w3.org/XML/1998/namespace',
prefix: 'xml',
declared: true
};
case 'xmlns':
return {
uri: 'http://www.w3.org/2000/xmlns/',
prefix: 'xmlns',
declared: true
};
default:
var mapping = this.namespaces.get(prefix);
/*jshint -W116 */
if (mapping != null) {
return mapping;
}
else if (this.parent) {
return this.parent.getNamespaceMapping(prefix);
}
else {
return null;
}
}
};
this.getPrefix = function (nsUri, localOnly) {
switch (nsUri) {
case 'http://www.w3.org/XML/1998/namespace':
return 'xml';
case 'http://www.w3.org/2000/xmlns/':
return 'xmlns';
default:
for (const [prefix, mapping] of this.namespaces) {
if (mapping.uri === nsUri) {
return prefix;
}
}
if (!localOnly && this.parent) {
return this.parent.getPrefix(nsUri);
}
else {
return null;
}
}
};
if (!(this instanceof NamespaceScope)) {
return new NamespaceScope(parent);
}
this.parent = parent;
this.namespaces = new Map();
}
}
class NamespaceContext {
constructor() {
this.addNamespace = function (prefix, nsUri, localOnly) {
if (this.getNamespaceURI(prefix, localOnly) === nsUri) {
return false;
}
if (this.currentScope) {
this.currentScope.namespaces.set(prefix, {
uri: nsUri,
prefix: prefix,
declared: false
});
return true;
}
return false;
};
this.pushContext = function () {
var scope = new NamespaceScope(this.currentScope);
this.scopes.push(scope);
this.currentScope = scope;
return scope;
};
this.popContext = function () {
var scope = this.scopes.pop();
if (scope) {
this.currentScope = scope.parent;
}
else {
this.currentScope = null;
}
return scope;
};
this.getNamespaceURI = function (prefix, localOnly) {
return this.currentScope && this.currentScope.getNamespaceURI(prefix, localOnly);
};
this.getPrefix = function (nsUri, localOnly) {
return this.currentScope && this.currentScope.getPrefix(nsUri, localOnly);
};
this.registerNamespace = function (nsUri) {
var prefix = this.getPrefix(nsUri);
if (prefix) {
// If the namespace has already mapped to a prefix
return prefix;
}
else {
// Try to generate a unique namespace
while (true) {
prefix = 'ns' + (++this.prefixCount);
if (!this.getNamespaceURI(prefix)) {
// The prefix is not used
break;
}
}
}
this.addNamespace(prefix, nsUri, true);
return prefix;
};
this.declareNamespace = function (prefix, nsUri) {
if (this.currentScope) {
var mapping = this.currentScope.getNamespaceMapping(prefix);
if (mapping && mapping.uri === nsUri && mapping.declared) {
return false;
}
this.currentScope.namespaces.set(prefix, {
uri: nsUri,
prefix: prefix,
declared: true
});
return true;
}
return false;
};
if (!(this instanceof NamespaceContext)) {
return new NamespaceContext();
}
this.scopes = [];
this.pushContext();
this.prefixCount = 0;
}
}
const passwordDigest = function passwordDigest(nonce, created, password) {
const rawNonce = new Buffer(nonce || '', 'base64').toString('binary');
return Base64.stringify(sha1(rawNonce + created + password, ''));
};
const TNS_PREFIX$1 = '__tns__'; // Prefix for targetNamespace
/**
* Find a key from an object based on the value
* @param Namespace prefix/uri mapping
* @param nsURI value
* @returns The matching key
*/
const findPrefix$1 = function (xmlnsMapping, nsURI) {
for (const n in xmlnsMapping) {
if (n === TNS_PREFIX$1) {
continue;
}
if (xmlnsMapping[n] === nsURI) {
return n;
}
}
};
/*
* Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
* MIT Licensed
*
*/
/*jshint proto:true*/
"use strict";
const debug$1 = debugBuilder('ngx-soap:wsdl');
const stripBom = (x) => {
// Catches EFBBBF (UTF-8 BOM) because the buffer-to-string
// conversion translates it to FEFF (UTF-16 BOM)
if (x.charCodeAt(0) === 0xFEFF) {
return x.slice(1);
}
return x;
};
let TNS_PREFIX = TNS_PREFIX$1;
let findPrefix = findPrefix$1;
let Primitives = {
string: 1,
boolean: 1,
decimal: 1,
float: 1,
double: 1,
anyType: 1,
byte: 1,
int: 1,
long: 1,
short: 1,
negativeInteger: 1,
nonNegativeInteger: 1,
positiveInteger: 1,
nonPositiveInteger: 1,
unsignedByte: 1,
unsignedInt: 1,
unsignedLong: 1,
unsignedShort: 1,
duration: 0,
dateTime: 0,
time: 0,
date: 0,
gYearMonth: 0,
gYear: 0,
gMonthDay: 0,
gDay: 0,
gMonth: 0,
hexBinary: 0,
base64Binary: 0,
anyURI: 0,
QName: 0,
NOTATION: 0
};
function splitQName(nsName) {
let i = typeof nsName === 'string' ? nsName.indexOf(':') : -1;
return i < 0 ? { prefix: TNS_PREFIX, name: nsName } :
{ prefix: nsName.substring(0, i), name: nsName.substring(i + 1) };
}
function xmlEscape(obj) {
if (typeof (obj) === 'string') {
if (obj.substr(0, 9) === '<![CDATA[' && obj.substr(-3) === "]]>") {
return obj;
}
return obj
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
return obj;
}
function trim(text) {
return text.trim();
}
function deepMerge(destination, source) {
return _.mergeWith(destination || {}, source, function (a, b) {
return _.isArray(a) ? a.concat(b) : undefined;
});
}
let Element = function (nsName, attrs, options) {
let parts = splitQName(nsName);
this.nsName = nsName;
this.prefix = parts.prefix;
this.name = parts.name;
this.children = [];
this.xmlns = {};
this._initializeOptions(options);
for (let key in attrs) {
let match = /^xmlns:?(.*)$/.exec(key);
if (match) {
this.xmlns[match[1] ? match[1] : TNS_PREFIX] = attrs[key];
}
else {
if (key === 'value') {
this[this.valueKey] = attrs[key];
}
else {
this['$' + key] = attrs[key];
}
}
}
if (this.$targetNamespace !== undefined) {
// Add targetNamespace to the mapping
this.xmlns[TNS_PREFIX] = this.$targetNamespace;
}
};
Element.prototype._initializeOptions = function (options) {
if (options) {
this.valueKey = options.valueKey || '$value';
this.xmlKey = options.xmlKey || '$xml';
this.ignoredNamespaces = options.ignoredNamespaces || [];
}
else {
this.valueKey = '$value';
this.xmlKey = '$xml';
this.ignoredNamespaces = [];
}
};
Element.prototype.deleteFixedAttrs = function () {
this.children && this.children.length === 0 && delete this.children;
this.xmlns && Object.keys(this.xmlns).length === 0 && delete this.xmlns;
delete this.nsName;
delete this.prefix;
delete this.name;
};
Element.prototype.allowedChildren = [];
Element.prototype.startElement = function (stack, nsName, attrs, options) {
if (!this.allowedChildren) {
return;
}
let ChildClass = this.allowedChildren[splitQName(nsName).name], element = null;
if (ChildClass) {
stack.push(new ChildClass(nsName, attrs, options));
}
else {
this.unexpected(nsName);
}
};
Element.prototype.endElement = function (stack, nsName) {
if (this.nsName === nsName) {
if (stack.length < 2)
return;
let parent = stack[stack.length - 2];
if (this !== stack[0]) {
_.defaultsDeep(stack[0].xmlns, this.xmlns);
// delete this.xmlns;
parent.children.push(this);
parent.addChild(this);
}
stack.pop();
}
};
Element.prototype.addChild = function (child) {
return;
};
Element.prototype.unexpected = function (name) {
throw new Error('Found unexpected element (' + name + ') inside ' + this.nsName);
};
Element.prototype.description = function (definitions) {
return this.$name || this.name;
};
Element.prototype.init = function () {
};
Element.createSubClass = function () {
let root = this;
let subElement = function () {
root.apply(this, arguments);
this.init();
};
// inherits(subElement, root);
subElement.prototype.__proto__ = root.prototype;
return subElement;
};
let ElementElement = Element.createSubClass();
let AnyElement = Element.createSubClass();
let InputElement = Element.createSubClass();
let OutputElement = Element.createSubClass();
let SimpleTypeElement = Element.createSubClass();
let RestrictionElement = Element.createSubClass();
let ExtensionElement = Element.createSubClass();
let ChoiceElement = Element.createSubClass();
let EnumerationElement = Element.createSubClass();
let ComplexTypeElement = Element.createSubClass();
let ComplexContentElement = Element.createSubClass();
let SimpleContentElement = Element.createSubClass();
let SequenceElement = Element.createSubClass();
let AllElement = Element.createSubClass();
let MessageElement = Element.createSubClass();
let DocumentationElement = Element.createSubClass();
let SchemaElement = Element.createSubClass();
let TypesElement = Element.createSubClass();
let OperationElement = Element.createSubClass();
let PortTypeElement = Element.createSubClass();
let BindingElement = Element.createSubClass();
let PortElement = Element.createSubClass();
let ServiceElement = Element.createSubClass();
let DefinitionsElement = Element.createSubClass();
let ElementTypeMap = {
types: [TypesElement, 'schema documentation'],
schema: [SchemaElement, 'element complexType simpleType include import'],
element: [ElementElement, 'annotation complexType'],
any: [AnyElement, ''],
simpleType: [SimpleTypeElement, 'restriction'],
restriction: [RestrictionElement, 'enumeration all choice sequence'],
extension: [ExtensionElement, 'all sequence choice'],
choice: [ChoiceElement, 'element sequence choice any'],
// group: [GroupElement, 'element group'],
enumeration: [EnumerationElement, ''],
complexType: [ComplexTypeElement, 'annotation sequence all complexContent simpleContent choice'],
complexContent: [ComplexContentElement, 'extension'],
simpleContent: [SimpleContentElement, 'extension'],
sequence: [SequenceElement, 'element sequence choice any'],
all: [AllElement, 'element choice'],
service: [ServiceElement, 'port documentation'],
port: [PortElement, 'address documentation'],
binding: [BindingElement, '_binding SecuritySpec operation documentation'],
portType: [PortTypeElement, 'operation documentation'],
message: [MessageElement, 'part documentation'],
operation: [OperationElement, 'documentation input output fault _operation'],
input: [InputElement, 'body SecuritySpecRef documentation header'],
output: [OutputElement, 'body SecuritySpecRef documentation header'],
fault: [Element, '_fault documentation'],
definitions: [DefinitionsElement, 'types message portType binding service import documentation'],
documentation: [DocumentationElement, '']
};
function mapElementTypes(types) {
let rtn = {};
types = types.split(' ');
types.forEach(function (type) {
rtn[type.replace(/^_/, '')] = (ElementTypeMap[type] || [Element])[0];
});
return rtn;
}
for (let n in ElementTypeMap) {
let v = ElementTypeMap[n];
v[0].prototype.allowedChildren = mapElementTypes(v[1]);
}
MessageElement.prototype.init = function () {
this.element = null;
this.parts = null;
};
SchemaElement.prototype.init = function () {
this.complexTypes = {};
this.types = {};
this.elements = {};
this.includes = [];
};
TypesElement.prototype.init = function () {
this.schemas = {};
};
OperationElement.prototype.init = function () {
this.input = null;
this.output = null;
this.inputSoap = null;
this.outputSoap = null;
this.style = '';
this.soapAction = '';
};
PortTypeElement.prototype.init = function () {
this.methods = {};
};
BindingElement.prototype.init = function () {
this.transport = '';
this.style = '';
this.methods = {};
};
PortElement.prototype.init = function () {
this.location = null;
};
ServiceElement.prototype.init = function () {
this.ports = {};
};
DefinitionsElement.prototype.init = function () {
if (this.name !== 'definitions')
this.unexpected(this.nsName);
this.messages = {};
this.portTypes = {};
this.bindings = {};
this.services = {};
this.schemas = {};
};
DocumentationElement.prototype.init = function () {
};
SchemaElement.prototype.merge = function (source) {
ok(source instanceof SchemaElement);
if (this.$targetNamespace === source.$targetNamespace) {
_.merge(this.complexTypes, source.complexTypes);
_.merge(this.types, source.types);
_.merge(this.elements, source.elements);
_.merge(this.xmlns, source.xmlns);
}
return this;
};
SchemaElement.prototype.addChild = function (child) {
if (child.$name in Primitives)
return;
if (child.name === 'include' || child.name === 'import') {
let location = child.$schemaLocation || child.$location;
if (location) {
this.includes.push({
namespace: child.$namespace || child.$targetNamespace || this.$targetNamespace,
location: location
});
}
}
else if (child.name === 'complexType') {
this.complexTypes[child.$name] = child;
}
else if (child.name === 'element') {
this.elements[child.$name] = child;
}
else if (child.$name) {
this.types[child.$name] = child;
}
this.children.pop();
// child.deleteFixedAttrs();
};
//fix#325
TypesElement.prototype.addChild = function (child) {
ok(child instanceof SchemaElement);
// Fallback to include namespace if targetNamespace is missing
let childInclude = child.includes && child.includes.find(function (e) {
return e.hasOwnProperty('namespace');
});
let childIncludeNs = childInclude && childInclude.namespace;
let targetNamespace = child.$targetNamespace || (child.includes && child.includes[0] && child.includes[0].namespace) || childIncludeNs;
if (!this.schemas.hasOwnProperty(targetNamespace)) {
this.schemas[targetNamespace] = child;
}
else {
// Merge schemas with duplicate namespaces instead of error
this.schemas[targetNamespace].merge(child);
}
};
InputElement.prototype.addChild = function (child) {
if (child.name === 'body') {
this.use = child.$use;
if (this.use === 'encoded') {
this.encodingStyle = child.$encodingStyle;
}
this.children.pop();
}
};
OutputElement.prototype.addChild = function (child) {
if (child.name === 'body') {
this.use = child.$use;
if (this.use === 'encoded') {
this.encodingStyle = child.$encodingStyle;
}
this.children.pop();
}
};
OperationElement.prototype.addChild = function (child) {
if (child.name === 'operation') {
this.soapAction = child.$soapAction || '';
this.style = child.$style || '';
this.children.pop();
}
};
BindingElement.prototype.addChild = function (child) {
if (child.name === 'binding') {
this.transport = child.$transport;
this.style = child.$style;
this.children.pop();
}
};
PortElement.prototype.addChild = function (child) {
if (child.name === 'address' && typeof (child.$location) !== 'undefined') {
this.location = child.$location;
}
};
DefinitionsElement.prototype.addChild = function (child) {
let self = this;
if (child instanceof TypesElement) {
// Merge types.schemas into definitions.schemas
_.merge(self.schemas, child.schemas);
}
else if (child instanceof MessageElement) {
self.messages[child.$name] = child;
}
else if (child.name === 'import') {
self.schemas[child.$namespace] = new SchemaElement(child.$namespace, {});
self.schemas[child.$namespace].addChild(child);
}
else if (child instanceof PortTypeElement) {
self.portTypes[child.$name] = child;
}
else if (child instanceof BindingElement) {
if (child.transport === 'http://schemas.xmlsoap.org/soap/http' ||
child.transport === 'http://www.w3.org/2003/05/soap/bindings/HTTP/')
self.bindings[child.$name] = child;
}
else if (child instanceof ServiceElement) {
self.services[child.$name] = child;
}
else if (child instanceof DocumentationElement) {
}
this.children.pop();
};
MessageElement.prototype.postProcess = function (definitions) {
let part = null;
let child = undefined;
let children = this.children || [];
let ns = undefined;
let nsName = undefined;
let i = undefined;
let type = undefined;
for (i in children) {
if ((child = children[i]).name === 'part') {
part = child;
break;
}
}
if (!part) {
return;
}
if (part.$element) {
let lookupTypes = [], elementChildren;
delete this.parts;
nsName = splitQName(part.$element);
ns = nsName.prefix;
let schema = definitions.schemas[definitions.xmlns[ns]];
this.element = schema.elements[nsName.name];
if (!this.element) {
// debug(nsName.name + " is not present in wsdl and cannot be processed correctly.");
return;
}
this.element.targetNSAlias = ns;
this.element.targetNamespace = definitions.xmlns[ns];
// set the optional $lookupType to be used within `client#_invoke()` when
// calling `wsdl#objectToDocumentXML()
this.element.$lookupType = part.$element;
elementChildren = this.element.children;
// get all nested lookup types (only complex types are followed)
if (elementChildren.length > 0) {
for (i = 0; i < elementChildren.length; i++) {
lookupTypes.push(this._getNestedLookupTypeString(elementChildren[i]));
}
}
// if nested lookup types where found, prepare them for furter usage
if (lookupTypes.length > 0) {
lookupTypes = lookupTypes.
join('_').
split('_').
filter(function removeEmptyLookupTypes(type) {
return type !== '^';
});
let schemaXmlns = definitions.schemas[this.element.targetNamespace].xmlns;
for (i = 0; i < lookupTypes.length; i++) {
lookupTypes[i] = this._createLookupTypeObject(lookupTypes[i], schemaXmlns);
}
}
this.element.$lookupTypes = lookupTypes;
if (this.element.$type) {
type = splitQName(this.element.$type);
let typeNs = schema.xmlns && schema.xmlns[type.prefix] || definitions.xmlns[type.prefix];
if (typeNs) {
if (type.name in Primitives) {
// this.element = this.element.$type;
}
else {
// first check local mapping of ns alias to namespace
schema = definitions.schemas[typeNs];
let ctype = schema.complexTypes[type.name] || schema.types[type.name] || schema.elements[type.name];
if (ctype) {
this.parts = ctype.description(definitions, schema.xmlns);
}
}
}
}
else {
let method = this.element.description(definitions, schema.xmlns);
this.parts = method[nsName.name];
}
this.children.splice(0, 1);
}
else {
// rpc encoding
this.parts = {};
delete this.element;
for (i = 0; part = this.children[i]; i++) {
if (part.name === 'documentation') {
// <wsdl:documentation can be present under <wsdl:message>
continue;
}
ok(part.name === 'part', 'Expected part element');
nsName = splitQName(part.$type);
ns = definitions.xmlns[nsName.prefix];
type = nsName.name;
let schemaDefinition = definitions.schemas[ns];
if (typeof schemaDefinition !== 'undefined') {
this.parts[part.$name] = definitions.schemas[ns].types[type] || definitions.schemas[ns].complexTypes[type];
}
else {
this.parts[part.$name] = part.$type;
}
if (typeof this.parts[part.$name] === 'object') {
this.parts[part.$name].prefix = nsName.prefix;
this.parts[part.$name].xmlns = ns;
}
this.children.splice(i--, 1);
}
}
this.deleteFixedAttrs();
};
/**
* Takes a given namespaced String(for example: 'alias:property') and creates a lookupType
* object for further use in as first (lookup) `parameterTypeObj` within the `objectToXML`
* method and provides an entry point for the already existing code in `findChildSchemaObject`.
*
* @method _createLookupTypeObject
* @param {String} nsString The NS String (for example "alias:type").
* @param {Object} xmlns The fully parsed `wsdl` definitions object (including all schemas).
* @returns {Object}
* @private
*/
MessageElement.prototype._createLookupTypeObject = function (nsString, xmlns) {
let splittedNSString = splitQName(nsString), nsAlias = splittedNSString.prefix, splittedName = splittedNSString.name.split('#'), type = splittedName[0], name = splittedName[1], lookupTypeObj = {};
lookupTypeObj.$namespace = xmlns[nsAlias];
lookupTypeObj.$type = nsAlias + ':' + type;
lookupTypeObj.$name = name;
return lookupTypeObj;
};
/**
* Iterates through the element and every nested child to find any defined `$type`
* property and returns it in a underscore ('_') separated String (using '^' as default
* value if no `$type` property was found).
*
* @method _getNestedLookupTypeString
* @param {Object} element The element which (probably) contains nested `$type` values.
* @returns {String}
* @private
*/
MessageElement.prototype._getNestedLookupTypeString = function (element) {
let resolvedType = '^', excluded = this.ignoredNamespaces.concat('xs'); // do not process $type values wich start with
if (element.hasOwnProperty('$type') && typeof element.$type === 'string') {
if (excluded.indexOf(element.$type.split(':')[0]) === -1) {
resolvedType += ('_' + element.$type + '#' + element.$name);
}
}
if (element.children.length > 0) {
let self = this;
element.children.forEach(function (child) {
let resolvedChildType = self._getNestedLookupTypeString(child).replace(/\^_/, '');
if (resolvedChildType && typeof resolvedChildType === 'string') {
resolvedType += ('_' + resolvedChildType);
}
});
}
return resolvedType;
};
OperationElement.prototype.postProcess = function (definitions, tag) {
let children = this.children;
for (let i = 0, child; child = children[i]; i++) {
if (child.name !== 'input' && child.name !== 'output')
continue;
if (tag === 'binding') {
this[child.name] = child;
children.splice(i--, 1);
continue;
}
let messageName = splitQName(child.$message).name;
let message = definitions.messages[messageName];
// Handle missing message definitions gracefully
if (!message) {
debug$1(`Warning: Message definition '${messageName}' not found in WSDL for operation '${this.$name}'`);
children.splice(i--, 1);
continue;
}
message.postProcess(definitions);
if (message.element) {
definitions.messages[message.element.$name] = message;
this[child.name] = message.element;
}
else {
this[child.name] = message;
}
children.splice(i--, 1);
}
this.deleteFixedAttrs();
};
PortTypeElement.prototype.postProcess = function (definitions) {
let children = this.children;
if (typeof children === 'undefined')
return;
for (let i = 0, child; child = children[i]; i++) {
if (child.name !== 'operation')
continue;
child.postProcess(definitions, 'portType');
this.methods[child.$name] = child;
children.splice(i--, 1);
}
delete this.$name;
this.deleteFixedAttrs();
};
BindingElement.prototype.postProcess = function (definitions) {
let type = splitQName(this.$type).name, portType = definitions.portTypes[type], style = this.style, children = this.children;
if (portType) {
portType.postProcess(definitions);
this.methods = portType.methods;
for (let i = 0, child; child = children[i]; i++) {
if (child.name !== 'operation')
continue;
child.postProcess(definitions, 'binding');
children.splice(i--, 1);
child.style || (child.style = style);
let method = this.methods[child.$name];
if (method) {
method.style = child.style;
method.soapAction = child.soapAction;
method.inputSoap = child.input || null;
method.outputSoap = child.output || null;
method.inputSoap && method.inputSoap.deleteFixedAttrs();
method.outputSoap && method.outputSoap.deleteFixedAttrs();
}
}
}
delete this.$name;
delete this.$type;
this.deleteFixedAttrs();
};
ServiceElement.prototype.postProcess = function (definitions) {
let children = this.children, bindings = definitions.bindings;
if (children && children.length > 0) {
for (let i = 0, child; child = children[i]; i++) {
if (child.name !== 'port')
continue;
let bindingName = splitQName(child.$binding).name;
let binding = bindings[bindingName];
if (binding) {
binding.postProcess(definitions);
this.ports[child.$name] = {
location: child.location,
binding: binding
};
children.splice(i--, 1);
}
}
}
delete this.$name;
this.deleteFixedAttrs();
};
SimpleTypeElement.prototype.description = function (definitions) {
let children = this.children;
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof RestrictionElement)
return this.$name + "|" + child.description();
}
return {};
};
RestrictionElement.prototype.description = function (definitions, xmlns) {
let children = this.children;
let desc;
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof SequenceElement ||
child instanceof ChoiceElement) {
desc = child.description(definitions, xmlns);
break;
}
}
if (desc && this.$base) {
let type = splitQName(this.$base), typeName = type.name, ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix], schema = definitions.schemas[ns], typeElement = schema && (schema.complexTypes[typeName] || schema.types[typeName] || schema.elements[typeName]);
desc.getBase = function () {
return typeElement.description(definitions, schema.xmlns);
};
return desc;
}
// then simple element
let base = this.$base ? this.$base + "|" : "";
return base + this.children.map(function (child) {
return child.description();
}).join(",");
};
ExtensionElement.prototype.description = function (definitions, xmlns) {
let children = this.children;
let desc = {};
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof SequenceElement ||
child instanceof ChoiceElement) {
desc = child.description(definitions, xmlns);
}
}
if (this.$base) {
let type = splitQName(this.$base), typeName = type.name, ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix], schema = definitions.schemas[ns];
if (typeName in Primitives) {
return this.$base;
}
else {
let typeElement = schema && (schema.complexTypes[typeName] ||
schema.types[typeName] || schema.elements[typeName]);
if (typeElement) {
let base = typeElement.description(definitions, schema.xmlns);
desc = _.defaultsDeep(base, desc);
}
}
}
return desc;
};
EnumerationElement.prototype.description = function () {
return this[this.valueKey];
};
ComplexTypeElement.prototype.description = function (definitions, xmlns) {
let children = this.children || [];
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof ChoiceElement ||
child instanceof SequenceElement ||
child instanceof AllElement ||
child instanceof SimpleContentElement ||
child instanceof ComplexContentElement) {
return child.description(definitions, xmlns);
}
}
return {};
};
ComplexContentElement.prototype.description = function (definitions, xmlns) {
let children = this.children;
for (let i = 0, child; child = children[i]; i++) {
// Handle both ExtensionElement and RestrictionElement in ComplexContent
if (child instanceof ExtensionElement || child instanceof RestrictionElement) {
return child.description(definitions, xmlns);
}
}
return {};
};
SimpleContentElement.prototype.description = function (definitions, xmlns) {
let children = this.children;
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof ExtensionElement) {
return child.description(definitions, xmlns);
}
}
return {};
};
ElementElement.prototype.description = function (definitions, xmlns) {
let element = {}, name = this.$name;
// Apply element key override if configured (for element renaming)
if (definitions.options && definitions.options.overrideElementKey && definitions.options.overrideElementKey[name]) {
name = definitions.options.overrideElementKey[name];
debug$1('Element key overridden: %s -> %s', this.$name, name);
}
let isMany = !this.$maxOccurs ? false : (isNaN(this.$maxOccurs) ? (this.$maxOccurs === 'unbounded') : (this.$maxOccurs > 1));
if (this.$minOccurs !== this.$maxOccurs && isMany) {
name += '[]';
}
if (xmlns && xmlns[TNS_PREFIX]) {
this.$targetNamespace = xmlns[TNS_PREFIX];
}
let type = this.$type || this.$ref;
if (type) {
type = splitQName(type);
let typeName = type.name, ns = xmlns && xmlns[type.prefix] || definitions.xmlns[type.prefix], schema = definitions.schemas[ns], typeElement = schema && (this.$type ? schema.complexTypes[typeName] || schema.types[typeName] : schema.elements[typeName]);
if (ns && definitions.schemas[ns]) {
xmlns = definitions.schemas[ns].xmlns;
}
if (typeElement && !(typeName in Primitives)) {
if (!(typeName in definitions.descriptions.types)) {
let elem = {};
definitions.descriptions.types[typeName] = elem;
let description = typeElement.description(definitions, xmlns);
if (typeof description === 'string') {
elem = description;
}
else {
Object.keys(description).forEach(function (key) {
elem[key] = description[key];
});
}
if (this.$ref) {
// For element refs, preserve maxOccurs/minOccurs from the referring element
// If the referring element has maxOccurs/minOccurs, apply array notation
if (isMany && typeof elem === 'object') {
// Apply array notation to the referenced element's name
let refElemName = Object.keys(elem)[0];
if (refElemName && !refElemName.endsWith('[]')) {
let refValue = elem[refElemName];
delete elem[refElemName];
elem[refElemName + '[]'] = refValue;
}
}
element = elem;
}
else {
element[name] = elem;
}
if (typeof elem === 'object') {
elem.targetNSAlias = type.prefix;
elem.targetNamespace = ns;
}
definitions.descriptions.types[typeName] = elem;
}
else {
if (this.$ref) {
// Apply maxOccurs/minOccurs from referring element to cached description
let cachedElem = definitions.descriptions.types[typeName];
if (isMany && typeof cachedElem === 'object') {
let refElemName = Object.keys(cachedElem)[0];
if (refElemName && !refElemName.endsWith('[]')) {
// Create a new object with array notation
element = {};
element[refElemName + '[]'] = cachedElem[refElemName];
}
else {
element = cachedElem;
}
}
else {
element = cachedElem;
}
}
else {
element[name] = definitions.descriptions.types[typeName];
}
}
}
else {
element[name] = this.$type;
}
}
else {
let children = this.children;
element[name] = {};
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof ComplexTypeElement) {
element[name] = child.description(definitions, xmlns);
}
}
}
return element;
};
AllElement.prototype.description =
SequenceElement.prototype.description = function (definitions, xmlns) {
let children = this.children;
let sequence = {};
for (let i = 0, child; child = children[i]; i++) {
if (child instanceof AnyElement) {
continue;
}
let description = child.description(definitions, xmlns);
for (let key in description) {
sequence[key] = description[key];
}
}
return sequence;
};
ChoiceElement.prototype.description = function (definitions, xmlns) {
let children = this.children;
let choice = {};
for (let i = 0, child; child = children[i]; i++) {
let description = child.description(definitions, xmlns);
for (let key in description) {
choice[key] = description[key];
}
}
return choice;
};
MessageElement.prototype.description = function (definitions) {
if (this.element) {
return this.element && this.element.description(definitions);
}
let desc = {};
desc[this.$name] = this.parts;
return desc;
};
PortTypeElement.prototype.description = function (definitions) {
let methods = {};
for (let name in this.methods) {
let method = this.methods[name];
methods[name] = method.description(definitions);
}
return methods;
};
OperationElement.prototype.description = function (definitions) {
let inputDesc = this.input ? this.input.description(definitions) : null;
let outputDesc = this.output ? this.output.description(definitions) : null;
return {
input: inputDesc && inputDesc[Object.keys(inputDesc)[0]],
output: outputDesc && outputDesc[Object.keys(outputDesc)[0]]
};
};
BindingElement.prototype.description = function (definitions) {
let methods = {};
for (let name in this.methods) {
let method = this.methods[name];
methods[name] = method.description(definitions);
}
return methods;
};
ServiceElement.prototype.description = function (definitions) {
let ports = {};
for (let name in this.ports) {
let port = this.ports[name];
ports[name] = port.binding.description(definitions);
}
return ports;
};
let WSDL$1 = function (definition, uri, options) {
let self = this, fromFunc;
this.uri = uri;
this.callback = function () {
};
this._includesWsdl = [];
// initialize WSDL cache
this.WSDL_CACHE = (options || {}).WSDL_CACHE || {};
this._initializeOptions(options);
if (typeof definition === 'string') {
definition = stripBom(definition);
fromFunc = this._fromXML;
}
else if (typeof definition === 'object') {
fromFunc = this._fromServices;
}
else {
throw new Error('WSDL letructor takes either an XML string or service definition');
}
Promise.resolve(true).then(() => {
try {
fromFunc.call(self, definition);
}
catch (e) {
return self.callback(e.message);
}
self.processIncludes().then(() => {
self.definitions.deleteFixedAttrs();
let services = self.services = self.definitions.services;
if (services) {
for (const name in services) {
services[name].postProcess(self.definitions);
}
}
let complexTypes = self.definitions.complexTypes;
if (complexTypes) {
for (const name in complexTypes) {
complexTypes[name].deleteFixedAttrs();
}
}
// for document style, for every binding, prepare input message element name to (methodName, output message element name) mapping
let bindings = self.definitions.bindings;
for (let bindingName in bindings) {
let binding = bindings[bindingName];
if (typeof binding.style === 'undefined') {
binding.style = 'document';
}
if (binding.style !== 'document')
continue;
let methods = binding.methods;
let topEls = binding.topElements = {};
for (let methodName in methods) {
if (methods[methodName].input) {
let inputName = methods[methodName].input.$name;
let outputName = "";
if (methods[methodName].output)
outputName = methods[methodName].output.$name;
topEls[inputName] = { "methodName": methodName, "outputName": outputName };
}
}
}
// prepare soap envelope xmlns definition string
self.xmlnsInEnvelope = self._xmlnsMap();
self.callback(null, self);
}).catch(err => self.callback(err));
});
// process.nextTick(function() {
// try {
// fromFunc.call(self, definition);
// } catch (e) {
// return self.callback(e.message);
// }
// self.processIncludes(function(err) {
// let name;
// if (err) {
// return self.callback(err);
// }
// self.definitions.deleteFixedAttrs();
// let services = self.services = self.definitions.services;
// if (services) {
// for (name in services) {
// services[name].postProcess(self.definitions);
// }
// }
// let complexTypes = self.definitions.complexTypes;
// if (complexTypes) {
// for (name in complexTypes) {
// complexTypes[name].deleteFixedAttrs();
// }
// }
// // for document style, for every binding, prepare input message element name to (methodName, output message element name) mapping
// let bindings = self.definitions.bindings;
// for (let bindingName in bindings) {
// let binding = bindings[bindingName];
// if (typeof binding.style === 'undefined') {
// binding.style = 'document';
// }
// if (binding.style !== 'document')
// continue;
// let methods = binding.methods;
// let topEls = binding.topElements = {};
// for (let methodName in methods) {
// if (methods[methodName].input) {
// let inputName = methods[methodName].input.$name;
// let outputName="";
// if(methods[methodName].output )
// outputName = methods[methodName].output.$name;
// topEls[inputName] = {"methodName": methodName, "outputName": outputName};
// }
// }
// }
// // prepare soap envelope xmlns definition string
// self.xmlnsInEnvelope = self._xmlnsMap();
// self.callback(err, self);
// });
// });
};
WSDL$1.prototype.ignoredNamespaces = ['tns', 'targetNamespace', 'typedNamespace'];
WSDL$1.prototype.ignoreBaseNameSpaces = false;
WSDL$1.prototype.valueKey = '$value';
WSDL$1.prototype.xmlKey = '$xml';
WSDL$1.prototype._initializeOptions = function (options) {
this._originalIgnoredNamespaces = (options || {}).ignoredNamespaces;
this.options = {};
let ignoredNamespaces = options ? options.ignoredNamespaces : null;
if (ignoredNamespaces &&
(Array.isArray(ignoredNamespaces.namespaces) || typeof ignoredNamespaces.namespaces === 'string')) {
if (ignoredNamespaces.override) {
this.options.ignoredNamespaces = ignoredNamespaces.namespaces;
}
else {
this.options.ignoredNamespaces = this.ignoredNamespaces.concat(ignoredNamespaces.namespaces);
}
}
else {
this.options.ignoredNamespaces = this.ignoredNamespaces;
}
this.options.valueKey = options.valueKey || this.valueKey;
this.options.xmlKey = options.xmlKey || this.xmlKey;
if (options.escapeXML !== undefined) {
this.options.escapeXML = options.escapeXML;
}
else {
this.options.escapeXML = true;
}
if (options.returnFault !== undefined) {
this.options.returnFault = options.returnFault;
}
else {
this.options.returnFault = false;
}
this.options.handleNilAsNull = !!options.handleNilAsNull;
if (options.namespaceArrayElements !== undefined) {
this.options.namespaceArrayElements = options.namespaceArrayElements;
}
else {
this.options.namespaceArrayElements = true;
}
// Configuration options
this.options.useEmptyTag = options.useEmptyTag !== undefined ? options.useEmptyTag : false;
this.options.preserveWhitespace = options.preserveWhitespace !== undefined ? options.preserveWhitespace : false;
this.options.normalizeNames = options.normalizeNames !== undefined ? options.normalizeNames : false;
this.options.suppressStack = options.suppressStack !== undefined ? options.suppressStack : false;
this.options.forceUseSchemaXmlns = options.forceUseSchemaXmlns !== undefined ? options.forceUseSchemaXmlns : false;
this.options.envelopeKey = options.envelopeKey || 'soap';
this.options.overridePromiseSuffix = options.overridePromiseSuffix || 'Async';
// Multi-service/multi-port support
this.options.serviceName = options.serviceName;
this.options.portName = options.portName;
// Element key override support
this.options.overrideElementKey = options.overrideElementKey;
// Custom SOAP envelope URL support
this.options.envelopeSoapUrl = options.envelopeSoapUrl;
// Response encoding support
this.options.encoding = options.encoding || 'utf-8';
// Custom WSDL cache support
this.options.wsdlCache = options.wsdlCache;
// Allow any request headers to keep passing through
this.options.wsdl_headers = options.wsdl_headers;
this.options.wsdl_options = options.wsdl_options;
if (options.httpClient) {
this.options.httpClient = options.httpClient;
}
// The supplied request-object should be passed through
if (options.request) {
this.options.request = options.request;
}
let ignoreBaseNameSpaces = options ? options.ignoreBaseNameSpaces : null;
if (ignoreBaseNameSpaces !== null && typeof ignoreBaseNameSpaces !== 'undefined') {
this.options.ignoreBaseNameSpaces = ignoreBaseNameSpaces;
}
else {
this.options.ignoreBaseNameSpaces = this.ignoreBaseNameSpaces;
}
// Works only in client
this.options.forceSoap12Headers = options.forceSoap12Headers;
this.options.customDeserializer = options.customDeserializer;
if (options.overrideRootElement !== undefined) {
this.options.overrideRootElement = options.overrideRootElement;
}
};
WSDL$1.prototype.onReady = function (callback) {
if (callback)
this.callback = callback;
};
WSDL$1.prototype._processNextInclude = async function (includes) {
let self = this, include = includes.shift(), options;
if (!include)
return; // callback();
let includePath;
if (!/^https?:/.test(self.uri) && !/^https?:/.test(include.location)) {
// includePath = path.resolve(path.dirname(self.uri), include.location);
}
else {
includePath = url.resolve(self.uri || '', include.location);
}
options = _.assign({}, this.options);
// follow supplied ignoredNamespaces option
options.ignoredNamespaces = this._originalIgnoredNamespaces || this.options.ignoredNamespaces;
options.WSDL_CACHE = this.WSDL_CACHE;
const wsdl = await open_wsdl_recursive(includePath, options);
self._includesWsdl.push(wsdl);
if (wsdl.definitions instanceof DefinitionsElement) {
_.mergeWith(self.definitions, wsdl.definitions, function (a, b) {
return (a instanceof SchemaElement) ? a.merge(b) : undefined;
});
}
else {
self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace] = deepMerge(self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace], wsdl.definitions);
}
return self._processNextInclude(includes);
// open_wsdl_recursive(includePath, options, function(err, wsdl) {
// if (err) {
// return callback(err);
// }
// self._includesWsdl.push(wsdl);
// if (wsdl.definitions instanceof DefinitionsElement) {
// _.mergeWith(self.definitions, wsdl.definitions, function(a,b) {
// return (a instanceof SchemaElement) ? a.merge(b) : undefined;
// });
// } else {
// self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace] = deepMerge(self.definitions.schemas[include.namespace || wsdl.definitions.$targetNamespace], wsdl.definitions);
// }
// self._processNextInclude(includes, function(err) {
// callback(err);
// });
// });
};
WSDL$1.prototype.processIncludes = async function () {
let schemas = this.definitions.schemas, includes = [];
for (let ns in schemas) {
let schema = schemas[ns];
includes = includes.concat(schema.includes || []);
}
return this._processNextInclude(includes);
};
WSDL$1.prototype.describeServices = function () {
let services = {};
for (let name in this.services) {
let service = this.services[name];
services[name] = service.description(this.definitions);
}
return services;
};
WSDL$1.prototype.toXML = function () {
return this.xml || '';
};
WSDL$1.prototype.xmlToObject = function (xml, callback) {
let self = this;
let p = typeof callback === 'function' ? {} : sax.parser(true);
let objectName = null;
let root = {};
let schema = {
Envelope: {
Header: {
Security: {
UsernameToken: {
Username: 'string',
Password: 'string'
}
}
},
Body: {
Fault: {
faultcode: 'string',
faultstring: 'string',
detail: 'string'
}
}
}
};
let stack = [{ name: null, object: root, schema: schema }];
let xmlns = {};
let refs = {}, id; // {id:{hrefs:[],obj:}, ...}
p.onopentag = function (node) {
let nsName = node.name;
let attrs = node.attributes;
let name = splitQName(nsName).name, attributeName, top = stack[stack.length - 1], topSchema = top.schema, elementAttributes = {}, hasNonXmlnsAttribute = false, hasNilAttribute = false, obj = {};
let originalName = name;
if (!objectName && top.name === 'Body' && name !== 'Fault') {
let message = self.definitions.messages[name];
// Support RPC/literal messages where response body contains one element named
// after the operation + 'Response'. See http://www.w3.org/TR/wsdl#_names
if (!message) {
try {
// Determine if this is request or response
let isInput = false;
let isOutput = false;
if ((/Response$/).test(name)) {
isOutput = true;
name = name.replace(/Response$/, '');
}
else if ((/Request$/).test(name)) {
isInput = true;
name = name.replace(/Request$/, '');
}
else if ((/Solicit$/).test(name)) {
isInput = true;
name = name.replace(/Solicit$/, '');
}
// Look up the appropriate message as given in the portType's operations
let portTypes = self.definitions.portTypes;
let portTypeNames = Object.keys(portTypes);
// Currently this supports only one portType definition.
let portType = portTypes[portTypeNames[0]];
if (isInput) {
name = portType.methods[name].input.$name;
}
else {
name = portType.methods[name].output.$name;
}
message = self.definitions.messages[name];
// 'cache' this alias to speed future lookups
self.definitions.messages[originalName] = self.definitions.messages[name];
}
catch (e) {
if (self.options.returnFault) {
p.onerror(e);
}
}
}
topSchema = message.description(self.definitions);
objectName = originalName;
}
if (attrs.href) {
id = attrs.href.substr(1);
if (!refs[id]) {
refs[id] = { hrefs: [], obj: null };
}
refs[id].hrefs.push({ par: top.object, key: name, obj: obj });
}
if (id = attrs.id) {
if (!refs[id]) {
refs[id] = { hrefs: [], obj: null };
}
}
//Handle element attributes
for (attributeName in attrs) {
if (/^xmlns:|^xmlns$/.test(attributeName)) {
xmlns[splitQName(attributeName).name] = attrs[attributeName];
continue;
}
hasNonXmlnsAttribute = true;
elementAttributes[attributeName] = attrs[attributeName];
}
for (attributeName in elementAttributes) {
let res = splitQName(attributeName);
if (res.name === 'nil' && xmlns[res.prefix] === 'http://www.w3.org/2001/XMLSchema-instance' && elementAttributes[attributeName] &&
(elementAttributes[attributeName].toLowerCase() === 'true' || elementAttributes[attributeName] === '1')) {
hasNilAttribute = true;
break;
}
}
if (hasNonXmlnsAttribute) {
obj[self.options.attributesKey] = elementAttributes;
}
// Pick up the schema for the type specified in element's xsi:type attribute.
let xsiTypeSchema;
let xsiType = elementAttributes['xsi:type'];
if (xsiType) {
let type = splitQName(xsiType);
let typeURI;
if (type.prefix === TNS_PREFIX) {
// In case of xsi:type = "MyType"
typeURI = xmlns[type.prefix] || xmlns.xmlns;
}
else {
typeURI = xmlns[type.prefix];
}
let typeDef = self.findSchemaObject(typeURI, type.name);
if (typeDef) {
xsiTypeSchema = typeDef.description(self.definitions);
}
}
if (topSchema && topSchema[name + '[]']) {
name = name + '[]';
}
stack.push({
name: originalName,
object: obj,
schema: (xsiTypeSchema || (topSchema && topSchema[name])),
id: attrs.id,
nil: hasNilAttribute
});
};
p.onclosetag = function (nsName) {
let cur = stack.pop(), obj = cur.object, top = stack[stack.length - 1], topObject = top.object, topSchema = top.schema, name = splitQName(nsName).name;
if (typeof cur.schema === 'string' && (cur.schema === 'string' || cur.schema.split(':')[1] === 'string')) {
if (typeof obj === 'object' && Object.keys(obj).length === 0)
obj = cur.object = '';
}
if (cur.nil === true) {
if (self.options.handleNilAsNull) {
obj = null;
}
else {
return;
}
}
if (_.isPlainObject(obj) && !Object.keys(obj).length) {
obj = null;
}
if (topSchema && topSchema[name + '[]']) {
if (!topObject[name]) {
topObject[name] = [];
}
topObject[name].push(obj);
}
else if (name in topObject) {
if (!Array.isArray(topObject[name])) {
topObject[name] = [topObject[name]];
}
topObject[name].push(obj);
}
else {
topObject[name] = obj;
}
if (cur.id) {
refs[cur.id].obj = obj;
}
};
p.oncdata = function (text) {
let originalText = text;
text = trim(text);
if (!text.length) {
return;
}
if (/<\?xml[\s\S]+\?>/.test(text)) {
let top = stack[stack.length - 1];
let value = self.xmlToObject(text);
if (top.object[self.options.attributesKey]) {
top.object[self.options.valueKey] = value;
}
else {
top.object = value;
}
}
else {
p.ontext(originalText);
}
};
p.onerror = function (e) {
p.resume();
throw {
Fault: {
faultcode: 500,
faultstring: 'Invalid XML',
detail: new Error(e).message,
statusCode: 500
}
};
};
p.ontext = function (text) {
let originalText = text;
text = trim(text);
if (!text.length) {
return;
}
let top = stack[stack.length - 1];
let name = splitQName(top.schema).name, value;
if (self.options && self.options.customDeserializer && self.options.customDeserializer[name]) {
value = self.options.customDeserializer[name](text, top);
}
else {
if (name === 'int' || name === 'integer') {
value = parseInt(text, 10);
}
else if (name === 'bool' || name === 'boolean') {
value = text.toLowerCase() === 'true' || text === '1';
}
else if (name === 'dateTime' || name === 'date') {
value = new Date(text);
}
else {
if (self.options.preserveWhitespace) {
text = originalText;
}
// handle string or other types
if (typeof top.object !== 'string') {
value = text;
}
else {
value = top.object + text;
}
}
}
if (top.object[self.options.attributesKey]) {
top.object[self.options.valueKey] = value;
}
else {
top.object = value;
}
};
if (typeof callback === 'function') {
// we be streaming
let saxStream = sax.createStream(true);
saxStream.on('opentag', p.onopentag);
saxStream.on('closetag', p.onclosetag);
saxStream.on('cdata', p.oncdata);
saxStream.on('text', p.ontext);
xml.pipe(saxStream)
.on('error', function (err) {
callback(err);
})
.on('end', function () {
let r;
try {
r = finish();
}
catch (e) {
return callback(e);
}
callback(null, r);
});
return;
}
p.write(xml).close();
return finish();
function finish() {
// MultiRef support: merge objects instead of replacing
for (let n in refs) {
let ref = refs[n];
for (let i = 0; i < ref.hrefs.length; i++) {
_.assign(ref.hrefs[i].obj, ref.obj);
}
}
if (root.Envelope) {
let body = root.Envelope.Body;
if (body && body.Fault) {
const fault = body.Fault;
let code, string, actor, detail, statusCode;
// SOAP 1.1 Fault
if (fault.faultcode) {
code = fault.faultcode && fault.faultcode.$value || fault.faultcode;
string = fault.faultstring && fault.faultstring.$value || fault.faultstring;
actor = fault.faultactor && fault.faultactor.$value || fault.faultactor;
detail = fault.detail && fault.detail.$value || fault.detail;
statusCode = fault.statusCode;
}
// SOAP 1.2 Fault
else if (fault.Code) {
code = fault.Code.Value;
string = fault.Reason && fault.Reason.Text && fault.Reason.Text.$value
|| fault.Reason && fault.Reason.Text
|| '';
actor = fault.Role;
detail = fault.Detail;
statusCode = fault.statusCode;
}
const error = new Error(string || code);
error.root = root;
error.Fault = fault;
error.code = code;
error.string = string;
error.actor = actor;
error.detail = detail;
error.statusCode = statusCode || 500;
// If returnFault option is enabled, return the fault in the response instead of throwing
if (self.options.returnFault) {
debug$1('SOAP Fault (returnFault=true): %s', string || code);
return root.Envelope;
}
debug$1('SOAP Fault: %s', string || code);
throw error;
}
return root.Envelope;
}
return root;
}
};
/**
* Look up a XSD type or element by namespace URI and name
* @param {String} nsURI Namespace URI
* @param {String} qname Local or qualified name
* @returns {*} The XSD type/element definition
*/
WSDL$1.prototype.findSchemaObject = function (nsURI, qname) {
if (!nsURI || !qname) {
return null;
}
let def = null;
if (this.definitions.schemas) {
let schema = this.definitions.schemas[nsURI];
if (schema) {
if (qname.indexOf(':') !== -1) {
qname = qname.substring(qname.indexOf(':') + 1, qname.length);
}
// if the client passed an input element which has a `$lookupType` property instead of `$type`
// the `def` is found in `schema.elements`.
def = schema.complexTypes[qname] || schema.types[qname] || schema.elements[qname];
}
}
return def;
};
/**
* Create document style xml string from the parameters
* @param {String} name
* @param {*} params
* @param {String} nsPrefix
* @param {String} nsURI
* @param {String} type
*/
WSDL$1.prototype.objectToDocumentXML = function (name, params, nsPrefix, nsURI, type) {
//If user supplies XML already, just use that. XML Declaration should not be present.
if (params && params._xml) {
return params._xml;
}
let args = {};
args[name] = params;
let parameterTypeObj = type ? this.findSchemaObject(nsURI, type) : null;
return this.objectToXML(args, null, nsPrefix, nsURI, true, null, parameterTypeObj);
};
/**
* Create RPC style xml string from the parameters
* @param {String} name
* @param {*} params
* @param {String} nsPrefix
* @param {String} nsURI
* @returns {string}
*/
WSDL$1.prototype.objectToRpcXML = function (name, params, nsPrefix, nsURI, isParts) {
let parts = [];
let defs = this.definitions;
let nsAttrName = '_xmlns';
nsPrefix = nsPrefix || findPrefix(defs.xmlns, nsURI);
nsURI = nsURI || defs.xmlns[nsPrefix];
nsPrefix = nsPrefix === TNS_PREFIX ? '' : (nsPrefix + ':');
parts.push(['<', nsPrefix, name, '>'].join(''));
for (let key in params) {
if (!params.hasOwnProperty(key)) {
continue;
}
if (key !== nsAttrName) {
let value = params[key];
let prefixedKey = (isParts ? '' : nsPrefix) + key;
let attributes = [];
if (typeof value === 'object' && value.hasOwnProperty(this.options.attributesKey)) {
let attrs = value[this.options.attributesKey];
for (let n in attrs) {
attributes.push(' ' + n + '=' + '"' + attrs[n] + '"');
}
}
parts.push(['<', prefixedKey].concat(attributes).concat('>').join(''));
parts.push((typeof value === 'object') ? this.objectToXML(value, key, nsPrefix, nsURI) : xmlEscape(value));
parts.push(['</', prefixedKey, '>'].join(''));
}
}
parts.push(['</', nsPrefix, name, '>'].join(''));
return parts.join('');
};
function appendColon(ns) {
return (ns && ns.charAt(ns.length - 1) !== ':') ? ns + ':' : ns;
}
function noColonNameSpace(ns) {
return (ns && ns.charAt(ns.length - 1) === ':') ? ns.substring(0, ns.length - 1) : ns;
}
WSDL$1.prototype.isIgnoredNameSpace = function (ns) {
return this.options.ignoredNamespaces.indexOf(ns) > -1;
};
WSDL$1.prototype.filterOutIgnoredNameSpace = function (ns) {
let namespace = noColonNameSpace(ns);
return this.isIgnoredNameSpace(namespace) ? '' : namespace;
};
/**
* Convert an object to XML. This is a recursive method as it calls itself.
*
* @param {Object} obj the object to convert.
* @param {String} name the name of the element (if the object being traversed is
* an element).
* @param {String} nsPrefix the namespace prefix of the object I.E. xsd.
* @param {String} nsURI the full namespace of the object I.E. http://w3.org/schema.
* @param {Boolean} isFirst whether or not this is the first item being traversed.
* @param {?} xmlnsAttr
* @param {?} parameterTypeObject
* @param {NamespaceContext} nsContext Namespace context
*/
WSDL$1.prototype.objectToXML = function (obj, name, nsPrefix, nsURI, isFirst, xmlnsAttr, schemaObject, nsContext) {
const schema = this.definitions.schemas[nsURI];
let parentNsPrefix = nsPrefix ? nsPrefix.parent : undefined;
if (typeof parentNsPrefix !== 'undefined') {
// we got the parentNsPrefix for our array. setting the namespace-variable back to the current namespace string
nsPrefix = nsPrefix.current;
}
parentNsPrefix = noColonNameSpace(parentNsPrefix);
if (this.isIgnoredNameSpace(parentNsPrefix)) {
parentNsPrefix = '';
}
const soapHeader = !schema;
const qualified = schema && schema.$elementFormDefault === 'qualified';
const parts = [];
const prefixNamespace = (nsPrefix || qualified) && nsPrefix !== TNS_PREFIX;
let xmlnsAttrib = '';
if (nsURI && isFirst) {
if (this.options.overrideRootElement && this.options.overrideRootElement.xmlnsAttributes) {
this.options.overrideRootElement.xmlnsAttributes.forEach((attribute) => {
xmlnsAttrib += ' ' + attribute.name + '="' + attribute.value + '"';
});
}
else {
if (prefixNamespace && !this.isIgnoredNameSpace(nsPrefix)) {
// resolve the prefix namespace
xmlnsAttrib += ' xmlns:' + nsPrefix + '="' + nsURI + '"';
}
// only add default namespace if the schema elementFormDefault is qualified
if (qualified || soapHeader) {
xmlnsAttrib += ' xmlns="' + nsURI + '"';
}
}
}
if (!nsContext) {
nsContext = new NamespaceContext();
nsContext.declareNamespace(nsPrefix, nsURI);
}
else {
nsContext.pushContext();
}
// explicitly use xmlns attribute if available
if (xmlnsAttr && !(this.options.overrideRootElement && this.options.overrideRootElement.xmlnsAttributes)) {
xmlnsAttrib = xmlnsAttr;
}
let ns = '';
if (this.options.overrideRootElement && isFirst) {
ns = this.options.overrideRootElement.namespace;
}
else if (prefixNamespace && (qualified || isFirst || soapHeader) && !this.isIgnoredNameSpace(nsPrefix)) {
ns = nsPrefix;
}
let i;
let n;
// start building out XML string.
if (Array.isArray(obj)) {
let nonSubNameSpace = '';
let emptyNonSubNameSpaceForArray = false;
const nameWithNsRegex = /^([^:]+):([^:]+)$/.exec(name);
if (nameWithNsRegex) {
nonSubNameSpace = nameWithNsRegex[1];
name = nameWithNsRegex[2];
}
else if (name[0] === ':') {
emptyNonSubNameSpaceForArray = true;
name = name.substr(1);
}
for (i = 0, n = obj.length; i < n; i++) {
const item = obj[i];
const arrayAttr = this.processAttributes(item, nsContext);
const correctOuterNsPrefix = nonSubNameSpace || parentNsPrefix || ns; // using the parent namespace prefix if given
const body = this.objectToXML(item, name, nsPrefix, nsURI, false, null, schemaObject, nsContext);
let openingTagParts = ['<', name, arrayAttr, xmlnsAttrib];
if (!emptyNonSubNameSpaceForArray) {
openingTagParts = ['<', appendColon(correctOuterNsPrefix), name, arrayAttr, xmlnsAttrib];
}
if (body === '' && this.options.useEmptyTag) {
// Use empty (self-closing) tags if no contents
openingTagParts.push(' />');
parts.push(openingTagParts.join(''));
}
else {
openingTagParts.push('>');
if (this.options.namespaceArrayElements || i === 0) {
parts.push(openingTagParts.join(''));
}
parts.push(body);
if (this.options.namespaceArrayElements || i === n - 1) {
if (emptyNonSubNameSpaceForArray) {
parts.push(['</', name, '>'].join(''));
}
else {
parts.push(['</', appendColon(correctOuterNsPrefix), name, '>'].join(''));
}
}
}
}
}
else if (typeof obj === 'object') {
for (name in obj) {
if (!obj.hasOwnProperty(name)) {
continue;
}
// don't process attributes as element
if (name === this.options.attributesKey) {
continue;
}
// Its the value of a xml object. Return it directly.
if (name === this.options.xmlKey) {
nsContext.popContext();
return obj[name];
}
// Its the value of an item. Return it directly.
if (name === this.options.valueKey) {
nsContext.popContext();
return xmlEscape(obj[name]);
}
const child = obj[name];
if (typeof child === 'undefined') {
continue;
}
const attr = this.processAttributes(child, nsContext);
let value = '';
let nonSubNameSpace = '';
let emptyNonSubNameSpace = false;
const nameWithNsRegex = /^([^:]+):([^:]+)$/.exec(name);
if (nameWithNsRegex) {
nonSubNameSpace = nameWithNsRegex[1] + ':';
name = nameWithNsRegex[2];
}
else if (name[0] === ':') {
emptyNonSubNameSpace = true;
name = name.substr(1);
}
if (isFirst) {
value = this.objectToXML(child, name, nsPrefix, nsURI, false, null, schemaObject, nsContext);
}
else {
if (this.definitions.schemas) {
if (schema) {
const childSchemaObject = this.findChildSchemaObject(schemaObject, name);
// find sub namespace if not a primitive
if (childSchemaObject &&
((childSchemaObject.$type && (childSchemaObject.$type.indexOf('xsd:') === -1)) ||
childSchemaObject.$ref || childSchemaObject.$name)) {
/*if the base name space of the children is not in the ingoredSchemaNamspaces we use it.
This is because in some services the child nodes do not need the baseNameSpace.
*/
let childNsPrefix = '';
let childName = '';
let childNsURI;
let childXmlnsAttrib = '';
let elementQName = childSchemaObject.$ref || childSchemaObject.$name;
if (elementQName) {
elementQName = splitQName(elementQName);
childName = elementQName.name;
if (elementQName.prefix === TNS_PREFIX) {
// Local element
childNsURI = childSchemaObject.$targetNamespace;
childNsPrefix = nsContext.registerNamespace(childNsURI);
if (this.isIgnoredNameSpace(childNsPrefix)) {
childNsPrefix = nsPrefix;
}
}
else {
childNsPrefix = elementQName.prefix;
if (this.isIgnoredNameSpace(childNsPrefix)) {
childNsPrefix = nsPrefix;
}
childNsURI = schema.xmlns[childNsPrefix] || this.definitions.xmlns[childNsPrefix];
}
let unqualified = false;
// Check qualification form for local elements
if (childSchemaObject.$name && childSchemaObject.targetNamespace === undefined) {
if (childSchemaObject.$form === 'unqualified') {
unqualified = true;
}
else if (childSchemaObject.$form === 'qualified') {
unqualified = false;
}
else {
unqualified = schema.$elementFormDefault !== 'qualified';
}
}
if (unqualified) {
childNsPrefix = '';
}
if (childNsURI && childNsPrefix) {
if (nsContext.declareNamespace(childNsPrefix, childNsURI)) {
childXmlnsAttrib = ' xmlns:' + childNsPrefix + '="' + childNsURI + '"';
xmlnsAttrib += childXmlnsAttrib;
}
}
}
let resolvedChildSchemaObject;
if (childSchemaObject.$type) {
const typeQName = splitQName(childSchemaObject.$type);
const typePrefix = typeQName.prefix;
const typeURI = schema.xmlns[typePrefix] || this.definitions.xmlns[typePrefix];
childNsURI = typeURI;
if (typeURI !== 'http://www.w3.org/2001/XMLSchema' && typePrefix !== TNS_PREFIX) {
// Add the prefix/namespace mapping, but not declare it
nsContext.addNamespace(typePrefix, typeURI);
}
resolvedChildSchemaObject =
this.findSchemaType(typeQName.name, typeURI) || childSchemaObject;
}
else {
resolvedChildSchemaObject =
this.findSchemaObject(childNsURI, childName) || childSchemaObject;
}
if (childSchemaObject.$baseNameSpace && this.options.ignoreBaseNameSpaces) {
childNsPrefix = nsPrefix;
childNsURI = nsURI;
}
if (this.options.ignoreBaseNameSpaces) {
childNsPrefix = '';
childNsURI = '';
}
ns = childNsPrefix;
if (Array.isArray(child)) {
// for arrays, we need to remember the current namespace
childNsPrefix = {
current: childNsPrefix,
parent: ns,
};
}
else {
// parent (array) already got the namespace
childXmlnsAttrib = null;
}
value = this.objectToXML(child, name, childNsPrefix, childNsURI, false, childXmlnsAttrib, resolvedChildSchemaObject, nsContext);
}
else if (obj[this.options.attributesKey] && obj[this.options.attributesKey].xsi_type) {
// if parent object has complex type defined and child not found in parent
const completeChildParamTypeObject = this.findChildSchemaObject(obj[this.options.attributesKey].xsi_type.type, obj[this.options.attributesKey].xsi_type.xmlns);
nonSubNameSpace = obj[this.options.attributesKey].xsi_type.prefix;
nsContext.addNamespace(obj[this.options.attributesKey].xsi_type.prefix, obj[this.options.attributesKey].xsi_type.xmlns);
value = this.objectToXML(child, name, obj[this.options.attributesKey].xsi_type.prefix, obj[this.options.attributesKey].xsi_type.xmlns, false, null, null, nsContext);
}
else {
if (Array.isArray(child)) {
if (emptyNonSubNameSpace) {
name = ':' + name;
}
else {
name = nonSubNameSpace + name;
}
// For arrays without schema, pass namespace information as object
const arrayNsPrefix = {
current: nonSubNameSpace || nsPrefix,
parent: ns || nsPrefix
};
value = this.objectToXML(child, name, arrayNsPrefix, nsURI, false, null, null, nsContext);
}
else {
value = this.objectToXML(child, name, nonSubNameSpace || nsPrefix, nsURI, false, null, null, nsContext);
}
}
}
else {
value = this.objectToXML(child, name, nonSubNameSpace || nsPrefix, nsURI, false, null, null, nsContext);
}
}
}
ns = noColonNameSpace(ns);
if (prefixNamespace && !qualified && isFirst && !this.options.overrideRootElement) {
ns = nsPrefix;
}
else if (this.isIgnoredNameSpace(ns)) {
ns = '';
}
const useEmptyTag = !value && this.options.useEmptyTag;
if (!Array.isArray(child)) {
// start tag
parts.push(['<', emptyNonSubNameSpace ? '' : appendColon(nonSubNameSpace || ns), name, attr, xmlnsAttrib,
(child === null ? ' xsi:nil="true"' : ''),
useEmptyTag ? ' />' : '>',
].join(''));
}
if (!useEmptyTag) {
parts.push(value);
if (!Array.isArray(child)) {
// end tag
parts.push(['</', emptyNonSubNameSpace ? '' : appendColon(nonSubNameSpace || ns), name, '>'].join(''));
}
}
}
}
else if (obj !== undefined) {
parts.push((this.options.escapeXML) ? xmlEscape(obj) : obj);
}
nsContext.popContext();
return parts.join('');
};
WSDL$1.prototype.processAttributes = function (child, nsContext) {
let attr = '';
if (child === null) {
child = [];
}
let attrObj = child[this.options.attributesKey];
if (attrObj && attrObj.xsi_type) {
let xsiType = attrObj.xsi_type;
let prefix = xsiType.prefix || xsiType.namespace;
// Generate a new namespace for complex extension if one not provided
if (!prefix) {
prefix = nsContext.registerNamespace(xsiType.xmlns);
}
else {
nsContext.declareNamespace(prefix, xsiType.xmlns);
}
xsiType.prefix = prefix;
}
if (attrObj) {
for (let attrKey in attrObj) {
//handle complex extension separately
if (attrKey === 'xsi_type') {
let attrValue = attrObj[attrKey];
attr += ' xsi:type="' + attrValue.prefix + ':' + attrValue.type + '"';
attr += ' xmlns:' + attrValue.prefix + '="' + attrValue.xmlns + '"';
continue;
}
else {
attr += ' ' + attrKey + '="' + xmlEscape(attrObj[attrKey]) + '"';
}
}
}
return attr;
};
/**
* Look up a schema type definition
* @param name
* @param nsURI
* @returns {*}
*/
WSDL$1.prototype.findSchemaType = function (name, nsURI) {
if (!this.definitions.schemas || !name || !nsURI) {
return null;
}
let schema = this.definitions.schemas[nsURI];
if (!schema || !schema.complexTypes) {
return null;
}
return schema.complexTypes[name];
};
WSDL$1.prototype.findChildSchemaObject = function (parameterTypeObj, childName, backtrace) {
if (!parameterTypeObj || !childName) {
return null;
}
if (!backtrace) {
backtrace = [];
}
if (backtrace.indexOf(parameterTypeObj) >= 0) {
// We've recursed back to ourselves; break.
return null;
}
else {
backtrace = backtrace.concat([parameterTypeObj]);
}
let found = null, i = 0, child, ref;
if (Array.isArray(parameterTypeObj.$lookupTypes) && parameterTypeObj.$lookupTypes.length) {
let types = parameterTypeObj.$lookupTypes;
for (i = 0; i < types.length; i++) {
let typeObj = types[i];
if (typeObj.$name === childName) {
found = typeObj;
break;
}
}
}
let object = parameterTypeObj;
if (object.$name === childName && object.name === 'element') {
return object;
}
if (object.$ref) {
ref = splitQName(object.$ref);
if (ref.name === childName) {
return object;
}
}
let childNsURI;
// want to avoid unecessary recursion to improve performance
if (object.$type && backtrace.length === 1) {
let typeInfo = splitQName(object.$type);
if (typeInfo.prefix === TNS_PREFIX) {
childNsURI = parameterTypeObj.$targetNamespace;
}
else {
childNsURI = this.definitions.xmlns[typeInfo.prefix];
}
let typeDef = this.findSchemaType(typeInfo.name, childNsURI);
if (typeDef) {
return this.findChildSchemaObject(typeDef, childName, backtrace);
}
}
if (object.children) {
for (i = 0, child; child = object.children[i]; i++) {
found = this.findChildSchemaObject(child, childName, backtrace);
if (found) {
break;
}
if (child.$base) {
let baseQName = splitQName(child.$base);
let childNameSpace = baseQName.prefix === TNS_PREFIX ? '' : baseQName.prefix;
childNsURI = child.xmlns[baseQName.prefix] || this.definitions.xmlns[baseQName.prefix];
let foundBase = this.findSchemaType(baseQName.name, childNsURI);
if (foundBase) {
found = this.findChildSchemaObject(foundBase, childName, backtrace);
if (found) {
// Clone the found object to prevent mutating the original schema
// This prevents state pollution between multiple requests
found = _.cloneDeep(found);
found.$baseNameSpace = childNameSpace;
found.$type = childNameSpace + ':' + childName;
break;
}
}
}
}
}
if (!found && object.$name === childName) {
return object;
}
return found;
};
WSDL$1.prototype._parse = function (xml) {
debug$1('Parsing WSDL XML, length: %d', xml?.length || 0);
let self = this, p = sax.parser(true), stack = [], root = null, types = null, schema = null, options = self.options;
p.onopentag = function (node) {
let nsName = node.name;
let attrs = node.attributes;
let top = stack[stack.length - 1];
let name;
if (top) {
try {
top.startElement(stack, nsName, attrs, options);
}
catch (e) {
if (self.options.strict) {
throw e;
}
else {
stack.push(new Element(nsName, attrs, options));
}
}
}
else {
name = splitQName(nsName).name;
if (name === 'definitions') {
root = new DefinitionsElement(nsName, attrs, options);
stack.push(root);
}
else if (name === 'schema') {
// Shim a structure in here to allow the proper objects to be created when merging back.
root = new DefinitionsElement('definitions', {}, {});
types = new TypesElement('types', {}, {});
schema = new SchemaElement(nsName, attrs, options);
types.addChild(schema);
root.addChild(types);
stack.push(schema);
}
else {
throw new Error('Unexpected root element of WSDL or include');
}
}
};
p.onclosetag = function (name) {
let top = stack[stack.length - 1];
ok(top, 'Unmatched close tag: ' + name);
top.endElement(stack, name);
};
p.write(xml).close();
return root;
};
WSDL$1.prototype._fromXML = function (xml) {
this.definitions = this._parse(xml);
this.definitions.descriptions = {
types: {}
};
this.xml = xml;
};
WSDL$1.prototype._fromServices = function (services) {
};
WSDL$1.prototype._xmlnsMap = function () {
let xmlns = this.definitions.xmlns;
let str = '';
for (let alias in xmlns) {
if (alias === '' || alias === TNS_PREFIX) {
continue;
}
let ns = xmlns[alias];
switch (ns) {
case "http://xml.apache.org/xml-soap": // apachesoap
case "http://schemas.xmlsoap.org/wsdl/": // wsdl
case "http://schemas.xmlsoap.org/wsdl/soap/": // wsdlsoap
case "http://schemas.xmlsoap.org/wsdl/soap12/": // wsdlsoap12
case "http://schemas.xmlsoap.org/soap/encoding/": // soapenc
case "http://www.w3.org/2001/XMLSchema": // xsd
continue;
}
if (~ns.indexOf('http://schemas.xmlsoap.org/')) {
continue;
}
if (~ns.indexOf('http://www.w3.org/')) {
continue;
}
if (~ns.indexOf('http://xml.apache.org/')) {
continue;
}
str += ' xmlns:' + alias + '="' + ns + '"';
}
return str;
};
/*
* Have another function to load previous WSDLs as we
* don't want this to be invoked externally (expect for tests)
* This will attempt to fix circular dependencies with XSD files,
* Given
* - file.wsdl
* - xs:import namespace="A" schemaLocation: A.xsd
* - A.xsd
* - xs:import namespace="B" schemaLocation: B.xsd
* - B.xsd
* - xs:import namespace="A" schemaLocation: A.xsd
* file.wsdl will start loading, import A, then A will import B, which will then import A
* Because A has already started to load previously it will be returned right away and
* have an internal circular reference
* B would then complete loading, then A, then file.wsdl
* By the time file A starts processing its includes its definitions will be already loaded,
* this is the only thing that B will depend on when "opening" A
*/
function open_wsdl_recursive(uri, options) {
let fromCache, WSDL_CACHE;
// if (typeof options === 'function') {
// callback = options;
// options = {};
// }
WSDL_CACHE = options.WSDL_CACHE;
if (fromCache = WSDL_CACHE[uri]) {
// return callback.call(fromCache, null, fromCache);
return fromCache;
}
return open_wsdl(uri, options);
}
async function open_wsdl(uri, options) {
// if (typeof options === 'function') {
// callback = options;
// options = {};
// }
// initialize cache when calling open_wsdl directly
let WSDL_CACHE = options.WSDL_CACHE || {};
let request_headers = options.wsdl_headers;
let request_options = options.wsdl_options;
// let wsdl;
// if (!/^https?:/.test(uri)) {
// // debug('Reading file: %s', uri);
// // fs.readFile(uri, 'utf8', function(err, definition) {
// // if (err) {
// // callback(err);
// // }
// // else {
// // wsdl = new WSDL(definition, uri, options);
// // WSDL_CACHE[ uri ] = wsdl;
// // wsdl.WSDL_CACHE = WSDL_CACHE;
// // wsdl.onReady(callback);
// // }
// // });
// }
// else {
// debug('Reading url: %s', uri);
// let httpClient = options.httpClient || new HttpClient(options);
// httpClient.request(uri, null /* options */, function(err, response, definition) {
// if (err) {
// callback(err);
// } else if (response && response.statusCode === 200) {
// wsdl = new WSDL(definition, uri, options);
// WSDL_CACHE[ uri ] = wsdl;
// wsdl.WSDL_CACHE = WSDL_CACHE;
// wsdl.onReady(callback);
// } else {
// callback(new Error('Invalid WSDL URL: ' + uri + "\n\n\r Code: " + response.statusCode + "\n\n\r Response Body: " + response.body));
// }
// }, request_headers, request_options);
// }
// return wsdl;
const httpClient = options.httpClient;
const wsdlDef = await httpClient.get(uri, { responseType: 'text' }).toPromise();
const wsdlObj = await new Promise((resolve) => {
const wsdl = new WSDL$1(wsdlDef, uri, options);
WSDL_CACHE[uri] = wsdl;
wsdl.WSDL_CACHE = WSDL_CACHE;
wsdl.onReady(resolve(wsdl));
});
return wsdlObj;
}
function BasicAuthSecurity$1(username, password, defaults) {
this._username = username;
this._password = password;
this.defaults = {};
_.merge(this.defaults, defaults);
}
BasicAuthSecurity$1.prototype.addHeaders = function (headers) {
headers.Authorization = 'Basic ' + new Buffer((this._username + ':' + this._password) || '').toString('base64');
};
BasicAuthSecurity$1.prototype.toXML = function () {
return '';
};
BasicAuthSecurity$1.prototype.addOptions = function (options) {
_.merge(options, this.defaults);
};
"use strict";
var validPasswordTypes = ['PasswordDigest', 'PasswordText'];
/**
* Generate a UUID using native crypto API with fallback for non-secure contexts
* Uses crypto.randomUUID() when available, with fallback for HTTP contexts
*/
function generateUUID$2() {
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID();
}
// Fallback for non-secure contexts (HTTP)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function generateId$1() {
return generateUUID$2().replace(/-/gm, '');
}
function WSSecurity$1(username, password, options) {
options = options || {};
this._username = username;
this._password = password;
//must account for backward compatibility for passwordType String param as well as object options defaults: passwordType = 'PasswordText', hasTimeStamp = true
if (typeof options === 'string') {
this._passwordType = options ? options : 'PasswordText';
options = {};
}
else {
this._passwordType = options.passwordType ? options.passwordType : 'PasswordText';
}
if (validPasswordTypes.indexOf(this._passwordType) === -1) {
this._passwordType = 'PasswordText';
}
this._hasTimeStamp = options.hasTimeStamp || typeof options.hasTimeStamp === 'boolean' ? !!options.hasTimeStamp : true;
/*jshint eqnull:true */
if (options.hasNonce != null) {
this._hasNonce = !!options.hasNonce;
}
this._hasTokenCreated = options.hasTokenCreated || typeof options.hasTokenCreated === 'boolean' ? !!options.hasTokenCreated : true;
if (options.actor != null) {
this._actor = options.actor;
}
if (options.mustUnderstand != null) {
this._mustUnderstand = !!options.mustUnderstand;
}
// Custom SOAP envelope prefix (e.g., 'SOAP-ENV', 'soapenv')
this._envelopeKey = options.envelopeKey || 'soap';
// Custom XML to append to security header (e.g., session tokens)
this._appendElement = options.appendElement || '';
}
WSSecurity$1.prototype.toXML = function () {
// avoid dependency on date formatting libraries
function getDate(d) {
function pad(n) {
return n < 10 ? '0' + n : n;
}
return d.getUTCFullYear() + '-'
+ pad(d.getUTCMonth() + 1) + '-'
+ pad(d.getUTCDate()) + 'T'
+ pad(d.getUTCHours()) + ':'
+ pad(d.getUTCMinutes()) + ':'
+ pad(d.getUTCSeconds()) + 'Z';
}
var now = new Date();
var created = getDate(now);
var timeStampXml = '';
if (this._hasTimeStamp) {
var expires = getDate(new Date(now.getTime() + (1000 * 600)));
// Use unique ID for timestamp (dynamic UUID generation)
var timestampId = 'Timestamp-' + generateId$1();
timeStampXml = "<wsu:Timestamp wsu:Id=\"" + timestampId + "\">" +
"<wsu:Created>" + created + "</wsu:Created>" +
"<wsu:Expires>" + expires + "</wsu:Expires>" +
"</wsu:Timestamp>";
}
var password, nonce;
if (this._hasNonce || this._passwordType !== 'PasswordText') {
// nonce = base64 ( sha1 ( created + random ) )
// var nHash = crypto.createHash('sha1');
// nHash.update(created + Math.random());
// nonce = nHash.digest('base64');
nonce = Base64.stringify(sha1(created + Math.random(), ''));
}
if (this._passwordType === 'PasswordText') {
password = "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" + this._password + "</wsse:Password>";
if (nonce) {
password += "<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + nonce + "</wsse:Nonce>";
}
}
else {
password = "<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + passwordDigest(nonce, created, this._password) + "</wsse:Password>" +
"<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + nonce + "</wsse:Nonce>";
}
// Proper spacing after xmlns attributes to prevent xmldom warnings
// Use envelopeKey for actor/mustUnderstand attributes
return "<wsse:Security " + (this._actor ? this._envelopeKey + ":actor=\"" + this._actor + "\" " : "") +
(this._mustUnderstand ? this._envelopeKey + ":mustUnderstand=\"1\" " : "") +
"xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" " +
"xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
timeStampXml +
"<wsse:UsernameToken xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" wsu:Id=\"SecurityToken-" + created + "\">" +
"<wsse:Username>" + this._username + "</wsse:Username>" +
password +
(this._hasTokenCreated ? "<wsu:Created>" + created + "</wsu:Created>" : "") +
"</wsse:UsernameToken>" +
this._appendElement +
"</wsse:Security>";
};
"use strict";
let wsseSecurityHeaderTemplate;
let wsseSecurityTokenTemplate;
function addMinutes(date, minutes) {
return new Date(date.getTime() + minutes * 60000);
}
function dateStringForSOAP(date) {
return date.getUTCFullYear() + '-' + ('0' + (date.getUTCMonth() + 1)).slice(-2) + '-' +
('0' + date.getUTCDate()).slice(-2) + 'T' + ('0' + date.getUTCHours()).slice(-2) + ":" +
('0' + date.getUTCMinutes()).slice(-2) + ":" + ('0' + date.getUTCSeconds()).slice(-2) + "Z";
}
function generateCreated() {
return dateStringForSOAP(new Date());
}
function generateExpires() {
return dateStringForSOAP(addMinutes(new Date(), 10));
}
function insertStr(src, dst, pos) {
return [dst.slice(0, pos), src, dst.slice(pos)].join('');
}
/**
* Generate a UUID using native crypto API with fallback for non-secure contexts
*/
function generateUUID$1() {
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID();
}
// Fallback for non-secure contexts (HTTP)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function generateId() {
return generateUUID$1().replace(/-/gm, '');
}
function WSSecurityCert(privatePEM, publicP12PEM, password, options) {
options = options || {};
this.publicP12PEM = publicP12PEM.toString().replace('-----BEGIN CERTIFICATE-----', '').replace('-----END CERTIFICATE-----', '').replace(/(\r\n|\n|\r)/gm, '');
// Store algorithm options
this.digestAlgorithm = options.digestAlgorithm || 'sha256';
this.signatureAlgorithm = options.signatureAlgorithm || 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
// Store reference exclusion options
this.excludeReferencesFromSigning = options.excludeReferencesFromSigning || [];
// Custom XML to append to security header (e.g., custom authentication elements)
this.appendElement = options.appendElement || '';
this.signer = new SignedXml();
this.signer.signatureAlgorithm = this.signatureAlgorithm;
this.signer.canonicalizationAlgorithm = 'http://www.w3.org/2001/10/xml-exc-c14n#';
this.signer.signingKey = {
key: privatePEM,
passphrase: password
};
this.x509Id = "x509-" + generateId();
var _this = this;
this.signer.keyInfoProvider = {};
this.signer.keyInfoProvider.getKeyInfo = function (key) {
if (!wsseSecurityTokenTemplate) {
// wsseSecurityTokenTemplate = ejs.compile(fs.readFileSync(path.join(__dirname, 'templates', 'wsse-security-token.ejs')).toString());
}
// return wsseSecurityTokenTemplate({ x509Id: _this.x509Id });
return `
<wsse:SecurityTokenReference>
<wsse:Reference URI="#${this.x509Id}" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
</wsse:SecurityTokenReference>
`;
};
}
WSSecurityCert.prototype.postProcess = function (xml, envelopeKey) {
this.created = generateCreated();
this.expires = generateExpires();
if (!wsseSecurityHeaderTemplate) {
// wsseSecurityHeaderTemplate = ejs.compile(fs.readFileSync(path.join(__dirname, 'templates', 'wsse-security-header.ejs')).toString());
}
// var secHeader = wsseSecurityHeaderTemplate({
// binaryToken: this.publicP12PEM,
// created: this.created,
// expires: this.expires,
// id: this.x509Id
// });
// Build security header with optional custom XML element
var secHeader = `
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
soap:mustUnderstand="1">
<wsse:BinarySecurityToken
EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
wsu:Id="${this.x509Id}">${this.publicP12PEM}</wsse:BinarySecurityToken>
<Timestamp xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="_1">
<Created>${this.created}</Created>
<Expires>${this.expires}</Expires>
</Timestamp>${this.appendElement}
</wsse:Security>
`;
var xmlWithSec = insertStr(secHeader, xml, xml.indexOf('</soap:Header>'));
var references = ["http://www.w3.org/2000/09/xmldsig#enveloped-signature",
"http://www.w3.org/2001/10/xml-exc-c14n#"];
// Add references conditionally based on excludeReferencesFromSigning option
const shouldExclude = (refName) => {
return this.excludeReferencesFromSigning &&
this.excludeReferencesFromSigning.some(excluded => refName.toLowerCase().includes(excluded.toLowerCase()));
};
// Use the configured digest algorithm for references
if (!shouldExclude('Body')) {
this.signer.addReference({
xpath: "//*[name(.)='" + envelopeKey + ":Body']",
transforms: references,
digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#' + this.digestAlgorithm
});
}
if (!shouldExclude('Timestamp')) {
this.signer.addReference({
xpath: "//*[name(.)='wsse:Security']/*[local-name(.)='Timestamp']",
transforms: references,
digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#' + this.digestAlgorithm
});
}
this.signer.computeSignature(xmlWithSec);
return insertStr(this.signer.getSignatureXml(), xmlWithSec, xmlWithSec.indexOf('</wsse:Security>'));
};
"use strict";
/**
* WS-Security with both certificate and username token
* Combines WSSecurityCert with UsernameToken for dual authentication
*
* @param privatePEM - Private key in PEM format
* @param publicP12PEM - Public certificate in P12/PEM format
* @param password - Certificate password
* @param options - Additional options
* @param options.username - Username for token authentication
* @param options.password - Password for token authentication
* @param options.passwordType - Type of password encoding ('PasswordText' or 'PasswordDigest')
* @param options.hasTimeStamp - Include timestamp in security header (default: true)
* @param options.hasNonce - Include nonce in security header
* @param options.hasTokenCreated - Include created timestamp in token (default: true)
* @param options.digestAlgorithm - Digest algorithm for signing (default: 'sha256')
* @param options.signatureAlgorithm - Signature algorithm for signing
* @param options.excludeReferencesFromSigning - Array of element names to exclude from signing
* @param options.appendElement - Custom XML to append to security header
* @param options.envelopeKey - Custom SOAP envelope prefix (default: 'soap')
*/
function WSSecurityCertWithToken(privatePEM, publicP12PEM, password, options) {
options = options || {};
// Initialize certificate security with all supported options
this.cert = new WSSecurityCert(privatePEM, publicP12PEM, password, {
digestAlgorithm: options.digestAlgorithm,
signatureAlgorithm: options.signatureAlgorithm,
excludeReferencesFromSigning: options.excludeReferencesFromSigning,
appendElement: options.appendElement
});
// Initialize username token security with all supported options
if (options.username && options.password) {
this.token = new WSSecurity$1(options.username, options.password, {
passwordType: options.passwordType,
hasTimeStamp: options.hasTimeStamp,
hasNonce: options.hasNonce,
hasTokenCreated: options.hasTokenCreated,
actor: options.actor,
mustUnderstand: options.mustUnderstand,
envelopeKey: options.envelopeKey,
appendElement: options.appendElement
});
}
}
/**
* Generate the WS-Security XML header
* Returns username token XML (certificate is added via postProcess)
*/
WSSecurityCertWithToken.prototype.toXML = function () {
// Only return username token if provided
// Certificate security is handled via postProcess
if (this.token) {
return this.token.toXML();
}
return '';
};
/**
* Post-process the SOAP envelope to add signature
*/
WSSecurityCertWithToken.prototype.postProcess = function (xml, envelopeKey) {
if (this.cert && this.cert.postProcess) {
return this.cert.postProcess(xml, envelopeKey);
}
return xml;
};
/**
* Add additional options to the security configuration
*/
WSSecurityCertWithToken.prototype.addOptions = function (options) {
if (this.token && options.username) {
this.token._username = options.username;
}
if (this.token && options.password) {
this.token._password = options.password;
}
};
"use strict";
/**
* Combined WSSecurity and WSSecurityCert
* Allows using both username token and certificate security together
*
* @param wsSecurity - WSSecurity instance for username token
* @param wsSecurityCert - WSSecurityCert instance for certificate
*/
function WSSecurityPlusCert(wsSecurity, wsSecurityCert) {
if (!wsSecurity) {
throw new Error('WSSecurity instance is required');
}
if (!wsSecurityCert) {
throw new Error('WSSecurityCert instance is required');
}
this.wsSecurity = wsSecurity;
this.wsSecurityCert = wsSecurityCert;
}
/**
* Generate the WS-Security XML header
* Returns username token XML (certificate is added via postProcess)
*/
WSSecurityPlusCert.prototype.toXML = function () {
// Only return WSSecurity (username token)
// Certificate security is handled via postProcess
if (this.wsSecurity && this.wsSecurity.toXML) {
return this.wsSecurity.toXML();
}
return '';
};
/**
* Post-process the SOAP envelope to add signature
*/
WSSecurityPlusCert.prototype.postProcess = function (xml, envelopeKey) {
// Apply certificate post-processing if available
if (this.wsSecurityCert && this.wsSecurityCert.postProcess) {
return this.wsSecurityCert.postProcess(xml, envelopeKey);
}
return xml;
};
/**
* Add additional options to both security configurations
*/
WSSecurityPlusCert.prototype.addOptions = function (options) {
if (this.wsSecurity && options.username) {
this.wsSecurity._username = options.username;
}
if (this.wsSecurity && options.password) {
this.wsSecurity._password = options.password;
}
};
"use strict";
function BearerSecurity$1(token, defaults) {
this._token = token;
this.defaults = {};
_.merge(this.defaults, defaults);
}
BearerSecurity$1.prototype.addHeaders = function (headers) {
headers.Authorization = "Bearer " + this._token;
};
BearerSecurity$1.prototype.toXML = function () {
return '';
};
BearerSecurity$1.prototype.addOptions = function (options) {
_.merge(options, this.defaults);
};
"use strict";
function NTLMSecurity$1(username, password, domain, workstation) {
if (typeof username === "object") {
this.defaults = username;
this.defaults.ntlm = true;
}
else {
this.defaults = {
ntlm: true,
username: username,
password: password,
domain: domain,
workstation: workstation
};
}
}
NTLMSecurity$1.prototype.addHeaders = function (headers) {
headers.Connection = 'keep-alive';
};
NTLMSecurity$1.prototype.toXML = function () {
return '';
};
NTLMSecurity$1.prototype.addOptions = function (options) {
_.merge(options, this.defaults);
};
"use strict";
const security = {
BasicAuthSecurity: BasicAuthSecurity$1,
BearerSecurity: BearerSecurity$1,
WSSecurity: WSSecurity$1,
WSSecurityCert,
WSSecurityCertWithToken,
WSSecurityPlusCert,
NTLMSecurity: NTLMSecurity$1,
// ClientSSLSecurity,
// ClientSSLSecurityPFX
};
class Multipart {
constructor() {
this.preambleCRLF = true;
this.postambleCRLF = true;
}
build(parts, boundary) {
const body = [];
function add(part) {
if (typeof part === 'number') {
part = part.toString();
}
return body.push(part);
}
if (this.preambleCRLF) {
add('\r\n');
}
parts.forEach(function (part) {
let preamble = '--' + boundary + '\r\n';
Object.keys(part).forEach(function (key) {
if (key === 'body') {
return;
}
preamble += key + ': ' + part[key] + '\r\n';
});
preamble += '\r\n';
add(preamble);
add(part.body);
add('\r\n');
});
add('--' + boundary + '--');
if (this.postambleCRLF) {
add('\r\n');
}
const size = body.map((part) => {
if (typeof part === 'string') {
return part.length;
}
else {
return part.byteLength;
}
}).reduce((a, b) => a + b, 0);
let uint8array = new Uint8Array(size);
let i = 0;
body.forEach((part) => {
if (typeof part === 'string') {
for (let j = 0; j < part.length; i++, j++) {
uint8array[i] = part.charCodeAt(j) & 0xff;
}
}
else {
for (let j = 0; j < part.byteLength; i++, j++) {
uint8array[i] = part[j];
}
}
});
return uint8array.buffer;
}
}
class SoapAttachment {
constructor(mimetype, contentId, name, body) {
this.mimetype = mimetype;
this.contentId = contentId;
this.name = name;
this.body = body;
}
static fromFormFiles(files = []) {
if (files instanceof FileList) {
files = Array.from(files);
}
const promises = files.map((file) => {
return new Promise(function (resolve) {
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (e) {
const arrayBuffer = e.target.result;
const bytes = new Uint8Array(arrayBuffer);
const attachment = new SoapAttachment(file.type, file.contentId || file.name, file.name, bytes);
resolve(attachment);
};
});
});
return Promise.all(promises);
}
}
/*
* Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
* MIT Licensed
*/
const debug = debugBuilder('ngx-soap:client');
const nonIdentifierChars = /[^a-z$_0-9]/i;
/**
* Generate a UUID using native crypto API with fallback for non-secure contexts
*/
function generateUUID() {
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID();
}
// Fallback for non-secure contexts (HTTP)
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
const Client = function (wsdl, endpoint, options) {
options = options || {};
this.wsdl = wsdl;
this._initializeOptions(options);
this._initializeServices(endpoint);
this.httpClient = options.httpClient;
const promiseOptions = { multiArgs: true };
if (options.overridePromiseSuffix) {
promiseOptions.suffix = options.overridePromiseSuffix;
}
Promise.all([this, promiseOptions]);
};
Client.prototype._processSoapHeader = function (soapHeader, name, namespace, xmlns) {
switch (typeof soapHeader) {
case 'object':
return this.wsdl.objectToXML(soapHeader, name, namespace, xmlns, true);
case 'function':
const self = this;
return function () {
const result = soapHeader.apply(null, arguments);
if (typeof result === 'object') {
return self.wsdl.objectToXML(result, name, namespace, xmlns, true);
}
return result;
};
default:
return soapHeader;
}
};
Client.prototype.addSoapHeader = function (soapHeader, name, namespace, xmlns) {
if (!this.soapHeaders) {
this.soapHeaders = [];
}
soapHeader = this._processSoapHeader(soapHeader, name, namespace, xmlns);
return this.soapHeaders.push(soapHeader) - 1;
};
Client.prototype.changeSoapHeader = function (index, soapHeader, name, namespace, xmlns) {
if (!this.soapHeaders) {
this.soapHeaders = [];
}
soapHeader = this._processSoapHeader(soapHeader, name, namespace, xmlns);
this.soapHeaders[index] = soapHeader;
};
Client.prototype.getSoapHeaders = function () {
return this.soapHeaders;
};
Client.prototype.clearSoapHeaders = function () {
this.soapHeaders = null;
};
Client.prototype.addHttpHeader = function (name, value) {
if (!this.httpHeaders) {
this.httpHeaders = {};
}
this.httpHeaders[name] = value;
};
Client.prototype.getHttpHeaders = function () {
return this.httpHeaders;
};
Client.prototype.clearHttpHeaders = function () {
this.httpHeaders = {};
};
Client.prototype.addBodyAttribute = function (bodyAttribute, name, namespace, xmlns) {
if (!this.bodyAttributes) {
this.bodyAttributes = [];
}
if (typeof bodyAttribute === 'object') {
let composition = '';
Object.getOwnPropertyNames(bodyAttribute).forEach(function (prop, idx, array) {
composition += ' ' + prop + '="' + bodyAttribute[prop] + '"';
});
bodyAttribute = composition;
}
if (bodyAttribute.substr(0, 1) !== ' ')
bodyAttribute = ' ' + bodyAttribute;
this.bodyAttributes.push(bodyAttribute);
};
Client.prototype.getBodyAttributes = function () {
return this.bodyAttributes;
};
Client.prototype.clearBodyAttributes = function () {
this.bodyAttributes = null;
};
Client.prototype.setEndpoint = function (endpoint) {
this.endpoint = endpoint;
this._initializeServices(endpoint);
};
Client.prototype.describe = function () {
const types = this.wsdl.definitions.types;
return this.wsdl.describeServices();
};
Client.prototype.setSecurity = function (security) {
this.security = security;
};
Client.prototype.setSOAPAction = function (SOAPAction) {
this.SOAPAction = SOAPAction;
};
Client.prototype._initializeServices = function (endpoint) {
const definitions = this.wsdl.definitions, services = definitions.services;
// Support selecting specific service from WSDL
const selectedServiceName = this.wsdl.options.serviceName;
if (selectedServiceName) {
// Initialize only the selected service
if (services[selectedServiceName]) {
this[selectedServiceName] = this._defineService(services[selectedServiceName], endpoint);
debug('Initialized selected service: %s', selectedServiceName);
}
else {
debug('Warning: Selected service "%s" not found in WSDL. Available services: %s', selectedServiceName, Object.keys(services).join(', '));
}
}
else {
// Initialize all services (backward compatible)
for (const name in services) {
this[name] = this._defineService(services[name], endpoint);
}
}
};
Client.prototype._initializeOptions = function (options) {
this.streamAllowed = options.stream;
this.normalizeNames = options.normalizeNames;
this.wsdl.options.attributesKey = options.attributesKey || 'attributes';
this.wsdl.options.envelopeKey = options.envelopeKey || 'soap';
this.wsdl.options.preserveWhitespace = !!options.preserveWhitespace;
// Support selecting specific service/port from WSDL
this.wsdl.options.serviceName = options.serviceName;
this.wsdl.options.portName = options.portName;
if (options.ignoredNamespaces !== undefined) {
if (options.ignoredNamespaces.override !== undefined) {
if (options.ignoredNamespaces.override === true) {
if (options.ignoredNamespaces.namespaces !== undefined) {
this.wsdl.options.ignoredNamespaces = options.ignoredNamespaces.namespaces;
}
}
}
}
if (options.overrideRootElement !== undefined) {
this.wsdl.options.overrideRootElement = options.overrideRootElement;
}
this.wsdl.options.forceSoap12Headers = !!options.forceSoap12Headers;
};
Client.prototype._defineService = function (service, endpoint) {
const ports = service.ports, def = {};
// Support selecting specific port from service
const selectedPortName = this.wsdl.options.portName;
if (selectedPortName) {
// Initialize only the selected port
if (ports[selectedPortName]) {
def[selectedPortName] = this._definePort(ports[selectedPortName], endpoint ? endpoint : ports[selectedPortName].location);
debug('Initialized selected port: %s', selectedPortName);
}
else {
debug('Warning: Selected port "%s" not found in service. Available ports: %s', selectedPortName, Object.keys(ports).join(', '));
}
}
else {
// Initialize all ports (backward compatible)
for (const name in ports) {
def[name] = this._definePort(ports[name], endpoint ? endpoint : ports[name].location);
}
}
return def;
};
Client.prototype._definePort = function (port, endpoint) {
const location = endpoint, binding = port.binding, methods = binding.methods, def = {};
for (const name in methods) {
def[name] = this._defineMethod(methods[name], location);
const methodName = this.normalizeNames ? name.replace(nonIdentifierChars, '_') : name;
this[methodName] = def[name];
}
return def;
};
Client.prototype._defineMethod = function (method, location) {
const self = this;
let temp = null;
return function (args, options, extraHeaders) {
return self._invoke(method, args, location, options, extraHeaders);
};
};
Client.prototype._invoke = function (method, args, location, options, extraHeaders) {
// Ensure options is defined
options = options || {};
// Generate or use provided exchange ID for request tracking
const eid = options.exchangeId || generateUUID();
debug('Invoking SOAP method: %s (EID: %s)', method.$name, eid);
let self = this, name = method.$name, input = method.input, output = method.output, style = method.style, defs = this.wsdl.definitions, envelopeKey = this.wsdl.options.envelopeKey, ns = defs.$targetNamespace, encoding = '', message = '', xml = null, req = null, soapAction = null, alias = findPrefix$1(defs.xmlns, ns), headers = {
'Content-Type': 'text/xml; charset=utf-8'
}, xmlnsSoap = 'xmlns:' + envelopeKey + '="http://schemas.xmlsoap.org/soap/envelope/"';
// Support custom SOAP envelope URL
if (this.wsdl.options.envelopeSoapUrl && !this.wsdl.options.forceSoap12Headers) {
xmlnsSoap = 'xmlns:' + envelopeKey + '="' + this.wsdl.options.envelopeSoapUrl + '"';
}
if (this.wsdl.options.forceSoap12Headers) {
headers['Content-Type'] = 'application/soap+xml; charset=utf-8';
xmlnsSoap = 'xmlns:' + envelopeKey + '="http://www.w3.org/2003/05/soap-envelope"';
}
if (this.SOAPAction) {
soapAction = this.SOAPAction;
}
else if (method.soapAction !== undefined && method.soapAction !== null) {
soapAction = method.soapAction;
}
else {
soapAction = (ns.lastIndexOf('/') !== ns.length - 1 ? ns + '/' : ns) + name;
}
if (!this.wsdl.options.forceSoap12Headers) {
headers.SOAPAction = '"' + soapAction + '"';
}
options = options || {};
//Add extra headers
for (const header in this.httpHeaders) {
headers[header] = this.httpHeaders[header];
}
for (const attr in extraHeaders) {
headers[attr] = extraHeaders[attr];
}
// Allow the security object to add headers
if (self.security && self.security.addHeaders)
self.security.addHeaders(headers);
if (self.security && self.security.addOptions)
self.security.addOptions(options);
if (style === 'rpc' && (input.parts || input.name === 'element' || args === null)) {
assert.ok(!style || style === 'rpc', 'invalid message definition for document style binding');
message = self.wsdl.objectToRpcXML(name, args, alias, ns, input.name !== 'element');
method.inputSoap === 'encoded' && (encoding = 'soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" ');
}
else {
assert.ok(!style || style === 'document', 'invalid message definition for rpc style binding');
// pass `input.$lookupType` if `input.$type` could not be found
message = self.wsdl.objectToDocumentXML(input.$name, args, input.targetNSAlias, input.targetNamespace, input.$type || input.$lookupType);
}
xml =
'<?xml version="1.0" encoding="utf-8"?>' +
'<' +
envelopeKey +
':Envelope ' +
xmlnsSoap +
' ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
encoding +
this.wsdl.xmlnsInEnvelope +
'>' +
(self.soapHeaders || self.security
? '<' +
envelopeKey +
':Header>' +
(self.soapHeaders ? self.soapHeaders.join('\n') : '') +
(self.security && !self.security.postProcess ? self.security.toXML() : '') +
'</' +
envelopeKey +
':Header>'
: '') +
'<' +
envelopeKey +
':Body' +
(self.bodyAttributes ? self.bodyAttributes.join(' ') : '') +
(self.security && self.security.postProcess ? ' Id="_0"' : '') +
'>' +
message +
'</' +
envelopeKey +
':Body>' +
'</' +
envelopeKey +
':Envelope>';
if (self.security && self.security.postProcess) {
xml = self.security.postProcess(xml, envelopeKey);
}
if (options && options.postProcess) {
xml = options.postProcess(xml);
}
self.lastMessage = message;
self.lastRequest = xml;
self.lastEndpoint = location;
const tryJSONparse = function (body) {
try {
return JSON.parse(body);
}
catch (err) {
return undefined;
}
};
return from(SoapAttachment.fromFormFiles(options.attachments)).pipe(map((soapAttachments) => {
if (!soapAttachments.length) {
return xml;
}
if (options.forceMTOM || soapAttachments.length > 0) {
const start = generateUUID();
const boundry = generateUUID();
let action = null;
if (headers['Content-Type'].indexOf('action') > -1) {
for (const ct of headers['Content-Type'].split('; ')) {
if (ct.indexOf('action') > -1) {
action = ct;
}
}
}
headers['Content-Type'] =
'multipart/related; type="application/xop+xml"; start="<' + start + '>"; start-info="text/xml"; boundary="' + boundry + '"';
if (action) {
headers['Content-Type'] = headers['Content-Type'] + '; ' + action;
}
const multipart = [
{
'Content-Type': 'application/xop+xml; charset=UTF-8; type="text/xml"',
'Content-ID': '<' + start + '>',
body: xml
}
];
soapAttachments.forEach((attachment) => {
multipart.push({
'Content-Type': attachment.mimetype + ';',
'Content-Transfer-Encoding': 'binary',
'Content-ID': '<' + (attachment.contentId || attachment.name) + '>',
'Content-Disposition': 'attachment; name="' + attachment.name + '"; filename="' + attachment.name + '"',
body: attachment.body
});
});
return new Multipart().build(multipart, boundry);
}
}), mergeMap((body) => (self.httpClient)
.post(location, body, {
headers: headers,
responseType: 'text',
observe: 'response'
})
.pipe(map((response) => {
self.lastResponse = response.body;
self.lastResponseHeaders = response && response.headers;
return parseSync(response.body, response);
}))));
function parseSync(body, response) {
// Handle empty or null body
if (!body || typeof body !== 'string' || body.trim().length === 0) {
debug('Received empty SOAP body');
if (!output) {
// One-way operation, no response expected
return { err: null, response: null, responseBody: body, header: undefined, xml };
}
return { err: null, result: {}, responseBody: body, header: undefined, xml };
}
let obj;
try {
obj = self.wsdl.xmlToObject(body);
}
catch (error) {
// When the output element cannot be looked up in the wsdl and the body is JSON
// instead of sending the error, we pass the body in the response.
if (!output || !output.$lookupTypes) {
// debug('Response element is not present. Unable to convert response xml to json.');
// If the response is JSON then return it as-is.
const json = _.isObject(body) ? body : tryJSONparse(body);
if (json) {
return { err: null, response, responseBody: json, header: undefined, xml };
}
}
error.response = response;
error.body = body;
// self.emit('soapError', error, eid);
throw error;
}
return finish(obj, body, response);
}
function finish(obj, responseBody, response) {
let result = null;
if (!output) {
// one-way, no output expected
return { err: null, response: null, responseBody, header: obj.Header, xml };
}
// If it's not HTML and Soap Body is empty
if (!obj.html && !obj.Body) {
return { err: null, obj, responseBody, header: obj.Header, xml };
}
if (typeof obj.Body !== 'object') {
const error = new Error('Cannot parse response');
error.response = response;
error.body = responseBody;
return { err: error, obj, responseBody, header: undefined, xml };
}
result = obj.Body[output.$name];
// RPC/literal response body may contain elements with added suffixes I.E.
// 'Response', or 'Output', or 'Out'
// This doesn't necessarily equal the ouput message name. See WSDL 1.1 Section 2.4.5
if (!result) {
result = obj.Body[output.$name.replace(/(?:Out(?:put)?|Response)$/, '')];
}
if (!result) {
['Response', 'Out', 'Output'].forEach(function (term) {
if (obj.Body.hasOwnProperty(name + term)) {
return (result = obj.Body[name + term]);
}
});
}
return { err: null, result, responseBody, header: obj.Header, xml };
}
};
Client.prototype.call = function (method, body, options, extraHeaders) {
if (!this[method]) {
return throwError(`Method ${method} not found`);
}
return this[method].call(this, body, options, extraHeaders);
};
/*
* Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
* MIT Licensed
*/
const WSDL = WSDL$1;
const cache = {}; // TODO some caching?
const getFromCache = async (url, options) => {
if (cache[url]) {
return cache[url];
}
else {
return open_wsdl(url, options).then(wsdl => {
cache[url] = wsdl;
return wsdl;
});
}
};
async function _requestWSDL(url, options) {
if (options.disableCache === true) {
return open_wsdl(url, options);
}
else {
return getFromCache(url, options);
}
}
async function createClient(url, options, endpoint) {
if (typeof options === 'undefined') {
options = {};
}
endpoint = options.endpoint || endpoint;
const wsdl = await _requestWSDL(url, options);
const client = new Client(wsdl, endpoint, options);
return client;
}
const BasicAuthSecurity = security.BasicAuthSecurity;
const NTLMSecurity = security.NTLMSecurity;
const WSSecurity = security.WSSecurity;
// export const WSSecurityCert = security.WSSecurityCert;
const BearerSecurity = security.BearerSecurity;
// export const ClientSSLSecurity = security.ClientSSLSecurity;
// export const ClientSSLSecurityPFX = security.ClientSSLSecurityPFX;
/**
* NgxSoapService - SOAP client service for Angular
*
* **Backwards Compatible:** Works with Angular 10+ (NgModule or standalone)
*
* This service creates SOAP clients from WSDL files and returns Promises for compatibility.
* The returned Promise can be wrapped in Angular 20+ resource() or used directly.
*
* @example Basic usage (works in all Angular versions)
* ```typescript
* constructor(private soap: NgxSoapService) {
* this.soap.createClient('assets/service.wsdl')
* .then(client => this.client = client)
* .catch(err => console.error(err));
* }
* ```
*
* @example Angular 20+ with resource() API
* ```typescript
* import { inject, resource } from '@angular/core';
*
* private soap = inject(NgxSoapService);
*
* soapClient = resource({
* loader: () => this.soap.createClient('assets/service.wsdl')
* });
* ```
*
* @example Angular 16+ with signals
* ```typescript
* import { inject, signal } from '@angular/core';
*
* private soap = inject(NgxSoapService);
* client = signal<Client | null>(null);
*
* constructor() {
* this.soap.createClient('assets/service.wsdl')
* .then(client => this.client.set(client));
* }
* ```
*
* @since 0.10.0
*/
class NgxSoapService {
constructor(http) {
this.http = http;
}
/**
* Creates a SOAP client from a WSDL URL
*
* @param wsdlUrl - URL to the WSDL file (can be relative or absolute)
* @param options - Optional SOAP client configuration options
* @param endpoint - Optional endpoint override (overrides WSDL endpoint)
* @returns Promise that resolves to a SOAP Client
*
* @example
* ```typescript
* const client = await this.soap.createClient('assets/calculator.wsdl');
* (client as any).Add({ intA: 1, intB: 2 }).subscribe(result => {
* console.log(result.AddResult);
* });
* ```
*/
createClient(wsdlUrl, options = {}, endpoint) {
options.httpClient = this.http;
return createClient(wsdlUrl, options, endpoint);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.HttpClient }] });
/**
* Provides NgxSoap services for standalone applications (Angular 14+)
*
* **Recommended for Angular 14+ standalone applications**
*
* This is the modern approach for Angular 14+ projects using standalone components.
* Works seamlessly with Angular 20 features like signals, computed(), and resource().
*
* @example
* ```typescript
* import { bootstrapApplication } from '@angular/platform-browser';
* import { provideHttpClient } from '@angular/common/http';
* import { provideNgxSoap } from 'ngx-soap-next';
*
* bootstrapApplication(AppComponent, {
* providers: [
* provideHttpClient(),
* provideNgxSoap()
* ]
* });
* ```
*
* @since 0.17.0 (Angular 14+)
*/
function provideNgxSoap() {
return makeEnvironmentProviders([
NgxSoapService
]);
}
/**
* NgxSoapModule for traditional NgModule-based applications
*
* **Fully supported for NgModule-based applications (Angular 10+)**
*
* Use this module in traditional NgModule-based Angular applications.
* Both NgModule and standalone approaches are fully supported for backwards compatibility.
*
* For new standalone applications, consider using `provideNgxSoap()` instead.
*
* @example NgModule-based application
* ```typescript
* import { NgModule } from '@angular/core';
* import { NgxSoapModule } from 'ngx-soap-next';
* import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
*
* @NgModule({
* imports: [NgxSoapModule],
* // Or provide HttpClient separately:
* // providers: [provideHttpClient(withInterceptorsFromDi())]
* })
* export class AppModule { }
* ```
*
* @since 0.10.0 (Angular 10+)
*/
class NgxSoapModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapModule }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapModule, providers: [
NgxSoapService,
provideHttpClient(withInterceptorsFromDi())
] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NgxSoapModule, decorators: [{
type: NgModule,
args: [{
exports: [],
imports: [],
providers: [
NgxSoapService,
provideHttpClient(withInterceptorsFromDi())
]
}]
}] });
/*
* Public API Surface of ngx-soap
*/
/**
* Generated bundle index. Do not edit.
*/
export { NgxSoapModule, NgxSoapService, provideNgxSoap, security };
//# sourceMappingURL=ngx-soap-next.mjs.map