@xapi-js/adaptor-nestjs 1.0.0 → 1.1.1
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.
- package/README.md +151 -29
- package/dist/index.cjs +150 -0
- package/dist/index.d.cts +42 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +125 -0
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/xapi-response-interceptor.ts +1 -1
package/README.md
CHANGED
|
@@ -1,29 +1,151 @@
|
|
|
1
|
-
# @xapi-ts/adaptor-nestjs
|
|
2
|
-
|
|
3
|
-
This package provides a NestJS adaptor for X-API data.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
# @xapi-ts/adaptor-nestjs
|
|
2
|
+
|
|
3
|
+
This package provides a NestJS adaptor for X-API data.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# npm
|
|
9
|
+
npm install @xapi-ts/adaptor-nestjs
|
|
10
|
+
|
|
11
|
+
# yarn
|
|
12
|
+
yarn add @xapi-ts/adaptor-nestjs
|
|
13
|
+
|
|
14
|
+
# pnpm
|
|
15
|
+
pnpm add @xapi-ts/adaptor-nestjs
|
|
16
|
+
|
|
17
|
+
# bun
|
|
18
|
+
bun add @xapi-ts/adaptor-nestjs
|
|
19
|
+
|
|
20
|
+
# deno
|
|
21
|
+
deno add @xapi-ts/adaptor-nestjs
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
`@xapi-ts/adaptor-nestjs` provides NestJS interceptors to automatically handle X-API request deserialization and response serialization.
|
|
27
|
+
|
|
28
|
+
### XapiRequestInterceptor
|
|
29
|
+
|
|
30
|
+
Use `XapiRequestInterceptor` to automatically parse incoming `application/xml` requests into `XapiRoot` objects.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// app.controller.ts
|
|
34
|
+
import { Controller, Post, UseInterceptors, Body } from '@nestjs/common';
|
|
35
|
+
import { XapiRoot } from '@xapi-ts/core';
|
|
36
|
+
import { XapiRequestInterceptor } from '@xapi-ts/adaptor-nestjs';
|
|
37
|
+
|
|
38
|
+
@Controller('xapi')
|
|
39
|
+
export class AppController {
|
|
40
|
+
@Post('/')
|
|
41
|
+
@UseInterceptors(XapiRequestInterceptor)
|
|
42
|
+
handleXapi(@Body() xapi: XapiRoot): XapiRoot {
|
|
43
|
+
console.log('Received XapiRoot:', xapi.parameters.get('service')?.value);
|
|
44
|
+
// Process the XapiRoot object
|
|
45
|
+
const responseXapi = new XapiRoot();
|
|
46
|
+
responseXapi.addParameter({ id: 'result', value: 'success' });
|
|
47
|
+
return responseXapi;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### XapiResponseInterceptor
|
|
53
|
+
|
|
54
|
+
Use `XapiResponseInterceptor` to automatically serialize `XapiRoot` objects returned from your NestJS controllers into `application/xml` responses.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// app.controller.ts
|
|
58
|
+
import { Controller, Post, UseInterceptors, Body } from '@nestjs/common';
|
|
59
|
+
import { XapiRoot } from '@xapi-ts/core
|
|
60
|
+
import { XapiRequestInterceptor, XapiResponseInterceptor } from '@xapi-ts/adaptor-nestjs';
|
|
61
|
+
|
|
62
|
+
@Controller('xapi')
|
|
63
|
+
export class AppController {
|
|
64
|
+
@Post('/')
|
|
65
|
+
@UseInterceptors(XapiRequestInterceptor, XapiResponseInterceptor)
|
|
66
|
+
handleXapi(@Body() xapi: XapiRoot): XapiRoot {
|
|
67
|
+
console.log('Received XapiRoot:', xapi.parameters.get('service')?.value);
|
|
68
|
+
// Process the XapiRoot object
|
|
69
|
+
const responseXapi = new XapiRoot();
|
|
70
|
+
responseXapi.addParameter({ id: 'result', value: 'success' });
|
|
71
|
+
return responseXapi;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
# @xapi-ts/adaptor-nestjs
|
|
79
|
+
|
|
80
|
+
이 패키지는 X-API 데이터를 위한 NestJS 어댑터를 제공합니다.
|
|
81
|
+
|
|
82
|
+
## 설치
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# npm
|
|
86
|
+
npm install @xapi-ts/adaptor-nestjs
|
|
87
|
+
|
|
88
|
+
# yarn
|
|
89
|
+
yarn add @xapi-ts/adaptor-nestjs
|
|
90
|
+
|
|
91
|
+
# pnpm
|
|
92
|
+
pnpm add @xapi-ts/adaptor-nestjs
|
|
93
|
+
|
|
94
|
+
# bun
|
|
95
|
+
bun add @xapi-ts/adaptor-nestjs
|
|
96
|
+
|
|
97
|
+
# deno
|
|
98
|
+
deno add @xapi-ts/adaptor-nestjs
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 사용법
|
|
102
|
+
|
|
103
|
+
`@xapi-ts/adaptor-nestjs`는 X-API 요청 역직렬화 및 응답 직렬화를 자동으로 처리하는 NestJS 인터셉터를 제공합니다.
|
|
104
|
+
|
|
105
|
+
### XapiRequestInterceptor
|
|
106
|
+
|
|
107
|
+
들어오는 `application/xml` 요청을 `XapiRoot` 객체로 자동 구문 분석하려면 `XapiRequestInterceptor`를 사용하십시오.
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// app.controller.ts
|
|
111
|
+
import { Controller, Post, UseInterceptors, Body } from '@nestjs/common';
|
|
112
|
+
import { XapiRoot } from '@xapi-ts/core';
|
|
113
|
+
import { XapiRequestInterceptor } from '@xapi-ts/adaptor-nestjs';
|
|
114
|
+
|
|
115
|
+
@Controller('xapi')
|
|
116
|
+
export class AppController {
|
|
117
|
+
@Post('/')
|
|
118
|
+
@UseInterceptors(XapiRequestInterceptor)
|
|
119
|
+
handleXapi(@Body() xapi: XapiRoot): XapiRoot {
|
|
120
|
+
console.log('Received XapiRoot:', xapi.parameters.get('service')?.value);
|
|
121
|
+
// XapiRoot 객체 처리
|
|
122
|
+
const responseXapi = new XapiRoot();
|
|
123
|
+
responseXapi.addParameter({ id: 'result', value: 'success' });
|
|
124
|
+
return responseXapi;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### XapiResponseInterceptor
|
|
130
|
+
|
|
131
|
+
NestJS 컨트롤러에서 반환된 `XapiRoot` 객체를 `application/xml` 응답으로 자동 직렬화하려면 `XapiResponseInterceptor`를 사용하십시오.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// app.controller.ts
|
|
135
|
+
import { Controller, Post, UseInterceptors, Body } from '@nestjs/common';
|
|
136
|
+
import { XapiRoot } from '@xapi-ts/core
|
|
137
|
+
import { XapiRequestInterceptor, XapiResponseInterceptor } from '@xapi-ts/adaptor-nestjs';
|
|
138
|
+
|
|
139
|
+
@Controller('xapi')
|
|
140
|
+
export class AppController {
|
|
141
|
+
@Post('/')
|
|
142
|
+
@UseInterceptors(XapiRequestInterceptor, XapiResponseInterceptor)
|
|
143
|
+
handleXapi(@Body() xapi: XapiRoot): XapiRoot {
|
|
144
|
+
console.log('Received XapiRoot:', xapi.parameters.get('service')?.value);
|
|
145
|
+
// XapiRoot 객체 처리
|
|
146
|
+
const responseXapi = new XapiRoot();
|
|
147
|
+
responseXapi.addParameter({ id: 'result', value: 'success' });
|
|
148
|
+
return responseXapi;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
8
|
+
var __typeError = (msg) => {
|
|
9
|
+
throw TypeError(msg);
|
|
10
|
+
};
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
13
|
+
var __export = (target, all) => {
|
|
14
|
+
for (var name in all)
|
|
15
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
+
for (let key of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
26
|
+
var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
|
|
27
|
+
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
|
|
28
|
+
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
|
|
29
|
+
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
|
|
30
|
+
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
|
|
31
|
+
var __runInitializers = (array, flags, self, value) => {
|
|
32
|
+
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
|
|
33
|
+
return value;
|
|
34
|
+
};
|
|
35
|
+
var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
36
|
+
var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
|
|
37
|
+
var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
|
|
38
|
+
var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
|
|
39
|
+
var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
|
|
40
|
+
return __privateGet(this, extra);
|
|
41
|
+
}, set [name](x) {
|
|
42
|
+
return __privateSet(this, extra, x);
|
|
43
|
+
} }, name));
|
|
44
|
+
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
|
|
45
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
46
|
+
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
|
|
47
|
+
if (k) {
|
|
48
|
+
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
|
|
49
|
+
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
|
|
50
|
+
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
|
|
51
|
+
}
|
|
52
|
+
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
|
|
53
|
+
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
|
|
54
|
+
else if (typeof it !== "object" || it === null) __typeError("Object expected");
|
|
55
|
+
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
|
|
56
|
+
}
|
|
57
|
+
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
58
|
+
};
|
|
59
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
60
|
+
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
|
|
61
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
62
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
63
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
64
|
+
|
|
65
|
+
// src/index.ts
|
|
66
|
+
var index_exports = {};
|
|
67
|
+
__export(index_exports, {
|
|
68
|
+
XapiRequestInterceptor: () => XapiRequestInterceptor,
|
|
69
|
+
XapiResponseInterceptor: () => XapiResponseInterceptor
|
|
70
|
+
});
|
|
71
|
+
module.exports = __toCommonJS(index_exports);
|
|
72
|
+
|
|
73
|
+
// src/xapi-request-interceptor.ts
|
|
74
|
+
var import_common = require("@nestjs/common");
|
|
75
|
+
var import_core = require("@xapi-js/core");
|
|
76
|
+
var _XapiRequestInterceptor_decorators, _init;
|
|
77
|
+
_XapiRequestInterceptor_decorators = [(0, import_common.Injectable)()];
|
|
78
|
+
var _XapiRequestInterceptor = class _XapiRequestInterceptor {
|
|
79
|
+
constructor() {
|
|
80
|
+
this.logger = new import_common.Logger(_XapiRequestInterceptor.name);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Intercepts the incoming request to parse XML body.
|
|
84
|
+
* If the content type is `application/xml` and a body exists, it attempts to parse the body
|
|
85
|
+
* into an `XapiRoot` object and replaces the original request body with it.
|
|
86
|
+
* @param context - The execution context of the request.
|
|
87
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
88
|
+
* @returns An `Observable` that will eventually contain the response.
|
|
89
|
+
*/
|
|
90
|
+
async intercept(context, next) {
|
|
91
|
+
const request = context.switchToHttp().getRequest();
|
|
92
|
+
this.logger.debug(`XapiRequestInterceptor Intercepting request: ${request.method} ${request.url}`);
|
|
93
|
+
if (request.headers["content-type"] === "application/xml" && request.body) {
|
|
94
|
+
request.body = await (0, import_core.parse)(request.body);
|
|
95
|
+
}
|
|
96
|
+
return next.handle();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
_init = __decoratorStart(null);
|
|
100
|
+
_XapiRequestInterceptor = __decorateElement(_init, 0, "XapiRequestInterceptor", _XapiRequestInterceptor_decorators, _XapiRequestInterceptor);
|
|
101
|
+
__runInitializers(_init, 1, _XapiRequestInterceptor);
|
|
102
|
+
var XapiRequestInterceptor = _XapiRequestInterceptor;
|
|
103
|
+
|
|
104
|
+
// src/xapi-response-interceptor.ts
|
|
105
|
+
var import_common2 = require("@nestjs/common");
|
|
106
|
+
var import_core2 = require("@xapi-js/core");
|
|
107
|
+
var import_rxjs = require("rxjs");
|
|
108
|
+
var _XapiResponseInterceptor_decorators, _init2;
|
|
109
|
+
_XapiResponseInterceptor_decorators = [(0, import_common2.Injectable)()];
|
|
110
|
+
var _XapiResponseInterceptor = class _XapiResponseInterceptor {
|
|
111
|
+
constructor() {
|
|
112
|
+
this.logger = new import_common2.Logger(_XapiResponseInterceptor.name);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Intercepts the outgoing response to serialize XapiRoot to XML string.
|
|
116
|
+
* If the handler returns an `XapiRoot` instance, it attempts to serialize it
|
|
117
|
+
* into an XML string.
|
|
118
|
+
* @param context - The execution context of the request.
|
|
119
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
120
|
+
* @returns An `Observable` that will eventually contain the XML string response.
|
|
121
|
+
* @throws {Error} if the handler does not return an `XapiRoot` instance or serialization fails.
|
|
122
|
+
*/
|
|
123
|
+
intercept(context, next) {
|
|
124
|
+
this.logger.debug(`XapiResponseInterceptor Intercepting response`);
|
|
125
|
+
return next.handle().pipe(
|
|
126
|
+
(0, import_rxjs.map)(async (value) => {
|
|
127
|
+
if (value instanceof import_core2.XapiRoot) {
|
|
128
|
+
try {
|
|
129
|
+
const xmlOutput = await (0, import_core2.writeString)(value);
|
|
130
|
+
return xmlOutput;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
this.logger.error(`Failed to serialize XapiRoot to XML string: ${error}`);
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
throw new Error("Handler did not return an XapiRoot instance");
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
_init2 = __decoratorStart(null);
|
|
143
|
+
_XapiResponseInterceptor = __decorateElement(_init2, 0, "XapiResponseInterceptor", _XapiResponseInterceptor_decorators, _XapiResponseInterceptor);
|
|
144
|
+
__runInitializers(_init2, 1, _XapiResponseInterceptor);
|
|
145
|
+
var XapiResponseInterceptor = _XapiResponseInterceptor;
|
|
146
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
147
|
+
0 && (module.exports = {
|
|
148
|
+
XapiRequestInterceptor,
|
|
149
|
+
XapiResponseInterceptor
|
|
150
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { XapiRoot } from '@xapi-js/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Interceptor that parses incoming XML request bodies into XapiRoot objects.
|
|
7
|
+
* This interceptor should be applied to routes that expect an `application/xml` content type
|
|
8
|
+
* and whose body contains X-API XML data.
|
|
9
|
+
*/
|
|
10
|
+
declare class XapiRequestInterceptor implements NestInterceptor {
|
|
11
|
+
private readonly logger;
|
|
12
|
+
/**
|
|
13
|
+
* Intercepts the incoming request to parse XML body.
|
|
14
|
+
* If the content type is `application/xml` and a body exists, it attempts to parse the body
|
|
15
|
+
* into an `XapiRoot` object and replaces the original request body with it.
|
|
16
|
+
* @param context - The execution context of the request.
|
|
17
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
18
|
+
* @returns An `Observable` that will eventually contain the response.
|
|
19
|
+
*/
|
|
20
|
+
intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Interceptor that serializes XapiRoot objects returned by NestJS route handlers into XML strings.
|
|
25
|
+
* This interceptor should be applied to routes that return an `XapiRoot` instance
|
|
26
|
+
* and whose response should be `application/xml`.
|
|
27
|
+
*/
|
|
28
|
+
declare class XapiResponseInterceptor implements NestInterceptor<XapiRoot, Promise<string>> {
|
|
29
|
+
private readonly logger;
|
|
30
|
+
/**
|
|
31
|
+
* Intercepts the outgoing response to serialize XapiRoot to XML string.
|
|
32
|
+
* If the handler returns an `XapiRoot` instance, it attempts to serialize it
|
|
33
|
+
* into an XML string.
|
|
34
|
+
* @param context - The execution context of the request.
|
|
35
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
36
|
+
* @returns An `Observable` that will eventually contain the XML string response.
|
|
37
|
+
* @throws {Error} if the handler does not return an `XapiRoot` instance or serialization fails.
|
|
38
|
+
*/
|
|
39
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<Promise<string>>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { XapiRequestInterceptor, XapiResponseInterceptor };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { XapiRoot } from '@xapi-js/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Interceptor that parses incoming XML request bodies into XapiRoot objects.
|
|
7
|
+
* This interceptor should be applied to routes that expect an `application/xml` content type
|
|
8
|
+
* and whose body contains X-API XML data.
|
|
9
|
+
*/
|
|
10
|
+
declare class XapiRequestInterceptor implements NestInterceptor {
|
|
11
|
+
private readonly logger;
|
|
12
|
+
/**
|
|
13
|
+
* Intercepts the incoming request to parse XML body.
|
|
14
|
+
* If the content type is `application/xml` and a body exists, it attempts to parse the body
|
|
15
|
+
* into an `XapiRoot` object and replaces the original request body with it.
|
|
16
|
+
* @param context - The execution context of the request.
|
|
17
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
18
|
+
* @returns An `Observable` that will eventually contain the response.
|
|
19
|
+
*/
|
|
20
|
+
intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Interceptor that serializes XapiRoot objects returned by NestJS route handlers into XML strings.
|
|
25
|
+
* This interceptor should be applied to routes that return an `XapiRoot` instance
|
|
26
|
+
* and whose response should be `application/xml`.
|
|
27
|
+
*/
|
|
28
|
+
declare class XapiResponseInterceptor implements NestInterceptor<XapiRoot, Promise<string>> {
|
|
29
|
+
private readonly logger;
|
|
30
|
+
/**
|
|
31
|
+
* Intercepts the outgoing response to serialize XapiRoot to XML string.
|
|
32
|
+
* If the handler returns an `XapiRoot` instance, it attempts to serialize it
|
|
33
|
+
* into an XML string.
|
|
34
|
+
* @param context - The execution context of the request.
|
|
35
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
36
|
+
* @returns An `Observable` that will eventually contain the XML string response.
|
|
37
|
+
* @throws {Error} if the handler does not return an `XapiRoot` instance or serialization fails.
|
|
38
|
+
*/
|
|
39
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<Promise<string>>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { XapiRequestInterceptor, XapiResponseInterceptor };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
5
|
+
var __typeError = (msg) => {
|
|
6
|
+
throw TypeError(msg);
|
|
7
|
+
};
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
+
var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
|
|
11
|
+
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
|
|
12
|
+
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
|
|
13
|
+
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
|
|
14
|
+
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
|
|
15
|
+
var __runInitializers = (array, flags, self, value) => {
|
|
16
|
+
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
|
|
17
|
+
return value;
|
|
18
|
+
};
|
|
19
|
+
var __decorateElement = (array, flags, name, decorators, target, extra) => {
|
|
20
|
+
var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
|
|
21
|
+
var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
|
|
22
|
+
var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
|
|
23
|
+
var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
|
|
24
|
+
return __privateGet(this, extra);
|
|
25
|
+
}, set [name](x) {
|
|
26
|
+
return __privateSet(this, extra, x);
|
|
27
|
+
} }, name));
|
|
28
|
+
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
|
|
29
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
30
|
+
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
|
|
31
|
+
if (k) {
|
|
32
|
+
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
|
|
33
|
+
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
|
|
34
|
+
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
|
|
35
|
+
}
|
|
36
|
+
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
|
|
37
|
+
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
|
|
38
|
+
else if (typeof it !== "object" || it === null) __typeError("Object expected");
|
|
39
|
+
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
|
|
40
|
+
}
|
|
41
|
+
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
|
|
42
|
+
};
|
|
43
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
44
|
+
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
|
|
45
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
46
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
47
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
48
|
+
|
|
49
|
+
// src/xapi-request-interceptor.ts
|
|
50
|
+
import { Injectable, Logger } from "@nestjs/common";
|
|
51
|
+
import { parse } from "@xapi-js/core";
|
|
52
|
+
var _XapiRequestInterceptor_decorators, _init;
|
|
53
|
+
_XapiRequestInterceptor_decorators = [Injectable()];
|
|
54
|
+
var _XapiRequestInterceptor = class _XapiRequestInterceptor {
|
|
55
|
+
constructor() {
|
|
56
|
+
this.logger = new Logger(_XapiRequestInterceptor.name);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Intercepts the incoming request to parse XML body.
|
|
60
|
+
* If the content type is `application/xml` and a body exists, it attempts to parse the body
|
|
61
|
+
* into an `XapiRoot` object and replaces the original request body with it.
|
|
62
|
+
* @param context - The execution context of the request.
|
|
63
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
64
|
+
* @returns An `Observable` that will eventually contain the response.
|
|
65
|
+
*/
|
|
66
|
+
async intercept(context, next) {
|
|
67
|
+
const request = context.switchToHttp().getRequest();
|
|
68
|
+
this.logger.debug(`XapiRequestInterceptor Intercepting request: ${request.method} ${request.url}`);
|
|
69
|
+
if (request.headers["content-type"] === "application/xml" && request.body) {
|
|
70
|
+
request.body = await parse(request.body);
|
|
71
|
+
}
|
|
72
|
+
return next.handle();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
_init = __decoratorStart(null);
|
|
76
|
+
_XapiRequestInterceptor = __decorateElement(_init, 0, "XapiRequestInterceptor", _XapiRequestInterceptor_decorators, _XapiRequestInterceptor);
|
|
77
|
+
__runInitializers(_init, 1, _XapiRequestInterceptor);
|
|
78
|
+
var XapiRequestInterceptor = _XapiRequestInterceptor;
|
|
79
|
+
|
|
80
|
+
// src/xapi-response-interceptor.ts
|
|
81
|
+
import { Injectable as Injectable2, Logger as Logger2 } from "@nestjs/common";
|
|
82
|
+
import { XapiRoot, writeString } from "@xapi-js/core";
|
|
83
|
+
import { map } from "rxjs";
|
|
84
|
+
var _XapiResponseInterceptor_decorators, _init2;
|
|
85
|
+
_XapiResponseInterceptor_decorators = [Injectable2()];
|
|
86
|
+
var _XapiResponseInterceptor = class _XapiResponseInterceptor {
|
|
87
|
+
constructor() {
|
|
88
|
+
this.logger = new Logger2(_XapiResponseInterceptor.name);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Intercepts the outgoing response to serialize XapiRoot to XML string.
|
|
92
|
+
* If the handler returns an `XapiRoot` instance, it attempts to serialize it
|
|
93
|
+
* into an XML string.
|
|
94
|
+
* @param context - The execution context of the request.
|
|
95
|
+
* @param next - A `CallHandler` to invoke the next interceptor or the route handler.
|
|
96
|
+
* @returns An `Observable` that will eventually contain the XML string response.
|
|
97
|
+
* @throws {Error} if the handler does not return an `XapiRoot` instance or serialization fails.
|
|
98
|
+
*/
|
|
99
|
+
intercept(context, next) {
|
|
100
|
+
this.logger.debug(`XapiResponseInterceptor Intercepting response`);
|
|
101
|
+
return next.handle().pipe(
|
|
102
|
+
map(async (value) => {
|
|
103
|
+
if (value instanceof XapiRoot) {
|
|
104
|
+
try {
|
|
105
|
+
const xmlOutput = await writeString(value);
|
|
106
|
+
return xmlOutput;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
this.logger.error(`Failed to serialize XapiRoot to XML string: ${error}`);
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error("Handler did not return an XapiRoot instance");
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
_init2 = __decoratorStart(null);
|
|
119
|
+
_XapiResponseInterceptor = __decorateElement(_init2, 0, "XapiResponseInterceptor", _XapiResponseInterceptor_decorators, _XapiResponseInterceptor);
|
|
120
|
+
__runInitializers(_init2, 1, _XapiResponseInterceptor);
|
|
121
|
+
var XapiResponseInterceptor = _XapiResponseInterceptor;
|
|
122
|
+
export {
|
|
123
|
+
XapiRequestInterceptor,
|
|
124
|
+
XapiResponseInterceptor
|
|
125
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xapi-js/adaptor-nestjs",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"express": "^5.1.0",
|
|
31
31
|
"rxjs": "^7.8.1",
|
|
32
32
|
"@nestjs/common": "^10.3.10",
|
|
33
|
-
"@xapi-js/core": "1.
|
|
33
|
+
"@xapi-js/core": "1.1.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {},
|
|
36
36
|
"scripts": {
|
package/src/index.ts
ADDED
|
@@ -30,7 +30,7 @@ export class XapiResponseInterceptor implements NestInterceptor<XapiRoot, Promis
|
|
|
30
30
|
const xmlOutput = await writeString(value as XapiRoot);
|
|
31
31
|
return xmlOutput!!;
|
|
32
32
|
} catch (error) {
|
|
33
|
-
this.logger.error(`Failed to serialize XapiRoot to XML string: ${error
|
|
33
|
+
this.logger.error(`Failed to serialize XapiRoot to XML string: ${error}`);
|
|
34
34
|
throw error; // Re-throw the original error
|
|
35
35
|
}
|
|
36
36
|
}
|