@cap-ts/soap-adapter 0.1.6 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,112 +1,453 @@
1
- export type TraceContext = any;
2
- export type CdsEntity = any;
3
- export type SoapHeaderObject = any;
4
1
  /**
5
- * @typedef {import('./_orchestrator').TraceContext} TraceContext
6
- * @typedef {import('./_orchestrator').CdsEntity} CdsEntity
7
- * @typedef {import('./_orchestrator').SoapHeaderObject} SoapHeaderObject
2
+ * @module @cap-ts/soap-adapter/lib
3
+ * @description Public API surface of the `@cap-ts/soap-adapter` library.
4
+ *
5
+ * Exports {@link ApplicationService} — the abstract base class that every
6
+ * per-entity SOAP adapter must extend — along with {@link FORBIDDEN_SOAP_HEADERS}
7
+ * and a set of re-exported utilities (`createRequest`, `getEntityKeyFields`,
8
+ * `dedupByKeys`, `isSoapService`, `read`).
9
+ *
10
+ * The loader (`_loader/index`) discovers subclasses by filename convention,
11
+ * instantiates them per request, and drives them via the orchestrator
12
+ * (`_orchestrator/index`).
13
+ *
14
+ * @see {@link ApplicationService}
15
+ * @see {@link FORBIDDEN_SOAP_HEADERS}
16
+ */
17
+ import type { Request } from '@sap/cds';
18
+ /**
19
+ * Correlation / tracing identifiers forwarded to every hook invocation so
20
+ * that adapter code can emit structured log lines without having to
21
+ * reconstruct the context from the raw CAP request.
22
+ *
23
+ * @interface TraceContext
24
+ * @property {string} correlationId - Platform-level correlation ID (e.g.
25
+ * `x-vcap-request-id` or `x-correlation-id` from the inbound request).
26
+ * @property {string} user - The authenticated user identifier, typically
27
+ * `req.user.id` as resolved by CAP's authentication middleware.
28
+ * @property {string} timestamp - ISO-8601 timestamp captured at the start
29
+ * of the request, used for log ordering and latency calculations.
30
+ */
31
+ interface TraceContext {
32
+ correlationId: string;
33
+ user: string;
34
+ timestamp: string;
35
+ }
36
+ /**
37
+ * Minimal shape of a CAP CSN entity reflection object as seen at runtime.
38
+ * The full `cds.linked` entity carries many more fields; only the subset
39
+ * consumed by the adapter framework is declared here.
40
+ *
41
+ * @interface CdsEntity
42
+ * @property {string} name - Fully qualified entity name, e.g.
43
+ * `'ext.BusinessPartnerSet'`.
44
+ * @property {Record<string, CdsEntityElement>} elements - Map of element
45
+ * (field) name → element descriptor.
46
+ * @property {SoapBindingConfig} [@Soap.binding] - Optional SOAP binding
47
+ * annotation placed on the entity in the `.cds` model.
48
+ * @property {{ name: string }} parent - The parent service or namespace
49
+ * object; `parent.name` is used to look up `cds.services[parentName]`.
50
+ */
51
+ interface CdsEntity {
52
+ name: string;
53
+ elements: Record<string, CdsEntityElement>;
54
+ '@Soap.binding'?: SoapBindingConfig;
55
+ parent: {
56
+ name: string;
57
+ };
58
+ [key: string]: unknown;
59
+ }
60
+ /**
61
+ * Descriptor for a single element (field) of a CDS entity as returned by
62
+ * `cds.linked` reflection.
63
+ *
64
+ * @interface CdsEntityElement
65
+ * @property {string} [type] - CDS type name, e.g. `'cds.String'`.
66
+ * @property {string} [@Soap.path] - XPath-like path within the SOAP
67
+ * response document that this element maps to.
68
+ */
69
+ interface CdsEntityElement {
70
+ type?: string;
71
+ '@Soap.path'?: string;
72
+ [key: string]: unknown;
73
+ }
74
+ /**
75
+ * Value of the `@Soap.binding` annotation on a CDS entity. Populated by
76
+ * the loader after it resolves the adapter class.
77
+ *
78
+ * @interface SoapBindingConfig
79
+ * @property {string} operation - SOAP operation name (WSDL `<operation>`),
80
+ * e.g. `'GetBusinessPartnerCollection'`.
81
+ * @property {new (entity: CdsEntity, req: Request, trace: TraceContext) => BaseAdapterInstance} [resolvedAdapterClass]
82
+ * - The adapter subclass constructor resolved by the loader. Absent until
83
+ * the loader has completed its discovery pass.
84
+ * @property {string} [rootRequest] - Optional XPath root element to wrap
85
+ * the outbound SOAP request payload in.
86
+ * @property {string} [rootResponse] - Optional XPath root element to unwrap
87
+ * from the inbound SOAP response before mapping.
88
+ */
89
+ interface SoapBindingConfig {
90
+ operation: string;
91
+ resolvedAdapterClass?: new (entity: CdsEntity, req: Request, trace: TraceContext) => BaseAdapterInstance;
92
+ rootRequest?: string;
93
+ rootResponse?: string;
94
+ }
95
+ /**
96
+ * A single SOAP header entry. Either a static object passed directly to
97
+ * `header()` or the resolved return value of a `SoapHeaderEvaluator`
98
+ * callback.
99
+ *
100
+ * @interface SoapHeaderObject
101
+ * @property {*} [value] - Header value (string or structured object
102
+ * depending on the WSDL contract).
103
+ * @property {string} [name] - Local name of the SOAP header element.
104
+ * @property {string} [prefix] - XML namespace prefix, e.g. `'wsse'`.
105
+ * @property {string} [xmlns] - XML namespace URI bound to `prefix`.
106
+ */
107
+ interface SoapHeaderObject {
108
+ value?: unknown;
109
+ name?: string;
110
+ prefix?: string;
111
+ xmlns?: string;
112
+ [key: string]: unknown;
113
+ }
114
+ /**
115
+ * Minimal structural contract that every `ApplicationService` instance must
116
+ * satisfy so the orchestrator can dispatch hooks without knowing the
117
+ * concrete subclass.
118
+ *
119
+ * @interface BaseAdapterInstance
120
+ * @property {Record<string, Array<Function>>} _requestHandlers - Per-entity
121
+ * ordered list of outbound payload transformers registered via
122
+ * {@link ApplicationService#request}.
123
+ * @property {Record<string, Function>} _mockHandlers - Per-entity mock
124
+ * replacements registered via {@link ApplicationService#mock}. Only one
125
+ * mock per entity; the last registration wins.
126
+ * @property {Record<string, Array<SoapHeaderObject|Function>>} _headerHandlers
127
+ * - Per-entity header providers registered via {@link ApplicationService#header}.
128
+ * @property {Record<string, Array<Function>>} _responseHandlers - Per-entity
129
+ * ordered list of response mappers registered via
130
+ * {@link ApplicationService#response}.
131
+ */
132
+ interface BaseAdapterInstance {
133
+ _requestHandlers: Record<string, Array<(payload: unknown, req: Request) => Promise<unknown> | unknown>>;
134
+ _mockHandlers: Record<string, (req: Request, payload: unknown) => Promise<unknown>>;
135
+ _headerHandlers: Record<string, Array<SoapHeaderObject | ((req: Request, payload: unknown) => Promise<SoapHeaderObject> | SoapHeaderObject)>>;
136
+ _responseHandlers: Record<string, Array<(rows: object[], req: Request) => Promise<object[]> | object[]>>;
137
+ }
138
+ /**
139
+ * Frozen, read-only list of HTTP header names that must **never** flow from
140
+ * an inbound CAP request into an outbound SOAP call.
141
+ *
142
+ * Covers:
143
+ * - **Auth material**: `authorization`, `proxy-authorization`, `saml-token`,
144
+ * `x-forwarded-authorization`.
145
+ * - **Session cookies**: `cookie`, `set-cookie`.
146
+ * - **Forwarded-identity metadata**: `x-forwarded-for`, `x-forwarded-host`,
147
+ * `x-forwarded-proto`, `x-real-ip`.
148
+ * - **Platform trace / correlation IDs**: `x-request-id`, `x-correlation-id`,
149
+ * `x-vcap-request-id`, `x-cf-app-instance`, `x-b3-*`, `traceparent`,
150
+ * `tracestate`, `sap-passport`.
151
+ * - **Security tokens**: `x-csrf-token`, `sec-websocket-key`,
152
+ * `sec-websocket-accept`.
153
+ *
154
+ * The list is exposed as `ApplicationService.FORBIDDEN_SOAP_HEADERS` so
155
+ * consumers can inspect it. It is frozen; mutating it will throw in strict
156
+ * mode. To extend it, clone the array and add your own entries.
157
+ *
158
+ * @see {@link ApplicationService.stripSensitiveHeaders}
8
159
  */
