@rosen-bridge/fastify-enhanced 2.0.2 → 3.1.0
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/CHANGELOG.md +15 -0
- package/README.md +134 -43
- package/dist/fastify.d.ts +3 -10
- package/dist/fastify.d.ts.map +1 -1
- package/dist/fastify.js +5 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/swagger.d.ts.map +1 -1
- package/dist/swagger.js +12 -6
- package/dist/types.d.ts +5 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +7 -3
- package/dist/jsonParser.d.ts +0 -4
- package/dist/jsonParser.d.ts.map +0 -1
- package/dist/jsonParser.js +0 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @rosen-bridge/fastify-enhanced
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add enableCSP option to swagger options of makeFastify
|
|
8
|
+
|
|
9
|
+
## 3.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- Remove @rosen-bridge/json-bigint dependency and jsonParser in facvor of zod's coerce functionality
|
|
14
|
+
- Add apiKey securityScheme to swagger
|
|
15
|
+
- Update the type of fastify-options argument of makeFastify to FastifyHttpOptions
|
|
16
|
+
- Re-export fastify request and reply types
|
|
17
|
+
|
|
3
18
|
## 2.0.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -16,47 +16,42 @@ npm:
|
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
18
|
npm i @rosen-bridge/fastify-enhanced
|
|
19
|
+
|
|
20
|
+
# install compatible zod version
|
|
21
|
+
npm i zod@^3.21.4
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
yarn:
|
|
22
25
|
|
|
23
26
|
```sh
|
|
24
27
|
yarn add @rosen-bridge/fastify-enhanced
|
|
28
|
+
|
|
29
|
+
# install compatible zod version
|
|
30
|
+
yarn add zod@^3.21.4
|
|
25
31
|
```
|
|
26
32
|
|
|
27
33
|
## Usage
|
|
28
34
|
|
|
29
|
-
To use the enhanced Fastify, import `
|
|
35
|
+
To use the enhanced Fastify, import `makeFastify` and use it to create a fastify instance and register routes. Install and use zod to define schemas for validating requests and responses:
|
|
36
|
+
|
|
37
|
+
> Note: For **BigInt** field types, since JSON does not support the BigInt data type, you should use `z.coerce.bigint()` in the schema, and the value in the data transfer object (DTO) should be either a **number** or a **string**; `coerce` allows Zod to validate and transform the number or string value into a BigInt. Also its preferred to use string for bigint types in the response schemas.
|
|
30
38
|
|
|
31
39
|
```ts
|
|
32
|
-
import {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const addTokenPaymentRoute = (
|
|
42
|
-
fastify: FastifyInstance<
|
|
43
|
-
Server<typeof IncomingMessage, typeof ServerResponse>,
|
|
44
|
-
IncomingMessage,
|
|
45
|
-
ServerResponse<IncomingMessage>,
|
|
46
|
-
FastifyBaseLogger,
|
|
47
|
-
ZodTypeProvider
|
|
48
|
-
>,
|
|
49
|
-
) => {
|
|
50
|
-
const bodySchema = types.object({
|
|
51
|
-
tokenName: types.string(),
|
|
52
|
-
tokenAmount: types.bigint(),
|
|
53
|
-
tokenDecimals: types.number(),
|
|
40
|
+
import { z } from 'zod';
|
|
41
|
+
|
|
42
|
+
import { FastifyWithZod, makeFastify } from '@rosen-bridge/fastify-enhanced';
|
|
43
|
+
|
|
44
|
+
const addTokenPaymentRoute = (fastify: FastifyWithZod) => {
|
|
45
|
+
const bodySchema = z.object({
|
|
46
|
+
tokenName: z.string(),
|
|
47
|
+
tokenAmount: z.coerce.bigint(),
|
|
48
|
+
tokenDecimals: z.number(),
|
|
54
49
|
});
|
|
55
50
|
|
|
56
|
-
const res200Schema =
|
|
57
|
-
name:
|
|
58
|
-
amount:
|
|
59
|
-
decimal:
|
|
51
|
+
const res200Schema = z.object({
|
|
52
|
+
name: z.string(),
|
|
53
|
+
amount: z.string(),
|
|
54
|
+
decimal: z.number(),
|
|
60
55
|
});
|
|
61
56
|
|
|
62
57
|
const payTokenOpts = {
|
|
@@ -71,15 +66,89 @@ const addTokenPaymentRoute = (
|
|
|
71
66
|
fastify.post('/payToken', payTokenOpts, async (request, reply) => {
|
|
72
67
|
return reply.status(200).send({
|
|
73
68
|
name: request.body.tokenName,
|
|
74
|
-
amount: request.body.tokenAmount,
|
|
69
|
+
amount: request.body.tokenAmount.toString(),
|
|
75
70
|
decimal: request.body.tokenDecimals,
|
|
76
71
|
});
|
|
77
72
|
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const addDemoRoute = (fastify: FastifyWithZod) => {
|
|
76
|
+
const bodySchema = z.object({
|
|
77
|
+
numberField: z.number(),
|
|
78
|
+
bigintField: z.coerce.bigint(),
|
|
79
|
+
booleanField: z.boolean(),
|
|
80
|
+
stringField: z.string(),
|
|
81
|
+
optionalStringField: z.optional(z.string()),
|
|
82
|
+
objectField: z.object({
|
|
83
|
+
bigintField: z.coerce.bigint(),
|
|
84
|
+
// ...
|
|
85
|
+
}),
|
|
86
|
+
numberArrayField: z.array(z.number()),
|
|
87
|
+
stringArrayField: z.array(z.string()),
|
|
88
|
+
unionField: z.union([
|
|
89
|
+
z.string(),
|
|
90
|
+
z.object({
|
|
91
|
+
stringArrayField: z.array(z.string()),
|
|
92
|
+
// ...
|
|
93
|
+
}),
|
|
94
|
+
]),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const qsSchema = z.object({
|
|
98
|
+
qs: z.union([z.string().transform((i) => [i]), z.array(z.string())]),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const res200Schema = z.object({
|
|
102
|
+
qs: z.array(z.string()),
|
|
103
|
+
numberField: z.number(),
|
|
104
|
+
bigintField: z.string(),
|
|
105
|
+
booleanField: z.boolean(),
|
|
106
|
+
stringField: z.string(),
|
|
107
|
+
optionalStringField: z.optional(z.string()),
|
|
108
|
+
objectField: z.object({
|
|
109
|
+
bigintField: z.string(),
|
|
110
|
+
// ...
|
|
111
|
+
}),
|
|
112
|
+
numberArrayField: z.array(z.number()),
|
|
113
|
+
stringArrayField: z.array(z.string()),
|
|
114
|
+
unionField: z.union([
|
|
115
|
+
z.string(),
|
|
116
|
+
z.object({
|
|
117
|
+
stringArrayField: z.array(z.string()),
|
|
118
|
+
// ...
|
|
119
|
+
}),
|
|
120
|
+
]),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const routeOpts = {
|
|
124
|
+
schema: {
|
|
125
|
+
querystring: qsSchema,
|
|
126
|
+
body: bodySchema,
|
|
127
|
+
response: {
|
|
128
|
+
200: res200Schema,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
};
|
|
78
132
|
|
|
79
|
-
|
|
133
|
+
fastify.post('/demo', routeOpts, async (request, reply) => {
|
|
134
|
+
return reply.status(200).send({
|
|
135
|
+
qs: request.query.qs,
|
|
136
|
+
numberField: request.body.numberField,
|
|
137
|
+
bigintField: request.body.bigintField.toString(),
|
|
138
|
+
booleanField: request.body.booleanField,
|
|
139
|
+
stringField: request.body.stringField,
|
|
140
|
+
optionalStringField: request.body.optionalStringField,
|
|
141
|
+
objectField: {
|
|
142
|
+
bigintField: request.body.objectField.bigintField.toString(),
|
|
143
|
+
},
|
|
144
|
+
numberArrayField: request.body.numberArrayField,
|
|
145
|
+
stringArrayField: request.body.stringArrayField,
|
|
146
|
+
unionField: request.body.unionField,
|
|
147
|
+
});
|
|
148
|
+
});
|
|
80
149
|
};
|
|
81
150
|
|
|
82
|
-
const fastify = await
|
|
151
|
+
const fastify = await makeFastify(
|
|
83
152
|
{
|
|
84
153
|
path: '/swagger',
|
|
85
154
|
title: '',
|
|
@@ -89,27 +158,49 @@ const fastify = await createFastify(
|
|
|
89
158
|
{ logger: false },
|
|
90
159
|
);
|
|
91
160
|
addTokenPaymentRoute(fastify);
|
|
161
|
+
// Or fastify.register(addTokenPaymentRoute);
|
|
162
|
+
addDemoRoute(fastify);
|
|
92
163
|
|
|
93
164
|
const start = async () => {
|
|
94
165
|
try {
|
|
95
|
-
await fastify.
|
|
166
|
+
await fastify.ready();
|
|
167
|
+
await fastify.listen({ host: '127.0.0.1', port: 8000 });
|
|
168
|
+
console.log(`listening http://127.0.0.1:8000`);
|
|
96
169
|
} catch (err) {
|
|
97
|
-
console.
|
|
170
|
+
console.error(err);
|
|
98
171
|
process.exit(1);
|
|
99
172
|
}
|
|
100
173
|
};
|
|
101
|
-
start();
|
|
102
|
-
```
|
|
103
174
|
|
|
104
|
-
|
|
175
|
+
start();
|
|
105
176
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
177
|
+
/*
|
|
178
|
+
curl --request POST \
|
|
179
|
+
--url 'http://localhost:8000/demo?qs=key1&qs=key2' \
|
|
180
|
+
--header 'content-type: application/json' \
|
|
181
|
+
--data '{
|
|
182
|
+
"numberField": 10,
|
|
183
|
+
"bigintField": "10000",
|
|
184
|
+
"booleanField": true,
|
|
185
|
+
"stringField": "str",
|
|
186
|
+
"objectField": {
|
|
187
|
+
"bigintField": 10
|
|
112
188
|
},
|
|
113
|
-
|
|
114
|
-
|
|
189
|
+
"numberArrayField": [
|
|
190
|
+
0,
|
|
191
|
+
100,
|
|
192
|
+
1000
|
|
193
|
+
],
|
|
194
|
+
"stringArrayField": [
|
|
195
|
+
"str1",
|
|
196
|
+
"str2"
|
|
197
|
+
],
|
|
198
|
+
"unionField": {
|
|
199
|
+
"stringArrayField": [
|
|
200
|
+
"str1",
|
|
201
|
+
"str2"
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
}'
|
|
205
|
+
*/
|
|
115
206
|
```
|
package/dist/fastify.d.ts
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
|
+
import { FastifyBaseLogger, FastifyHttpOptions } from 'fastify';
|
|
1
2
|
import 'zod-openapi/extend';
|
|
2
|
-
import { FastifyWithZod, SwaggerOpts } from './types';
|
|
3
|
+
import { FastifyWithZod, FastifyWithZodServer, SwaggerOpts } from './types';
|
|
3
4
|
/**
|
|
4
5
|
* creates an instance of Fastify with Zod validation library as validator and
|
|
5
6
|
* type provider
|
|
6
7
|
*/
|
|
7
|
-
export declare const makeFastify: (swaggerOpts?: SwaggerOpts, opts?:
|
|
8
|
-
logger: boolean;
|
|
9
|
-
}, jsonHandler?: {
|
|
10
|
-
parse: (text: string, reviver?: (this: any, key: string, value: any) => any) => any;
|
|
11
|
-
stringify: {
|
|
12
|
-
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
13
|
-
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
14
|
-
};
|
|
15
|
-
}) => Promise<FastifyWithZod>;
|
|
8
|
+
export declare const makeFastify: (swaggerOpts?: SwaggerOpts, opts?: FastifyHttpOptions<FastifyWithZodServer, FastifyBaseLogger>) => Promise<FastifyWithZod>;
|
|
16
9
|
//# sourceMappingURL=fastify.d.ts.map
|
package/dist/fastify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../lib/fastify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../lib/fastify.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAOzE,OAAO,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,WAAW,GACtB,cAAa,WAMZ,EACD,OAAM,kBAAkB,CAAC,oBAAoB,EAAE,iBAAiB,CAE/D,KACA,OAAO,CAAC,cAAc,CAYxB,CAAC"}
|
package/dist/fastify.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import Fastify from 'fastify';
|
|
2
2
|
import { fastifyZodOpenApiPlugin, serializerCompiler, validatorCompiler, } from 'fastify-zod-openapi';
|
|
3
3
|
import 'zod-openapi/extend';
|
|
4
|
-
import { JsonBigIntFactory } from '@rosen-bridge/json-bigint';
|
|
5
|
-
import { makeJsonParser } from './jsonParser';
|
|
6
4
|
import { registerSwagger } from './swagger';
|
|
7
5
|
/**
|
|
8
6
|
* creates an instance of Fastify with Zod validation library as validator and
|
|
@@ -13,17 +11,15 @@ export const makeFastify = async (swaggerOpts = {
|
|
|
13
11
|
title: 'api',
|
|
14
12
|
description: '',
|
|
15
13
|
version: '0.0.1',
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
})) => {
|
|
14
|
+
enableCSP: false,
|
|
15
|
+
}, opts = {
|
|
16
|
+
logger: true,
|
|
17
|
+
}) => {
|
|
21
18
|
const fastify = Fastify(opts).withTypeProvider();
|
|
22
19
|
fastify.setValidatorCompiler(validatorCompiler);
|
|
23
20
|
fastify.setSerializerCompiler(serializerCompiler);
|
|
24
21
|
await fastify.register(fastifyZodOpenApiPlugin);
|
|
25
|
-
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, makeJsonParser(jsonHandler));
|
|
26
22
|
await registerSwagger(fastify, swaggerOpts);
|
|
27
23
|
return fastify;
|
|
28
24
|
};
|
|
29
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFzdGlmeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL2xpYi9mYXN0aWZ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sT0FBa0QsTUFBTSxTQUFTLENBQUM7QUFDekUsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixrQkFBa0IsRUFDbEIsaUJBQWlCLEdBQ2xCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxvQkFBb0IsQ0FBQztBQUU1QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRzVDOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQzlCLGNBQTJCO0lBQ3pCLElBQUksRUFBRSxVQUFVO0lBQ2hCLEtBQUssRUFBRSxLQUFLO0lBQ1osV0FBVyxFQUFFLEVBQUU7SUFDZixPQUFPLEVBQUUsT0FBTztJQUNoQixTQUFTLEVBQUUsS0FBSztDQUNqQixFQUNELE9BQW9FO0lBQ2xFLE1BQU0sRUFBRSxJQUFJO0NBQ2IsRUFDd0IsRUFBRTtJQUMzQixNQUFNLE9BQU8sR0FDWCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsZ0JBQWdCLEVBQWlDLENBQUM7SUFFbEUsT0FBTyxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDaEQsT0FBTyxDQUFDLHFCQUFxQixDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFFbEQsTUFBTSxPQUFPLENBQUMsUUFBUSxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFFaEQsTUFBTSxlQUFlLENBQUMsT0FBTyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBRTVDLE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBGYXN0aWZ5LCB7IEZhc3RpZnlCYXNlTG9nZ2VyLCBGYXN0aWZ5SHR0cE9wdGlvbnMgfSBmcm9tICdmYXN0aWZ5JztcbmltcG9ydCB7XG4gIHR5cGUgRmFzdGlmeVpvZE9wZW5BcGlUeXBlUHJvdmlkZXIsXG4gIGZhc3RpZnlab2RPcGVuQXBpUGx1Z2luLFxuICBzZXJpYWxpemVyQ29tcGlsZXIsXG4gIHZhbGlkYXRvckNvbXBpbGVyLFxufSBmcm9tICdmYXN0aWZ5LXpvZC1vcGVuYXBpJztcbmltcG9ydCAnem9kLW9wZW5hcGkvZXh0ZW5kJztcblxuaW1wb3J0IHsgcmVnaXN0ZXJTd2FnZ2VyIH0gZnJvbSAnLi9zd2FnZ2VyJztcbmltcG9ydCB7IEZhc3RpZnlXaXRoWm9kLCBGYXN0aWZ5V2l0aFpvZFNlcnZlciwgU3dhZ2dlck9wdHMgfSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBjcmVhdGVzIGFuIGluc3RhbmNlIG9mIEZhc3RpZnkgd2l0aCBab2QgdmFsaWRhdGlvbiBsaWJyYXJ5IGFzIHZhbGlkYXRvciBhbmRcbiAqIHR5cGUgcHJvdmlkZXJcbiAqL1xuZXhwb3J0IGNvbnN0IG1ha2VGYXN0aWZ5ID0gYXN5bmMgKFxuICBzd2FnZ2VyT3B0czogU3dhZ2dlck9wdHMgPSB7XG4gICAgcGF0aDogJy9zd2FnZ2VyJyxcbiAgICB0aXRsZTogJ2FwaScsXG4gICAgZGVzY3JpcHRpb246ICcnLFxuICAgIHZlcnNpb246ICcwLjAuMScsXG4gICAgZW5hYmxlQ1NQOiBmYWxzZSxcbiAgfSxcbiAgb3B0czogRmFzdGlmeUh0dHBPcHRpb25zPEZhc3RpZnlXaXRoWm9kU2VydmVyLCBGYXN0aWZ5QmFzZUxvZ2dlcj4gPSB7XG4gICAgbG9nZ2VyOiB0cnVlLFxuICB9LFxuKTogUHJvbWlzZTxGYXN0aWZ5V2l0aFpvZD4gPT4ge1xuICBjb25zdCBmYXN0aWZ5ID1cbiAgICBGYXN0aWZ5KG9wdHMpLndpdGhUeXBlUHJvdmlkZXI8RmFzdGlmeVpvZE9wZW5BcGlUeXBlUHJvdmlkZXI+KCk7XG5cbiAgZmFzdGlmeS5zZXRWYWxpZGF0b3JDb21waWxlcih2YWxpZGF0b3JDb21waWxlcik7XG4gIGZhc3RpZnkuc2V0U2VyaWFsaXplckNvbXBpbGVyKHNlcmlhbGl6ZXJDb21waWxlcik7XG5cbiAgYXdhaXQgZmFzdGlmeS5yZWdpc3RlcihmYXN0aWZ5Wm9kT3BlbkFwaVBsdWdpbik7XG5cbiAgYXdhaXQgcmVnaXN0ZXJTd2FnZ2VyKGZhc3RpZnksIHN3YWdnZXJPcHRzKTtcblxuICByZXR1cm4gZmFzdGlmeTtcbn07XG4iXX0=
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACzE,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACzE,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,YAAY,EACV,cAAc,EACd,YAAY,EACZ,uBAAuB,GACxB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './fastify';
|
|
2
2
|
export * from './types';
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9saWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsY0FBYyxXQUFXLENBQUM7QUFDMUIsY0FBYyxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdHlwZSB7IEZhc3RpZnlab2RPcGVuQXBpVHlwZVByb3ZpZGVyIH0gZnJvbSAnZmFzdGlmeS16b2Qtb3BlbmFwaSc7XG5leHBvcnQgKiBmcm9tICcuL2Zhc3RpZnknO1xuZXhwb3J0ICogZnJvbSAnLi90eXBlcyc7XG5leHBvcnQgdHlwZSB7XG4gIEZhc3RpZnlSZXF1ZXN0LFxuICBGYXN0aWZ5UmVwbHksXG4gIEhvb2tIYW5kbGVyRG9uZUZ1bmN0aW9uLFxufSBmcm9tICdmYXN0aWZ5JztcbiJdfQ==
|
package/dist/swagger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swagger.d.ts","sourceRoot":"","sources":["../lib/swagger.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,4BAA4B,EAG7B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,4BAA4B,CACxD,WAAW,
|
|
1
|
+
{"version":3,"file":"swagger.d.ts","sourceRoot":"","sources":["../lib/swagger.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,4BAA4B,EAG7B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,4BAA4B,CACxD,WAAW,CA2CZ,CAAC"}
|
package/dist/swagger.js
CHANGED
|
@@ -13,6 +13,15 @@ export const registerSwagger = async (fastify, opts) => {
|
|
|
13
13
|
description: opts.description,
|
|
14
14
|
version: opts.version,
|
|
15
15
|
},
|
|
16
|
+
components: {
|
|
17
|
+
securitySchemes: {
|
|
18
|
+
apiKey: {
|
|
19
|
+
type: 'apiKey',
|
|
20
|
+
name: 'Api-Key',
|
|
21
|
+
in: 'header',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
16
25
|
},
|
|
17
26
|
transform: fastifyZodOpenApiTransform,
|
|
18
27
|
transformObject: fastifyZodOpenApiTransformObject,
|
|
@@ -31,13 +40,10 @@ export const registerSwagger = async (fastify, opts) => {
|
|
|
31
40
|
next();
|
|
32
41
|
},
|
|
33
42
|
},
|
|
34
|
-
staticCSP:
|
|
43
|
+
staticCSP: opts.enableCSP,
|
|
35
44
|
transformStaticCSP: (header) => header,
|
|
36
|
-
|
|
37
|
-
transformSpecification: (swaggerObject, request, reply) => {
|
|
38
|
-
return swaggerObject;
|
|
39
|
-
},
|
|
45
|
+
transformSpecification: (swaggerObject) => swaggerObject,
|
|
40
46
|
transformSpecificationClone: true,
|
|
41
47
|
});
|
|
42
48
|
};
|
|
43
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3dhZ2dlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL2xpYi9zd2FnZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZDLE9BQU8sU0FBUyxNQUFNLHFCQUFxQixDQUFDO0FBQzVDLE9BQU8sRUFFTCwwQkFBMEIsRUFDMUIsZ0NBQWdDLEdBQ2pDLE1BQU0scUJBQXFCLENBQUM7QUFLN0I7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBRXhCLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUU7SUFDMUIsTUFBTSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtRQUM5QixPQUFPLEVBQUU7WUFDUCxPQUFPLEVBQUUsT0FBNEI7WUFDckMsSUFBSSxFQUFFO2dCQUNKLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDakIsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXO2dCQUM3QixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87YUFDdEI7WUFDRCxVQUFVLEVBQUU7Z0JBQ1YsZUFBZSxFQUFFO29CQUNmLE1BQU0sRUFBRTt3QkFDTixJQUFJLEVBQUUsUUFBUTt3QkFDZCxJQUFJLEVBQUUsU0FBUzt3QkFDZixFQUFFLEVBQUUsUUFBUTtxQkFDYjtpQkFDRjthQUNGO1NBQ0Y7UUFDRCxTQUFTLEVBQUUsMEJBQTBCO1FBQ3JDLGVBQWUsRUFBRSxnQ0FBZ0M7S0FDbEQsQ0FBQyxDQUFDO0lBRUgsTUFBTSxPQUFPLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRTtRQUNoQyxXQUFXLEVBQUUsSUFBSSxDQUFDLElBQUk7UUFDdEIsUUFBUSxFQUFFO1lBQ1IsWUFBWSxFQUFFLE1BQU07WUFDcEIsV0FBVyxFQUFFLEtBQUs7U0FDbkI7UUFDRCxPQUFPLEVBQUU7WUFDUCxTQUFTLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQWdCLEVBQUUsRUFBRTtnQkFDOUMsSUFBSSxFQUFFLENBQUM7WUFDVCxDQUFDO1lBQ0QsVUFBVSxFQUFFLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFnQixFQUFFLEVBQUU7Z0JBQy9DLElBQUksRUFBRSxDQUFDO1lBQ1QsQ0FBQztTQUNGO1FBQ0QsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1FBQ3pCLGtCQUFrQixFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNO1FBQ3RDLHNCQUFzQixFQUFFLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxhQUFhO1FBQ3hELDJCQUEyQixFQUFFLElBQUk7S0FDbEMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHN3YWdnZXIgZnJvbSAnQGZhc3RpZnkvc3dhZ2dlcic7XG5pbXBvcnQgc3dhZ2dlclVpIGZyb20gJ0BmYXN0aWZ5L3N3YWdnZXItdWknO1xuaW1wb3J0IHtcbiAgRmFzdGlmeVBsdWdpbkFzeW5jWm9kT3BlbkFwaSxcbiAgZmFzdGlmeVpvZE9wZW5BcGlUcmFuc2Zvcm0sXG4gIGZhc3RpZnlab2RPcGVuQXBpVHJhbnNmb3JtT2JqZWN0LFxufSBmcm9tICdmYXN0aWZ5LXpvZC1vcGVuYXBpJztcbmltcG9ydCB7IFpvZE9wZW5BcGlWZXJzaW9uIH0gZnJvbSAnem9kLW9wZW5hcGknO1xuXG5pbXBvcnQgeyBTd2FnZ2VyT3B0cyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIGFkZHMgc3dhZ2dlciB0byB0aGUgZmFzdGlmeSBpbnN0YW5jZVxuICovXG5leHBvcnQgY29uc3QgcmVnaXN0ZXJTd2FnZ2VyOiBGYXN0aWZ5UGx1Z2luQXN5bmNab2RPcGVuQXBpPFxuICBTd2FnZ2VyT3B0c1xuPiA9IGFzeW5jIChmYXN0aWZ5LCBvcHRzKSA9PiB7XG4gIGF3YWl0IGZhc3RpZnkucmVnaXN0ZXIoc3dhZ2dlciwge1xuICAgIG9wZW5hcGk6IHtcbiAgICAgIG9wZW5hcGk6ICczLjEuMCcgYXMgWm9kT3BlbkFwaVZlcnNpb24sXG4gICAgICBpbmZvOiB7XG4gICAgICAgIHRpdGxlOiBvcHRzLnRpdGxlLFxuICAgICAgICBkZXNjcmlwdGlvbjogb3B0cy5kZXNjcmlwdGlvbixcbiAgICAgICAgdmVyc2lvbjogb3B0cy52ZXJzaW9uLFxuICAgICAgfSxcbiAgICAgIGNvbXBvbmVudHM6IHtcbiAgICAgICAgc2VjdXJpdHlTY2hlbWVzOiB7XG4gICAgICAgICAgYXBpS2V5OiB7XG4gICAgICAgICAgICB0eXBlOiAnYXBpS2V5JyxcbiAgICAgICAgICAgIG5hbWU6ICdBcGktS2V5JyxcbiAgICAgICAgICAgIGluOiAnaGVhZGVyJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICAgIHRyYW5zZm9ybTogZmFzdGlmeVpvZE9wZW5BcGlUcmFuc2Zvcm0sXG4gICAgdHJhbnNmb3JtT2JqZWN0OiBmYXN0aWZ5Wm9kT3BlbkFwaVRyYW5zZm9ybU9iamVjdCxcbiAgfSk7XG5cbiAgYXdhaXQgZmFzdGlmeS5yZWdpc3Rlcihzd2FnZ2VyVWksIHtcbiAgICByb3V0ZVByZWZpeDogb3B0cy5wYXRoLFxuICAgIHVpQ29uZmlnOiB7XG4gICAgICBkb2NFeHBhbnNpb246ICdmdWxsJyxcbiAgICAgIGRlZXBMaW5raW5nOiBmYWxzZSxcbiAgICB9LFxuICAgIHVpSG9va3M6IHtcbiAgICAgIG9uUmVxdWVzdDogKHJlcXVlc3QsIHJlcGx5LCBuZXh0OiAoKSA9PiB2b2lkKSA9PiB7XG4gICAgICAgIG5leHQoKTtcbiAgICAgIH0sXG4gICAgICBwcmVIYW5kbGVyOiAocmVxdWVzdCwgcmVwbHksIG5leHQ6ICgpID0+IHZvaWQpID0+IHtcbiAgICAgICAgbmV4dCgpO1xuICAgICAgfSxcbiAgICB9LFxuICAgIHN0YXRpY0NTUDogb3B0cy5lbmFibGVDU1AsXG4gICAgdHJhbnNmb3JtU3RhdGljQ1NQOiAoaGVhZGVyKSA9PiBoZWFkZXIsXG4gICAgdHJhbnNmb3JtU3BlY2lmaWNhdGlvbjogKHN3YWdnZXJPYmplY3QpID0+IHN3YWdnZXJPYmplY3QsXG4gICAgdHJhbnNmb3JtU3BlY2lmaWNhdGlvbkNsb25lOiB0cnVlLFxuICB9KTtcbn07XG4iXX0=
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { FastifyBaseLogger, FastifyInstance } from 'fastify';
|
|
2
2
|
import type { FastifyZodOpenApiTypeProvider } from 'fastify-zod-openapi';
|
|
3
3
|
import * as http from 'http';
|
|
4
|
-
export type
|
|
5
|
-
export
|
|
4
|
+
export type FastifyWithZodServer = http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
5
|
+
export type FastifyWithZod = FastifyInstance<FastifyWithZodServer, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, FastifyBaseLogger, FastifyZodOpenApiTypeProvider>;
|
|
6
|
+
export type SwaggerOpts = {
|
|
6
7
|
path: string;
|
|
7
8
|
title: string;
|
|
8
9
|
description: string;
|
|
9
10
|
version: string;
|
|
10
|
-
|
|
11
|
+
enableCSP: boolean;
|
|
12
|
+
};
|
|
11
13
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAC5C,OAAO,IAAI,CAAC,eAAe,EAC3B,OAAO,IAAI,CAAC,cAAc,CAC3B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,eAAe,CAC1C,oBAAoB,EACpB,IAAI,CAAC,eAAe,EACpB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC,EACzC,iBAAiB,EACjB,6BAA6B,CAC9B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC"}
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9saWIvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZhc3RpZnlCYXNlTG9nZ2VyLCBGYXN0aWZ5SW5zdGFuY2UgfSBmcm9tICdmYXN0aWZ5JztcbmltcG9ydCB0eXBlIHsgRmFzdGlmeVpvZE9wZW5BcGlUeXBlUHJvdmlkZXIgfSBmcm9tICdmYXN0aWZ5LXpvZC1vcGVuYXBpJztcbmltcG9ydCAqIGFzIGh0dHAgZnJvbSAnaHR0cCc7XG5cbmV4cG9ydCB0eXBlIEZhc3RpZnlXaXRoWm9kU2VydmVyID0gaHR0cC5TZXJ2ZXI8XG4gIHR5cGVvZiBodHRwLkluY29taW5nTWVzc2FnZSxcbiAgdHlwZW9mIGh0dHAuU2VydmVyUmVzcG9uc2Vcbj47XG5cbmV4cG9ydCB0eXBlIEZhc3RpZnlXaXRoWm9kID0gRmFzdGlmeUluc3RhbmNlPFxuICBGYXN0aWZ5V2l0aFpvZFNlcnZlcixcbiAgaHR0cC5JbmNvbWluZ01lc3NhZ2UsXG4gIGh0dHAuU2VydmVyUmVzcG9uc2U8aHR0cC5JbmNvbWluZ01lc3NhZ2U+LFxuICBGYXN0aWZ5QmFzZUxvZ2dlcixcbiAgRmFzdGlmeVpvZE9wZW5BcGlUeXBlUHJvdmlkZXJcbj47XG5cbmV4cG9ydCB0eXBlIFN3YWdnZXJPcHRzID0ge1xuICBwYXRoOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIHZlcnNpb246IHN0cmluZztcbiAgZW5hYmxlQ1NQOiBib29sZWFuO1xufTtcbiJdfQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rosen-bridge/fastify-enhanced",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "a wrapper around fastify web framework to make it even better",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -30,12 +30,16 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@fastify/swagger": "^9.5.1",
|
|
32
32
|
"@fastify/swagger-ui": "^5.2.3",
|
|
33
|
-
"@rosen-bridge/json-bigint": "^1.1.0",
|
|
34
33
|
"fastify": "^5.3.3",
|
|
35
34
|
"fastify-zod-openapi": "^4.1.2",
|
|
36
|
-
"zod": "^3.25.56",
|
|
37
35
|
"zod-openapi": "^4.2.4"
|
|
38
36
|
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"zod": "^3.21.4"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"zod": "^3.21.4"
|
|
42
|
+
},
|
|
39
43
|
"engines": {
|
|
40
44
|
"node": ">=22.18.0",
|
|
41
45
|
"npm": "11.6.2"
|
package/dist/jsonParser.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { ContentTypeParserDoneFunction } from 'fastify/types/content-type-parser';
|
|
2
|
-
import { JsonBigIntFactory } from '@rosen-bridge/json-bigint';
|
|
3
|
-
export declare const makeJsonParser: (jsonHandler: ReturnType<typeof JsonBigIntFactory>) => (req: unknown, body: string, done: ContentTypeParserDoneFunction) => void;
|
|
4
|
-
//# sourceMappingURL=jsonParser.d.ts.map
|
package/dist/jsonParser.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jsonParser.d.ts","sourceRoot":"","sources":["../lib/jsonParser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,mCAAmC,CAAC;AAElF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,eAAO,MAAM,cAAc,GACzB,aAAa,UAAU,CAAC,OAAO,iBAAiB,CAAC,MAEzC,KAAK,OAAO,EAAE,MAAM,MAAM,EAAE,MAAM,6BAA6B,SAgBxE,CAAC"}
|
package/dist/jsonParser.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const makeJsonParser = (jsonHandler) => {
|
|
2
|
-
return (req, body, done) => {
|
|
3
|
-
try {
|
|
4
|
-
const json = jsonHandler.parse(body);
|
|
5
|
-
done(null, json);
|
|
6
|
-
}
|
|
7
|
-
catch (err) {
|
|
8
|
-
if (err instanceof Error || err === null) {
|
|
9
|
-
done(err, undefined);
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
const wrappedErr = new Error(`An unexpected error occurred while trying to parse request body`, { cause: err });
|
|
13
|
-
done(wrappedErr, undefined);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvblBhcnNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL2xpYi9qc29uUGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxDQUM1QixXQUFpRCxFQUNqRCxFQUFFO0lBQ0YsT0FBTyxDQUFDLEdBQVksRUFBRSxJQUFZLEVBQUUsSUFBbUMsRUFBRSxFQUFFO1FBQ3pFLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNuQixDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLElBQUksR0FBRyxZQUFZLEtBQUssSUFBSSxHQUFHLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDdkIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sVUFBVSxHQUFHLElBQUksS0FBSyxDQUMxQixpRUFBaUUsRUFDakUsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQ2YsQ0FBQztnQkFDRixJQUFJLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQzlCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQyxDQUFDO0FBQ0osQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29udGVudFR5cGVQYXJzZXJEb25lRnVuY3Rpb24gfSBmcm9tICdmYXN0aWZ5L3R5cGVzL2NvbnRlbnQtdHlwZS1wYXJzZXInO1xuXG5pbXBvcnQgeyBKc29uQmlnSW50RmFjdG9yeSB9IGZyb20gJ0Byb3Nlbi1icmlkZ2UvanNvbi1iaWdpbnQnO1xuXG5leHBvcnQgY29uc3QgbWFrZUpzb25QYXJzZXIgPSAoXG4gIGpzb25IYW5kbGVyOiBSZXR1cm5UeXBlPHR5cGVvZiBKc29uQmlnSW50RmFjdG9yeT4sXG4pID0+IHtcbiAgcmV0dXJuIChyZXE6IHVua25vd24sIGJvZHk6IHN0cmluZywgZG9uZTogQ29udGVudFR5cGVQYXJzZXJEb25lRnVuY3Rpb24pID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QganNvbiA9IGpzb25IYW5kbGVyLnBhcnNlKGJvZHkpO1xuICAgICAgZG9uZShudWxsLCBqc29uKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBFcnJvciB8fCBlcnIgPT09IG51bGwpIHtcbiAgICAgICAgZG9uZShlcnIsIHVuZGVmaW5lZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB3cmFwcGVkRXJyID0gbmV3IEVycm9yKFxuICAgICAgICAgIGBBbiB1bmV4cGVjdGVkIGVycm9yIG9jY3VycmVkIHdoaWxlIHRyeWluZyB0byBwYXJzZSByZXF1ZXN0IGJvZHlgLFxuICAgICAgICAgIHsgY2F1c2U6IGVyciB9LFxuICAgICAgICApO1xuICAgICAgICBkb25lKHdyYXBwZWRFcnIsIHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xufTtcbiJdfQ==
|