SOAP Tool Generation Example
This example shows how to create an OpenPets plugin from a SOAP/WSDL specification.
Example: Currency Conversion SOAP Service
We'll use a public SOAP service to demonstrate the generation process.
Step 1: Create New Pet
bash
pets new currency-converter
cd pets/currency-converterStep 2: Add SOAP Configuration
Edit package.json to include SOAP specification:
json
{
"$schema": "https://pets.raggle.co/config.json",
"name": "@openpets/currency-converter",
"version": "1.0.0",
"title": "Currency Converter",
"subtitle": "Convert currencies using SOAP service",
"description": "Currency conversion plugin using legacy SOAP web service",
"main": "index.ts",
"types": "index.ts",
"soapSpec": {
"url": "http://www.dataaccess.com/webservicesserver/NumberConversion.wso?WSDL",
"authType": "basic",
"authEnvVar": "CURRENCY_CONVERTER_API_KEY"
},
"envVariables": {
"optional": [
{
"name": "CURRENCY_CONVERTER_API_KEY_USERNAME",
"description": "SOAP service username (if required)",
"provider": "Currency Converter",
"priority": 1
},
{
"name": "CURRENCY_CONVERTER_API_KEY_PASSWORD",
"description": "SOAP service password (if required)",
"provider": "Currency Converter",
"priority": 2
}
]
},
"queries": [
"convert number to words",
"convert currency"
],
"dependencies": {
"openpets-sdk": "workspace:*",
"soap": "^1.0.0",
"dotenv": "^16.0.0"
}
}Step 3: Generate SOAP Tools
bash
# Install dependencies
bun install
# Generate SOAP client and tools
pets generate-soap --verboseOutput:
🔧 Generating SOAP tools from WSDL...
ℹ Fetching WSDL from URL
ℹ WSDL downloaded successfully
ℹ Generating TypeScript client with wsdl-tsclient
ℹ Found 4 SOAP operations
ℹ Generated SOAP client
ℹ Generated SOAP tools
✅ Generated 4 SOAP tools from WSDL
📁 Client: /path/to/pets/currency-converter/soap-client.ts
📁 Tools: /path/to/pets/currency-converter/soap-tools.tsStep 4: Review Generated Files
soap-client.ts
typescript
/**
* SOAP Client Utilities
*
* Auto-generated from WSDL: http://www.dataaccess.com/webservicesserver/NumberConversion.wso?WSDL
* Generated: 2025-02-04T10:30:00.000Z
*/
import soap from "soap"
import { createLogger, loadEnv } from "openpets-sdk"
const logger = createLogger("soap-client")
const env = loadEnv(process.cwd())
export const WSDL_URL = "http://www.dataaccess.com/webservicesserver/NumberConversion.wso?WSDL"
export async function createSOAPClient(): Promise<any> {
try {
const client = await soap.createClientAsync(WSDL_URL, {
wsdl_headers: getAuthHeaders()
})
client.setSecurity(new soap.BasicAuthSecurity(
env.CURRENCY_CONVERTER_API_KEY_USERNAME || "",
env.CURRENCY_CONVERTER_API_KEY_PASSWORD || ""
))
logger.info("SOAP client created successfully")
return client
} catch (error: any) {
logger.error("Failed to create SOAP client", { error: error.message })
throw error
}
}
export async function callSOAPOperation(
operationName: string,
args: any
): Promise<any> {
const client = await createSOAPClient()
try {
const method = client[`${operationName}Async`]
if (!method) {
throw new Error(`Operation ${operationName} not found`)
}
const result = await method.call(client, args)
return result[0]
} catch (error: any) {
logger.error("SOAP operation failed", { operationName, error: error.message })
throw error
}
}
// ... more utilitiessoap-tools.ts
typescript
/**
* SOAP Tool Definitions
*
* Auto-generated SOAP operations as OpenPets tools
*/
import { z, type ToolDefinition } from "openpets-sdk"
import { callSOAPOperation } from "./soap-client"
const soapTools: ToolDefinition[] = [
{
name: "soap-number-to-words",
description: "Convert a number to words",
schema: z.object({
params: z.string().optional().describe("JSON string of operation parameters")
}),
async execute(args) {
try {
const params = args.params ? JSON.parse(args.params) : {}
const result = await callSOAPOperation("NumberToWords", params)
return JSON.stringify({
success: true,
operation: "NumberToWords",
result
}, null, 2)
} catch (error: any) {
return JSON.stringify({
success: false,
operation: "NumberToWords",
error: error.message
}, null, 2)
}
}
},
// ... more tools
]
export default soapToolsStep 5: Integrate in index.ts
typescript
import { config as loadDotenv } from "dotenv"
import { createPlugin, createLogger, loadEnv, z } from "openpets-sdk"
import soapTools from "./soap-tools"
loadDotenv()
export const CurrencyConverterPlugin = async () => {
const logger = createLogger("currency-converter")
const env = loadEnv("currency-converter")
const customTools = [
{
name: "currency-converter-test-connection",
description: "Test SOAP connection to currency converter service",
schema: z.object({}),
async execute() {
try {
return JSON.stringify({
success: true,
status: "connected",
message: "SOAP service available"
}, null, 2)
} catch (error: any) {
return JSON.stringify({
success: false,
status: "error",
message: error.message
}, null, 2)
}
}
}
]
return createPlugin([
...customTools,
...soapTools
])
}
export default CurrencyConverterPluginStep 6: Test the Plugin
bash
# Test connection
bun test:pet currency-converter --query "test connection"
# Use SOAP operation
bun test:pet currency-converter --query "convert number 123 to words"Advanced Configuration
Custom Authentication
For different auth types, update package.json:
json
{
"soapSpec": {
"url": "https://api.example.com/service?wsdl",
"authType": "wssecurity", // Options: basic, wssecurity, bearer, clientssl, ntlm
"authEnvVar": "MY_SERVICE_API_KEY"
}
}Manual Generation
You can also run generation manually:
bash
# From WSDL URL
pets generate-soap \
--url http://example.com/service?wsdl \
--auth-type basic \
--auth-env-var MY_SERVICE_API \
--verbose
# From local WSDL file
pets generate-soap \
--file ./service.wsdl \
--auth-type wssecurity \
--output-client my-client.ts \
--output-tools my-tools.ts
# Preview without writing files
pets generate-soap --url http://example.com/service?wsdl --dry-run
# Generate only TypeScript definitions
pets generate-soap --url http://example.com/service?wsdl --definitions-onlyReal-World Example: HM Land Registry
For a production example with SSL certificates and complex authentication:
bash
pets new land-registry
cd pets/land-registry
# Add SOAP configuration
cat > package.json <<EOF
{
"name": "@openpets/land-registry",
"version": "1.0.0",
"soapSpec": {
"url": "https://bgtest.landregistry.gov.uk/b2b/BGStubService?wsdl",
"authType": "basic",
"authEnvVar": "LAND_REGISTRY_API_KEY"
},
"envVariables": {
"required": [
{
"name": "LAND_REGISTRY_API_KEY_USERNAME",
"description": "HM Land Registry username",
"provider": "HM Land Registry",
"priority": 1
},
{
"name": "LAND_REGISTRY_API_KEY_PASSWORD",
"description": "HM Land Registry password",
"provider": "HM Land Registry",
"priority": 2
}
]
},
"dependencies": {
"openpets-sdk": "workspace:*",
"soap": "^1.0.0",
"dotenv": "^16.0.0"
}
}
EOF
# Generate SOAP tools
pets generate-soap --verboseThis page is the complete SOAP generation walkthrough.
Troubleshooting
wsdl-tsclient not found
bash
# Install globally
npm install -g wsdl-tsclient
# Or let the generator install it automatically
pets generate-soap --verboseSOAP dependency missing
bash
# Add soap package
bun add soapWSDL fetch fails
bash
# Download WSDL manually
curl https://api.example.com/service?wsdl > service.wsdl
# Generate from local file
pets generate-soap --file ./service.wsdlSSL certificate errors
For services requiring SSL certificates:
typescript
// In soap-client.ts, add SSL options
const client = await soap.createClientAsync(WSDL_URL, {
wsdl_headers: getAuthHeaders(),
cert: readFileSync(env.CERT_PATH),
key: readFileSync(env.KEY_PATH)
})