160
+ declare const FORBIDDEN_SOAP_HEADERS: readonly string[];
9
161
  /**
10
- * Abstract foundational class defining structural contracts and lifecycle hook registration chains
11
- * for CAP-to-SOAP adapter overrides. This class cannot be instantiated directly.
162
+ * Abstract base class for per-entity SOAP adapters.
163
+ *
164
+ * Consumers subclass this, override {@link ApplicationService#init} to
165
+ * register any combination of {@link ApplicationService#header},
166
+ * {@link ApplicationService#request}, {@link ApplicationService#mock}, and
167
+ * {@link ApplicationService#response} hooks, then export the subclass from a
168
+ * file named `<EntityShortName>.js` or `<EntityShortName>.ts` placed next to
169
+ * the service's `.cds` file.
170
+ *
171
+ * **Contract:**
172
+ * - **One instance per request.** Do not cache request-scoped state on
173
+ * `this` across requests. `entity`, `req`, and `traceContext` are
174
+ * populated fresh for every invocation.
175
+ * - **`init()` is called once, from the constructor**, after the request
176
+ * fields are populated. Register all hooks there.
177
+ * - **Hooks are dispatched by unqualified entity short-name** (e.g.
178
+ * `'BusinessPartner'`, not `'ext.BusinessPartner'`). The `targets`
179
+ * parameter of each registration method accepts strings, CSN entity
180
+ * objects, arrays of either, or comma-separated strings.
12
181
  *
13
182
  * @abstract
183
+ * @example
184
+ * // Minimal adapter for a "ProductSet" entity:
185
+ * class ProductSet extends ApplicationService {
186
+ * init() {
187
+ * this.request('ProductSet', async (req) => ({
188
+ * ProductID: req.data.ID,
189
+ * }));
190
+ * this.response('ProductSet', (req, rows) =>
191
+ * rows.map(r => ({ ...r, _source: 'soap' }))
192
+ * );
193
+ * }
194
+ * }
195
+ * module.exports = { ProductSet };
14
196
  */
