Skip to content

Commit

Permalink
feat: new parameter --useWsdlTypeNames to generate interface names fr…
Browse files Browse the repository at this point in the history
…om wsdl type names
  • Loading branch information
doubleaxe committed Jan 6, 2025
1 parent 16ff043 commit 2ce05f0
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 12 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Options:
'PascalCase') [string]
--caseInsensitiveNames Parse WSDL definitions case-insensitively
[boolean]
--useWsdlTypeNames Use wsdl schema type names instead of
parameter names for generated interface
names [boolean]
--maxRecursiveDefinitionName Maximum count of definitions with the same
name but increased suffix. Will throw an
error if exceeded. [number]
Expand Down
11 changes: 10 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ const conf = yargs(process.argv.slice(2))
type: "boolean",
description: "Parse WSDL definitions case-insensitively",
})
.option("useWsdlTypeNames", {
type: "boolean",
description: "Use wsdl schema type names instead of parameter names for generated interface names",
})
.option("maxRecursiveDefinitionName", {
type: "number",
description:
Expand All @@ -59,7 +63,8 @@ const conf = yargs(process.argv.slice(2))
.option("no-color", {
type: "boolean",
description: "Logs without colors",
}).parseSync();
})
.parseSync();

// Logger section

Expand Down Expand Up @@ -123,6 +128,10 @@ if (conf.caseInsensitiveNames) {
options.caseInsensitiveNames = conf.caseInsensitiveNames;
}

if (conf.useWsdlTypeNames) {
options.useWsdlTypeNames = conf.useWsdlTypeNames;
}

