@dgac/nmb2b-client
Version:
EUROCONTROL Network Manager B2B SOAP client
1 lines • 7.52 kB
Source Map (JSON)
{"version":3,"file":"soap-query-definition.mjs","names":[],"sources":["../../src/utils/soap-query-definition.ts"],"sourcesContent":["import { createClientAsync, type Client as SoapClient } from 'soap';\nimport type { B2BRequest, Reply } from '../Common/types.js';\nimport type { SoapOptions } from '../soap.js';\nimport { applyHooks } from './hooks/index.js';\nimport {\n assertOkReply,\n injectSendTime,\n type WithInjectedSendTime,\n} from './internals.js';\nimport { prepareSerializer } from './transformers/serializer.js';\nimport { getSoapEndpoint, type Config } from '../config.js';\nimport { getServiceWSDLFilePath } from './xsd/paths.js';\nimport { prepareSecurity } from '../security.js';\nimport { deserializer as customDeserializer } from '../utils/transformers/index.js';\nimport { assert } from './assert.js';\nimport type { SoapQueryHook } from './hooks/hooks.js';\nimport { logHook } from './hooks/withLog.js';\nimport { AssertionError } from 'node:assert';\nimport { NMB2BError } from './NMB2BError.js';\n\nexport type SoapQueryDefinition<\n TInput extends B2BRequest,\n TResult extends Reply,\n> = {\n /**\n * Name of the service.\n */\n service: string;\n\n /**\n * Name of the query.\n *\n * Will be used to infer the soap-client query function name if `executeQuery` is not defined.\n */\n query: string;\n\n /**\n * Given a SoapClient, return the schema for the input of this query.\n *\n * Will be used to build a serializer.\n */\n getSchema: (client: SoapClient) => unknown;\n\n /**\n * Optional getter to extract the correct query function from a `SoapClient`.\n *\n * By default, will use `SoapClient[${query}Async]`\n */\n executeQuery?: (\n client: SoapClient,\n ) => (values: TInput, options?: SoapOptions) => Promise<[TResult]>;\n};\n\nexport function createSoapQueryDefinition<\n TInput extends B2BRequest,\n TResult extends Reply,\n>(queryDefinition: SoapQueryDefinition<TInput, TResult>) {\n return queryDefinition;\n}\n\nexport async function createSoapService<\n TDefinitions extends ServiceDefinition,\n>({\n serviceName,\n config,\n queryDefinitions,\n}: {\n serviceName: string;\n config: Config;\n queryDefinitions: TDefinitions;\n}): Promise<SoapService<TDefinitions>> {\n const WSDL = getServiceWSDLFilePath({\n service: serviceName,\n flavour: config.flavour,\n XSD_PATH: config.XSD_PATH,\n xsdEndpoint: config.xsdEndpoint,\n });\n\n const security = prepareSecurity(config);\n\n const client = await createClientAsync(WSDL, { customDeserializer });\n client.setSecurity(security);\n if (config.endpoint) {\n client.setEndpoint(getSoapEndpoint(config));\n }\n\n return createSoapServiceFromSoapClient({ config, client, queryDefinitions });\n}\n\nexport function createSoapServiceFromSoapClient<\n TDefinitions extends ServiceDefinition,\n>({\n client,\n config,\n queryDefinitions,\n}: {\n client: SoapClient;\n config: Config;\n queryDefinitions: TDefinitions;\n}): SoapService<TDefinitions> {\n const soapQueryFunctions = Object.fromEntries(\n Object.entries(queryDefinitions).map(([queryName, queryDefinition]) => [\n queryName,\n buildQueryFunctionFromSoapDefinition({\n queryDefinition,\n client,\n hooks: [logHook, ...config.hooks],\n }),\n ]),\n );\n\n return {\n __soapClient: client,\n config,\n ...soapQueryFunctions,\n } as SoapService<TDefinitions>;\n}\n\nexport type SoapService<TDefinitions extends ServiceDefinition> = {\n readonly __soapClient: SoapClient;\n readonly config: Config;\n /** @internal */\n readonly __definitions: TDefinitions;\n} & {\n [TKey in keyof TDefinitions]: ExtractSoapQuery<TDefinitions[TKey]>;\n};\n\nexport type ExtractQueryDefinitions<TService> = TService extends {\n readonly __definitions: infer TDefinitions;\n}\n ? TDefinitions\n : never;\n\nfunction buildQueryFunctionFromSoapDefinition<\n TInput extends B2BRequest,\n TResult extends Reply,\n>({\n queryDefinition,\n client,\n hooks,\n}: {\n queryDefinition: SoapQueryDefinition<TInput, TResult>;\n client: SoapClient;\n hooks: Array<SoapQueryHook>;\n}): (\n input: WithInjectedSendTime<TInput>,\n options?: SoapOptions,\n) => Promise<TResult> {\n const schema = queryDefinition.getSchema(client);\n\n assert(\n typeof schema === 'object' && schema !== null,\n `Could not find serializer for query ${queryDefinition.service}.${queryDefinition.query}`,\n );\n\n const serializer = prepareSerializer<TInput>(schema);\n\n let queryFn = queryDefinition.executeQuery\n ? queryDefinition.executeQuery(client)\n : (client[`${queryDefinition.query}Async`] as\n | undefined\n | ((values: TInput, options?: SoapOptions) => Promise<[TResult]>));\n\n assert(\n typeof queryFn === 'function',\n `Could not find query function for query ${queryDefinition.service}.${queryDefinition.query}`,\n );\n\n queryFn = queryFn.bind(client);\n\n return applyHooks<WithInjectedSendTime<TInput>, TResult>({\n service: queryDefinition.service,\n query: queryDefinition.query,\n hooks: hooks,\n queryFn: async (input, options?): Promise<TResult> => {\n try {\n const withSendTime: TInput = injectSendTime(input);\n\n const [result] = await queryFn(serializer(withSendTime), options);\n\n assertOkReply(result);\n return result;\n } catch (err: unknown) {\n if (err instanceof AssertionError || err instanceof NMB2BError) {\n throw err;\n }\n\n throw new Error(\n `[Query ${queryDefinition.service}.${queryDefinition.query}] Error thrown during query execution: ${err instanceof Error ? err.message : 'Unknown error'}`,\n { cause: err },\n );\n }\n },\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ServiceDefinition = Record<string, SoapQueryDefinition<any, any>>;\n\ntype ExtractSoapQuery<T extends SoapQueryDefinition<B2BRequest, Reply>> =\n T extends SoapQueryDefinition<infer TInput, infer TResult>\n ? (\n input: WithInjectedSendTime<TInput>,\n options?: SoapOptions,\n ) => Promise<TResult>\n : never;\n"],"mappings":";;;;;;;;;;;;;;AAqDA,SAAgB,0BAGd,iBAAuD;AACvD,QAAO;;AAGT,eAAsB,kBAEpB,EACA,aACA,QACA,oBAKqC;CACrC,MAAM,OAAO,uBAAuB;EAClC,SAAS;EACT,SAAS,OAAO;EAChB,UAAU,OAAO;EACjB,aAAa,OAAO;EACrB,CAAC;CAEF,MAAM,WAAW,gBAAgB,OAAO;CAExC,MAAM,SAAS,MAAM,kBAAkB,MAAM,EAAE,kCAAoB,CAAC;AACpE,QAAO,YAAY,SAAS;AAC5B,KAAI,OAAO,SACT,QAAO,YAAY,gBAAgB,OAAO,CAAC;AAG7C,QAAO,gCAAgC;EAAE;EAAQ;EAAQ;EAAkB,CAAC;;AAG9E,SAAgB,gCAEd,EACA,QACA,QACA,oBAK4B;AAY5B,QAAO;EACL,cAAc;EACd;EACA,GAdyB,OAAO,YAChC,OAAO,QAAQ,iBAAiB,CAAC,KAAK,CAAC,WAAW,qBAAqB,CACrE,WACA,qCAAqC;GACnC;GACA;GACA,OAAO,CAAC,SAAS,GAAG,OAAO,MAAM;GAClC,CAAC,CACH,CAAC,CACH;EAMA;;AAkBH,SAAS,qCAGP,EACA,iBACA,QACA,SAQoB;CACpB,MAAM,SAAS,gBAAgB,UAAU,OAAO;AAEhD,QACE,OAAO,WAAW,YAAY,WAAW,MACzC,uCAAuC,gBAAgB,QAAQ,GAAG,gBAAgB,QACnF;CAED,MAAM,aAAa,kBAA0B,OAAO;CAEpD,IAAI,UAAU,gBAAgB,eAC1B,gBAAgB,aAAa,OAAO,GACnC,OAAO,GAAG,gBAAgB,MAAM;AAIrC,QACE,OAAO,YAAY,YACnB,2CAA2C,gBAAgB,QAAQ,GAAG,gBAAgB,QACvF;AAED,WAAU,QAAQ,KAAK,OAAO;AAE9B,QAAO,WAAkD;EACvD,SAAS,gBAAgB;EACzB,OAAO,gBAAgB;EAChB;EACP,SAAS,OAAO,OAAO,YAA+B;AACpD,OAAI;IACF,MAAM,eAAuB,eAAe,MAAM;IAElD,MAAM,CAAC,UAAU,MAAM,QAAQ,WAAW,aAAa,EAAE,QAAQ;AAEjE,kBAAc,OAAO;AACrB,WAAO;YACA,KAAc;AACrB,QAAI,eAAe,kBAAkB,eAAe,WAClD,OAAM;AAGR,UAAM,IAAI,MACR,UAAU,gBAAgB,QAAQ,GAAG,gBAAgB,MAAM,yCAAyC,eAAe,QAAQ,IAAI,UAAU,mBACzI,EAAE,OAAO,KAAK,CACf;;;EAGN,CAAC"}