15
- export class ApplicationService {
16
- /**
17
- * Initializes the abstract service base layout.
18
- * @param {CdsEntity} entity - Contextual meta-reflection model representing the current execution entity instance.
19
- * @param {cds.Request} req - The incoming runtime context parameter bundle payload managed by the active application framework.
20
- * @param {TraceContext} traceContext - Unique execution tracking identifier context map used for logging.
21
- * @throws {TypeError} If this abstract class is directly instantiated via `new ApplicationService()`.
22
- */
23
- constructor(entity: CdsEntity, req: cds.Request, traceContext: TraceContext);
24
- entity: any;
25
- req: cds.Request;
26
- traceContext: any;
27
- _requestHandlers: {};
28
- _responseHandlers: {};
29
- _mockHandlers: {};
30
- _headerHandlers: {};
31
- entities: any;
32
- /**
33
- * Internal framework initialization lifecycle wrapper.
34
- * Safe fallback that child classes can call via super._superInit() if wanted.
35
- * @private
197
+ declare class ApplicationService {
198
+ /**
199
+ * Frozen array of HTTP header names that must never be forwarded to a
200
+ * SOAP backend. Used by {@link ApplicationService.stripSensitiveHeaders}.
201
+ * @static
202
+ * @readonly
203
+ * @public
36
204
  */
37
- private _superInit;
205
+ static readonly FORBIDDEN_SOAP_HEADERS: readonly string[];
38
206
  /**
39
- * Abstract initialization sequence triggered automatically during instance generation.
40
- * Must be overridden in child classes to establish event listeners.
41
- * @abstract
42
- * @throws {Error} If the derived child class does not implement this method.
43
- * @returns {void}
207
+ * CSN entity reflection object for the entity this adapter instance
208
+ * serves. Populated by the constructor before `init()` is called.
209
+ * @public
44
210
  */
45
- init(): void;
211
+ entity: CdsEntity;
46
212
  /**
47
- * Internal framework utility to convert single or multi-target inputs down
48
- * to a flat list of clean, unqualified short name string token keys.
49
- * Fully handles: Arrays of CSN Objects, single Objects, and raw strings.
50
- * @param {string|Object|Array.<string|Object>} targets - The input target(s) to normalize into a flat list of unqualified entity names.
51
- * @returns {Array.<string>} A flat list of unqualified entity name strings.
52
- * @private
213
+ * The current CAP request. Available as `this.req` inside all hooks.
214
+ * @public
53
215
  */
54
- private _resolveEntityNames;
216
+ req: Request;
55
217
  /**
56
- * @callback SoapHeaderEvaluator
57
- * @param {cds.Request} req - The incoming CAP request context.
58
- * @param {*} [data] - The optional secondary payload data context.
59
- * @returns {Promise.<SoapHeaderObject>|SoapHeaderObject}
218
+ * Correlation / tracing identifiers forwarded from the orchestrator.
219
+ * Forwarded to every hook invocation for structured logging.
220
+ * @public
60
221
  */
222
+ traceContext: TraceContext;
61
223
  /**
62
- * Registers a custom SOAP header factory interceptor or a static structural payload value for a specific entity.
63
- * @param {string|Object|Array.<string|Object>} targets - The input target(s) to normalize into a flat list of unqualified entity names.
64
- * @param {SoapHeaderObject|SoapHeaderEvaluator} handler - A static header matching object configurations or an executable factory generator function.
65
- * @throws {Error} If the provided handler is neither a functional execution block nor an object structure.
66
- * @returns {void}
224
+ * All entities exposed by the parent CAP service, keyed by unqualified
225
+ * short-name. Populated automatically from `cds.services[parentName].entities`
226
+ * in the constructor. Empty object `{}` when the parent service cannot
227
+ * be resolved (e.g. in unit tests that do not boot a full CAP server).
228
+ * @public
229
+ */
230
+ entities: Record<string, CdsEntity>;
231
+ /**
232
+ * Per-entity ordered list of outbound payload transformer functions
233
+ * registered via {@link ApplicationService#request}.
234
+ * @protected
235
+ */
236
+ protected _requestHandlers: Record<string, Array<(payload: unknown, req: Request) => Promise<unknown> | unknown>>;
237
+ /**
238
+ * Per-entity ordered list of response mapper functions registered via
239
+ * {@link ApplicationService#response}.
240
+ * @protected
241
+ */
242
+ protected _responseHandlers: Record<string, Array<(rows: object[], req: Request) => Promise<object[]> | object[]>>;
243
+ /**
244
+ * Per-entity mock replacement functions registered via
245
+ * {@link ApplicationService#mock}. Only one mock per entity; the last
246
+ * registration wins.
247
+ * @protected
67
248
  */
68
- header(targets: string | Object | Array<string | Object>, handler: SoapHeaderObject | ((req: cds.Request, data?: any) => Promise<SoapHeaderObject> | SoapHeaderObject)): void;
249
+ protected _mockHandlers: Record<string, (req: Request, payload: unknown) => Promise<unknown>>;
69
250
  /**
70
- * @callback SoapRequestEvaluator
71
- * @param {cds.Request} req - The incoming CAP request context.
72
- * @param {*} [data] - The optional secondary payload data context.
73
- * @returns {Promise.<*>|*}
251
+ * Per-entity header providers (static objects or evaluator functions)
252
+ * registered via {@link ApplicationService#header}.
253
+ * @protected
74
254
  */
255
+ protected _headerHandlers: Record<string, Array<SoapHeaderObject | ((req: Request, payload: unknown) => Promise<SoapHeaderObject> | SoapHeaderObject)>>;
75
256
  /**
76
- * Appends a pre-flight payload manipulation interceptor function to the execution chain of an entity.
77
- * @param {string|Object|Array.<string|Object>} targets - The unqualified short name string or the compiled CSN Entity Object definition.
78
- * @param {SoapRequestEvaluator} handler - Callback function mutating incoming outbound arguments.
79
- * @throws {Error} If the handler input fails functional type evaluation checks.
257
+ * Return a shallow copy of `headers` with every key that appears in
258
+ * {@link FORBIDDEN_SOAP_HEADERS} removed (comparison is
259
+ * case-insensitive — keys are lower-cased before matching).
260
+ *
261
+ * Non-object or falsy input returns an empty object `{}` rather than
262
+ * throwing, so callers can safely pass `req.headers ?? {}` without a
263
+ * guard.
264
+ *
265
+ * The allowlist is exposed as `ApplicationService.FORBIDDEN_SOAP_HEADERS`
266
+ * (frozen). Consumers can extend it by cloning the array and adding
267
+ * extra entries; mutating the exported constant throws in strict mode.
268
+ *
269
+ * @param {Record<string, *>} headers - The raw HTTP headers object to
270
+ * sanitise (e.g. `req.headers`).
271
+ * @returns {Record<string, *>} A new object containing only the headers
272
+ * that are safe to forward to the SOAP backend.
273
+ * @example
274
+ * // Inside a header() hook:
275
+ * this.header(Entity, (req) =>
276
+ * ApplicationService.stripSensitiveHeaders(req.headers ?? {})
277
+ * );
278
+ * @static
279
+ * @public
280
+ */
281
+ static stripSensitiveHeaders(headers: Record<string, unknown>): Record<string, unknown>;
282
+ /**
283
+ * Initialise the adapter instance for a single CAP request.
284
+ *
285
+ * Performs the following steps in order:
286
+ * 1. Guards against direct instantiation (abstract-class enforcement).
287
+ * 2. Stores `entity`, `req`, and `traceContext` on `this`.
288
+ * 3. Initialises the four empty handler registries
289
+ * (`_requestHandlers`, `_responseHandlers`, `_mockHandlers`,
290
+ * `_headerHandlers`).
291
+ * 4. Resolves the parent service name from the entity reflection and
292
+ * binds `this.entities` from `cds.services[parentName].entities`.
293
+ * 5. Calls `_superInit()` (framework extension point, currently a no-op).
294
+ * 6. Calls `init()` so the subclass can register its hooks.
295
+ *
296
+ * @param {CdsEntity} entity - CSN entity reflection for the entity this
297
+ * adapter serves (e.g. `srv.entities.BusinessUserSet`).
298
+ * @param {Request} req - The current CAP request. Available as
299
+ * `this.req` inside all hook callbacks.
300
+ * @param {TraceContext} traceContext - Correlation IDs for structured
301
+ * logs; forwarded to every hook invocation.
302
+ * @throws {TypeError} If instantiated directly (i.e. `new.target ===
303
+ * ApplicationService`) instead of via a concrete subclass.
304
+ * @public
305
+ */
306
+ constructor(entity: CdsEntity, req: Request, traceContext: TraceContext);
307
+ /**
308
+ * Framework extension point called by the constructor immediately before
309
+ * {@link ApplicationService#init}. Currently a no-op; reserved for
310
+ * future default initialisation steps (e.g. injecting framework-level
311
+ * hooks or populating shared metadata).
312
+ *
313
+ * Subclasses **may** call `super._superInit()` from their own `init()`
314
+ * for forward-compatibility, but nothing depends on it today.
315
+ *
316
+ * Visibility is `protected` (not `private`) because the documented
317
+ * override contract via `super._superInit()` requires subclass access.
318
+ *
319
+ * @returns {void}
320
+ * @protected
321
+ */
322
+ protected _superInit(): void;
323
+ /**
324
+ * Lifecycle hook called once from the constructor after all instance
325
+ * fields are populated. Subclasses **must** override this method and
326
+ * use it to register their SOAP hooks via `header()`, `request()`,
327
+ * `mock()`, and/or `response()`.
328
+ *
329
+ * The base implementation throws unconditionally so that a missing
330
+ * override is caught at instantiation time rather than silently
331
+ * producing a no-op adapter.
332
+ *
333
+ * @abstract
334
+ * @throws {Error} Always — subclasses must override this method.
80
335
  * @returns {void}
336
+ * @public
81
337
  */
82
- request(targets: string | Object | Array<string | Object>, handler: (req: cds.Request, data?: any) => Promise<any> | any): void;
338
+ init(): void;
339
+ /**
340
+ * Normalise a `targets` argument into a flat, deduplicated list of
341
+ * unqualified entity short-names used as internal dispatch keys.
342
+ *
343
+ * Accepted input forms:
344
+ * - **CSN entity object** (`{ name: 'ext.BusinessPartner', … }`) →
345
+ * returns `['BusinessPartner']` (last segment after the last `.`).
346
+ * - **Qualified string** (`'ext.BusinessPartner'`) → same as above.
347
+ * - **Unqualified string** (`'BusinessPartner'`) → returned as-is.
348
+ * - **Comma-separated string** (`'A,ext.B'`) → split, trimmed, and
349
+ * each entry normalised individually.
350
+ * - **Array** of any of the above → recursively flattened.
351
+ * - `null` / `undefined` / empty string → returns `[]`.
352
+ *
353
+ * @param {string|CdsEntity|Array<string|CdsEntity>|null|undefined} targets
354
+ * - One or more entity references to normalise.
355
+ * @returns {string[]} Zero or more unqualified entity short-names.
356
+ * @private
357
+ */
358
+ private _resolveEntityNames;
83
359
  /**
84
- * @callback SoapMockEvaluator
85
- * @param {cds.Request} req - The incoming CAP request context.
86
- * @param {*} [data] - The optional secondary payload data context.
87
- * @returns {Promise.<*>|*}
360
+ * Register SOAP header providers for one or more entities.
361
+ *
362
+ * `handler` may be either:
363
+ * - A **static** {@link SoapHeaderObject} that is attached verbatim to
364
+ * every outbound SOAP call for the matched entities.
365
+ * - An **evaluator function** `(req, data) => SoapHeaderObject` (sync or
366
+ * async) that is called per request and may inspect `req` to build the
367
+ * header dynamically.
368
+ *
369
+ * Multiple registrations for the same entity are all invoked in
370
+ * registration order. The same handler reference passed twice for the
371
+ * same entity is de-duplicated (only the first registration is kept).
372
+ *
373
+ * Common use: strip sensitive inbound HTTP headers before forwarding
374
+ * them to the SOAP backend — see
375
+ * {@link ApplicationService.stripSensitiveHeaders}.
376
+ *
377
+ * @param {string|CdsEntity|Array<string|CdsEntity>} targets - One or
378
+ * more entity references that this header provider applies to.
379
+ * @param {SoapHeaderObject|((req: Request, payload: *) => Promise<SoapHeaderObject>|SoapHeaderObject)} handler
380
+ * - Static header object or evaluator function.
381
+ * @throws {Error} If `handler` is neither a function nor an object.
382
+ * @returns {void}
383
+ * @public
88
384
  */
385
+ header(targets: string | CdsEntity | Array<string | CdsEntity>, handler: SoapHeaderObject | ((req: Request, payload: unknown) => Promise<SoapHeaderObject> | SoapHeaderObject)): void;
89
386
  /**
90
- * Registers a single intercept sandbox bypass mock handler function for an entity, overriding native network requests entirely.
91
- * @param {string|Object|Array.<string|Object>} targets - The input target(s) to normalize into a flat list of unqualified entity names.
92
- * @param {SoapMockEvaluator} handler - Intercept bypass simulation callback executing sandboxed returns.
93
- * @throws {Error} If the handler input fails functional type evaluation checks.
387
+ * Register a hook that shapes the outbound SOAP payload for one or more
388
+ * entities.
389
+ *
390
+ * The return value of `handler` replaces the payload that the
391
+ * orchestrator would otherwise build from the CAP request. Multiple
392
+ * registrations for the same entity run in registration order; each
393
+ * invocation receives the output of the previous stage. The same
394
+ * handler reference passed twice is de-duplicated.
395
+ *
396
+ * @param {string|CdsEntity|Array<string|CdsEntity>} targets - One or
397
+ * more entity references that this request transformer applies to.
398
+ * @param {(payload: *, req: Request) => Promise<*>|*} handler - A
399
+ * function that receives the current payload and the CAP request, and
400
+ * returns the transformed payload (sync or async).
401
+ * @throws {Error} If `handler` is not a function.
94
402
  * @returns {void}
403
+ * @public
95
404
  */
96
- mock(targets: string | Object | Array<string | Object>, handler: (req: cds.Request, data?: any) => Promise<any> | any): void;
405
+ request(targets: string | CdsEntity | Array<string | CdsEntity>, handler: (payload: unknown, req: Request) => Promise<unknown> | unknown): void;
97
406
  /**
98
- * @callback SoapResponseEvaluator
99
- * @param {cds.Request} req - The incoming CAP request context.
100
- * @param {any[]} data - The response data context.
101
- * @returns {Promise.<Array.<Object>>|Array.<Object>}
102
- */
407
+ * Register a mock that fully replaces the SOAP round-trip for the given
408
+ * entity/entities.
409
+ *
410
+ * When a mock is registered, the orchestrator returns the mock's value
411
+ * directly instead of calling the SOAP backend. Only **one** mock per
412
+ * entity is kept — the last registration wins (unlike `request` /
413
+ * `response` which accumulate).
414
+ *
415
+ * Intended for unit tests. Not subject to error sanitisation — any
416
+ * exception thrown by the mock is surfaced as-is to the caller.
417
+ *
418
+ * @param {string|CdsEntity|Array<string|CdsEntity>} targets - One or
419
+ * more entity references to mock.
420
+ * @param {(req: Request, payload: *) => Promise<*>|*} handler - A
421
+ * function that receives the CAP request and the current payload, and
422
+ * returns the mock response (sync or async).
423
+ * @throws {Error} If `handler` is not a function.
424
+ * @returns {void}
425
+ * @public
426
+ */
427
+ mock(targets: string | CdsEntity | Array<string | CdsEntity>, handler: (req: Request, payload: unknown) => Promise<unknown>): void;
103
428
  /**
104
- * Appends a post-flight response extraction array mapping transformation interceptor function to the execution chain of an entity.
105
- * @param {string|Object|Array.<string|Object>} targets - The unqualified short name string or the compiled CSN Entity Object definition.
106
- * @param {SoapResponseEvaluator} handler - Translation mapper formatting downstream runtime array structures.
107
- * @throws {Error} If the handler input fails functional type evaluation checks.
429
+ * Register a hook that maps the raw SOAP response array into the flat
430
+ * row shape that CAP expects for the target entity.
431
+ *
432
+ * Multiple registrations for the same entity run in registration order;
433
+ * each invocation receives the output of the previous stage. Unlike
434
+ * `header` and `request`, this hook is **not** de-duplicated —
435
+ * registering the same handler reference twice causes it to run twice.
436
+ *
437
+ * @param {string|CdsEntity|Array<string|CdsEntity>} targets - One or
438
+ * more entity references that this response mapper applies to.
439
+ * @param {(rows: object[], req: Request) => Promise<object[]>|object[]} handler
440
+ * - A function that receives the current row array and the CAP
441
+ * request, and returns the transformed row array (sync or async).
442
+ * @throws {Error} If `handler` is not a function.
108
443
  * @returns {void}
444
+ * @public
109
445
  */
110
- response(targets: string | Object | Array<string | Object>, handler: (req: cds.Request, data: any[]) => Promise<Array<Object>> | Array<Object>): void;
446
+ response(targets: string | CdsEntity | Array<string | CdsEntity>, handler: (rows: object[], req: Request) => Promise<object[]> | object[]): void;
111
447
  }