if (conf.esm) {
options.esm = conf.esm;
}
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export interface Options {
* @default false
*/
caseInsensitiveNames: boolean;
/**
* Use wsdl schema type names instead of parameter names for generated interface names
* @default false
*/
useWsdlTypeNames: boolean;
/**
* Maximum count of definition's with same name but increased suffix. Will throw an error if exceed
* @default 64
Expand All @@ -44,7 +49,7 @@ export interface Options {
/**
* Generate imports with .js suffix
*/
esm: boolean
esm: boolean;
/**
* Print verbose logs
* @default false
Expand All @@ -67,6 +72,7 @@ export const defaultOptions: Options = {
modelNamePreffix: "",
modelNameSuffix: "",
caseInsensitiveNames: false,
useWsdlTypeNames: false,
maxRecursiveDefinitionName: 64,
modelPropertyNaming: null,
esm: false,
Expand Down
112 changes: 102 additions & 10 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import * as path from "path";
import { ComplexTypeElement } from "soap/lib/wsdl/elements";
import {
AllElement,
ChoiceElement,
ComplexContentElement,
ComplexTypeElement,
DefinitionsElement,
ElementElement,
ExtensionElement,
SequenceElement,
SimpleContentElement,
SimpleTypeElement,
} from "soap/lib/wsdl/elements";
import { splitQName } from "soap/lib/utils";
import { open_wsdl } from "soap/lib/wsdl/index";
import { Definition, Method, ParsedWsdl, Port, Service } from "./models/parsed-wsdl";
import { changeCase } from "./utils/change-case";
Expand All @@ -12,13 +24,15 @@ interface ParserOptions {
modelNameSuffix: string;
maxRecursiveDefinitionName: number;
caseInsensitiveNames: boolean;
useWsdlTypeNames: boolean;
}

const defaultOptions: ParserOptions = {
modelNamePreffix: "",
modelNameSuffix: "",
maxRecursiveDefinitionName: 64,
caseInsensitiveNames: false,
useWsdlTypeNames: false,
};

type VisitedDefinition = {
Expand Down Expand Up @@ -53,6 +67,60 @@ function toPrimitiveType(type: string): string {
return NODE_SOAP_PARSED_TYPES[type] || "string";
}

type ElementSchema = ElementElement | ComplexTypeElement | SimpleTypeElement;

function findElementSchemaType(definitions: DefinitionsElement, element: ElementSchema) {
if (!("$type" in element) && !("$ref" in element)) return element;
const type = element.$type || element.$ref;
if (!type) return element;
const { prefix, name: localName } = splitQName(type);
const ns = element.schemaXmlns[prefix] ?? definitions.xmlns[prefix] ?? definitions.xmlns[element.targetNSAlias];
const schema = definitions.schemas[ns];
if (!schema) return element;
const typeElement = schema.complexTypes[localName] ?? schema.types[localName];
return typeElement;
}

function findPropSchemaType(
definitions: DefinitionsElement,
parentElement: ElementSchema | undefined,
propName: string
): ElementSchema | undefined {
if (!parentElement?.children) return undefined;
for (const child of parentElement.children) {
if (
child instanceof ChoiceElement ||
child instanceof SequenceElement ||
child instanceof AllElement ||
child instanceof SimpleContentElement ||
child instanceof ComplexContentElement ||
child instanceof ExtensionElement
) {
return findPropSchemaType(definitions, child, propName);
}
if (child.$name === propName) {
if (
child instanceof ElementElement ||
child instanceof ComplexTypeElement ||
child instanceof SimpleTypeElement
) {
return findElementSchemaType(definitions, child);
}
}
}
return undefined;
}

function getNamefromSchema(element: ElementSchema | undefined) {
if (!element) return undefined;
if ("$type" in element || "$ref" in element) {
const type = element.$type || element.$ref;
const { name: localName } = splitQName(type);
return localName;
}
return element.$name;
}

/**
* parse definition
* @param parsedWsdl context of parsed wsdl
Expand All @@ -67,7 +135,9 @@ function parseDefinition(
name: string,
defParts: { [propNameType: string]: any },
stack: string[],
visitedDefs: Array<VisitedDefinition>
visitedDefs: Array<VisitedDefinition>,
definitions: DefinitionsElement,
schema: ElementSchema | undefined
): Definition {
const defName = changeCase(name, { pascalCase: true });

Expand Down Expand Up @@ -146,13 +216,17 @@ function parseDefinition(
});
} else {
try {
const propSchema = findPropSchemaType(definitions, schema, stripedPropName);
const guessPropName = getNamefromSchema(propSchema) ?? stripedPropName;
const subDefinition = parseDefinition(
parsedWsdl,
options,
stripedPropName,
guessPropName,
type,
[...stack, propName],
visitedDefs
visitedDefs,
definitions,
propSchema
);
definition.properties.push({
kind: "REFERENCE",
Expand Down Expand Up @@ -205,13 +279,17 @@ function parseDefinition(
});
} else {
try {
const propSchema = findPropSchemaType(definitions, schema, propName);
const guessPropName = getNamefromSchema(propSchema) ?? propName;
const subDefinition = parseDefinition(
parsedWsdl,
options,
propName,
guessPropName,
type,
[...stack, propName],
visitedDefs
visitedDefs,
definitions,
propSchema
);
definition.properties.push({
kind: "REFERENCE",
Expand Down Expand Up @@ -300,6 +378,9 @@ export async function parseWsdl(wsdlPath: string, options: Partial<ParserOptions
const type = parsedWsdl.findDefinition(
inputMessage.element.$type ?? inputMessage.element.$name
);
const schema = mergedOptions.useWsdlTypeNames
? findElementSchemaType(wsdl.definitions, inputMessage.element)
: undefined;
inputDefinition =
type ??
parseDefinition(
Expand All @@ -308,7 +389,9 @@ export async function parseWsdl(wsdlPath: string, options: Partial<ParserOptions
typeName,
inputMessage.parts,
[typeName],
visitedDefinitions
visitedDefinitions,
wsdl.definitions,
schema
);
} else if (inputMessage.parts) {
const type = parsedWsdl.findDefinition(requestParamName);
Expand All @@ -320,7 +403,9 @@ export async function parseWsdl(wsdlPath: string, options: Partial<ParserOptions
requestParamName,
inputMessage.parts,
[requestParamName],
visitedDefinitions
visitedDefinitions,
wsdl.definitions,
undefined
);
} else {
Logger.debug(
Expand All @@ -340,6 +425,9 @@ export async function parseWsdl(wsdlPath: string, options: Partial<ParserOptions
// TODO: if `$type` not defined, inline type into function declartion (do not create definition file) - wsimport
const typeName = outputMessage.element.$type ?? outputMessage.element.$name;
const type = parsedWsdl.findDefinition(typeName);
const schema = mergedOptions.useWsdlTypeNames
? findElementSchemaType(wsdl.definitions, outputMessage.element)
: undefined;
outputDefinition =
type ??
parseDefinition(
Expand All @@ -348,7 +436,9 @@ export async function parseWsdl(wsdlPath: string, options: Partial<ParserOptions
typeName,
outputMessage.parts,
[typeName],
visitedDefinitions
visitedDefinitions,
wsdl.definitions,
schema
);
} else {
const type = parsedWsdl.findDefinition(responseParamName);
Expand All @@ -360,7 +450,9 @@ export async function parseWsdl(wsdlPath: string, options: Partial<ParserOptions
responseParamName,
outputMessage.parts,
[responseParamName],
visitedDefinitions
visitedDefinitions,
wsdl.definitions,
undefined
);
}
}
Expand Down

0 comments on commit 2ce05f0

Please sign in to comment.