448
+ declare const createRequest: typeof import("./_request").createRequest;
449
+ declare const getEntityKeyFields: typeof import("./_util/entity").getEntityKeyFields, dedupByKeys: typeof import("./_util/entity").dedupByKeys, isSoapService: typeof import("./_util/entity").isSoapService;
450
+ declare const read: typeof import("./_read").read;
451
+ export type { ReadOptions } from './_read';
452
+ export { ApplicationService, FORBIDDEN_SOAP_HEADERS, createRequest, getEntityKeyFields, dedupByKeys, isSoapService, read, };
112
453
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../.types/lib/index.js"],"names":[],"mappings":";;;AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH;IACI;;;;;;OAMG;IACH,oBALW,SAAS,OACT,GAAG,CAAC,OAAO,gBACX,YAAY,EAiCtB;IA1BG,YAAoB;IACpB,iBAAc;IACd,kBAAgC;IAGhC,qBAA0B;IAC1B,sBAA2B;IAC3B,kBAAuB;IACvB,oBAAyB;IAUrB,cAA8D;IAUtE;;;;OAIG;IACH,mBAEC;IAED;;;;;;OAMG;IACH,QAFa,IAAI,CAIhB;IAED;;;;;;;OAOG;IACH,4BA8BC;IAED;;;;;OAKG;IAEH;;;;;;OAMG;IACH,gBALW,MAAM,GAAC,MAAM,GAAC,KAAK,CAAE,MAAM,GAAC,MAAM,CAAC,WACnC,gBAAgB,UARhB,GAAG,CAAC,OAAO,SACX,GAAC,KACC,OAAO,CAAE,gBAAgB,CAAC,GAAC,gBAAgB,CAMT,GAElC,IAAI,CAgBhB;IAED;;;;;OAKG;IAEH;;;;;;OAMG;IACH,iBALW,MAAM,GAAC,MAAM,GAAC,KAAK,CAAE,MAAM,GAAC,MAAM,CAAC,iBAPnC,GAAG,CAAC,OAAO,SACX,GAAC,KACC,OAAO,CAAE,GAAC,CAAC,GAAC,GAAC,GAQb,IAAI,CAYhB;IAED;;;;;OAKG;IAEH;;;;;;OAMG;IACH,cALW,MAAM,GAAC,MAAM,GAAC,KAAK,CAAE,MAAM,GAAC,MAAM,CAAC,iBAPnC,GAAG,CAAC,OAAO,SACX,GAAC,KACC,OAAO,CAAE,GAAC,CAAC,GAAC,GAAC,GAQb,IAAI,CAShB;IAEA;;;;;MAKE;IAEH;;;;;;OAMG;IACH,kBALW,MAAM,GAAC,MAAM,GAAC,KAAK,CAAE,MAAM,GAAC,MAAM,CAAC,iBAPnC,GAAG,CAAC,OAAO,QACX,GAAG,EAAE,KACH,OAAO,CAAE,KAAK,CAAE,MAAM,CAAC,CAAC,GAAC,KAAK,CAAE,MAAM,CAAC,GAQvC,IAAI,CAUhB;CACJ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../build/src/lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AASxC;;;;;;;;;;;;GAYG;AACH,UAAU,YAAY;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,UAAU,SAAS;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,eAAe,CAAC,EAAE,iBAAiB,CAAC;IACpC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,UAAU,gBAAgB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,UAAU,iBAAiB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,KAAK,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,mBAAmB,CAAC;IACzG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,UAAU,gBAAgB;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,UAAU,mBAAmB;IACzB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACxG,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACpF,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9I,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;CAC5G;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,QAAA,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAyB3C,CAAC;AAMH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,cAAM,kBAAkB;IACpB;;;;;;OAMG;IACH,gBAAuB,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAEjE;;;;OAIG;IACI,MAAM,EAAE,SAAS,CAAC;IAEzB;;;OAGG;IACI,GAAG,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACI,YAAY,EAAE,YAAY,CAAC;IAElC;;;;;;OAMG;IACI,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAE3C;;;;OAIG;IACH,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAElH;;;;OAIG;IACH,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;IAEnH;;;;;OAKG;IACH,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAE9F;;;;OAIG;IACH,SAAS,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAExJ;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;WACW,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAY9F;;;;;;;;;;;;;;;;;;;;;;;OAuBG;gBACgB,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY;IA6B9E;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,UAAU,IAAI,IAAI;IAI5B;;;;;;;;;;;;;;OAcG;IACI,IAAI,IAAI,IAAI;IAInB;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,MAAM,CACT,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,EACvD,OAAO,EAAE,gBAAgB,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAC,GAC/G,IAAI;IAcP;;;;;;;;;;;;;;;;;;OAkBG;IACI,OAAO,CACV,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,EACvD,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,GACxE,IAAI;IAYP;;;;;;;;;;;;;;;;;;;;OAoBG;IACI,IAAI,CACP,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,EACvD,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAC9D,IAAI;IASP;;;;;;;;;;;;;;;;;OAiBG;IACI,QAAQ,CACX,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,EACvD,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GACxE,IAAI;CASV;AAUD,QAAA,MAAQ,aAAa,2CAA0F,CAAC;AAGhH,QAAA,MACI,kBAAkB,sDAClB,WAAW,+CACX,aAAa,+CAKhB,CAAC;AAKF,QAAA,MAAQ,IAAI,+BAAkE,CAAC;AAE/E,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM3C,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,IAAI,GACP,CAAC"}