@grupodiariodaregiao/bunstone 0.3.5 → 0.3.6
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/dist/index.js +28 -1
- package/dist/lib/types/options.d.ts +8 -0
- package/lib/app-startup.ts +38 -1
- package/lib/types/options.ts +8 -0
- package/package.json +1 -1
- package/starter/.vscode/extensions.json +1 -3
- package/starter/biome.json +42 -40
- package/starter/src/views/Welcome.tsx +3 -1
package/dist/index.js
CHANGED
|
@@ -103580,8 +103580,35 @@ class AppStartup {
|
|
|
103580
103580
|
AppStartup.elysia.use(cors(options.cors));
|
|
103581
103581
|
}
|
|
103582
103582
|
if (options?.swagger) {
|
|
103583
|
+
const swaggerPath = options.swagger.path || "/swagger";
|
|
103584
|
+
if (options.swagger.auth) {
|
|
103585
|
+
const { username, password } = options.swagger.auth;
|
|
103586
|
+
const expectedToken = Buffer.from(`${username}:${password}`).toString("base64");
|
|
103587
|
+
AppStartup.elysia.onBeforeHandle(({ request, set }) => {
|
|
103588
|
+
const url = new URL(request.url);
|
|
103589
|
+
if (url.pathname.startsWith(swaggerPath)) {
|
|
103590
|
+
const authHeader = request.headers.get("authorization");
|
|
103591
|
+
let validCredentials = false;
|
|
103592
|
+
if (authHeader) {
|
|
103593
|
+
const parts = authHeader.trim().split(/\s+/);
|
|
103594
|
+
if (parts.length >= 2) {
|
|
103595
|
+
const scheme = parts[0] ?? "";
|
|
103596
|
+
const token2 = parts.slice(1).join(" ");
|
|
103597
|
+
if (scheme.toLowerCase() === "basic" && token2 === expectedToken) {
|
|
103598
|
+
validCredentials = true;
|
|
103599
|
+
}
|
|
103600
|
+
}
|
|
103601
|
+
}
|
|
103602
|
+
if (!validCredentials) {
|
|
103603
|
+
set.status = 401;
|
|
103604
|
+
set.headers["WWW-Authenticate"] = 'Basic realm="Swagger Documentation"';
|
|
103605
|
+
return new Response("Unauthorized", { status: 401 });
|
|
103606
|
+
}
|
|
103607
|
+
}
|
|
103608
|
+
});
|
|
103609
|
+
}
|
|
103583
103610
|
AppStartup.elysia.use(swagger({
|
|
103584
|
-
path:
|
|
103611
|
+
path: swaggerPath,
|
|
103585
103612
|
documentation: options.swagger.documentation
|
|
103586
103613
|
}));
|
|
103587
103614
|
}
|
|
@@ -58,6 +58,14 @@ export type Options = {
|
|
|
58
58
|
description: string;
|
|
59
59
|
}[];
|
|
60
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Optional Basic Auth protection for the Swagger documentation page.
|
|
63
|
+
* When set, the documentation route will require HTTP Basic Authentication.
|
|
64
|
+
*/
|
|
65
|
+
auth?: {
|
|
66
|
+
username: string;
|
|
67
|
+
password: string;
|
|
68
|
+
};
|
|
61
69
|
};
|
|
62
70
|
/** Global rate limit configuration applied to all endpoints */
|
|
63
71
|
rateLimit?: RateLimitGlobalConfig;
|
package/lib/app-startup.ts
CHANGED
|
@@ -146,9 +146,46 @@ export class AppStartup {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
if (options?.swagger) {
|
|
149
|
+
const swaggerPath = options.swagger.path || "/swagger";
|
|
150
|
+
|
|
151
|
+
if (options.swagger.auth) {
|
|
152
|
+
const { username, password } = options.swagger.auth;
|
|
153
|
+
const expectedToken = Buffer.from(`${username}:${password}`).toString(
|
|
154
|
+
"base64",
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
AppStartup.elysia.onBeforeHandle(({ request, set }) => {
|
|
158
|
+
const url = new URL(request.url);
|
|
159
|
+
if (url.pathname.startsWith(swaggerPath)) {
|
|
160
|
+
const authHeader = request.headers.get("authorization");
|
|
161
|
+
let validCredentials = false;
|
|
162
|
+
|
|
163
|
+
if (authHeader) {
|
|
164
|
+
const parts = authHeader.trim().split(/\s+/);
|
|
165
|
+
if (parts.length >= 2) {
|
|
166
|
+
const scheme = parts[0] ?? "";
|
|
167
|
+
const token = parts.slice(1).join(" ");
|
|
168
|
+
if (
|
|
169
|
+
scheme.toLowerCase() === "basic" &&
|
|
170
|
+
token === expectedToken
|
|
171
|
+
) {
|
|
172
|
+
validCredentials = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!validCredentials) {
|
|
177
|
+
set.status = 401;
|
|
178
|
+
set.headers["WWW-Authenticate"] =
|
|
179
|
+
'Basic realm="Swagger Documentation"';
|
|
180
|
+
return new Response("Unauthorized", { status: 401 });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
149
186
|
AppStartup.elysia.use(
|
|
150
187
|
swagger({
|
|
151
|
-
path:
|
|
188
|
+
path: swaggerPath,
|
|
152
189
|
documentation: options.swagger.documentation,
|
|
153
190
|
}),
|
|
154
191
|
);
|
package/lib/types/options.ts
CHANGED
|
@@ -58,6 +58,14 @@ export type Options = {
|
|
|
58
58
|
};
|
|
59
59
|
tags?: { name: string; description: string }[];
|
|
60
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Optional Basic Auth protection for the Swagger documentation page.
|
|
63
|
+
* When set, the documentation route will require HTTP Basic Authentication.
|
|
64
|
+
*/
|
|
65
|
+
auth?: {
|
|
66
|
+
username: string;
|
|
67
|
+
password: string;
|
|
68
|
+
};
|
|
61
69
|
};
|
|
62
70
|
/** Global rate limit configuration applied to all endpoints */
|
|
63
71
|
rateLimit?: RateLimitGlobalConfig;
|
package/package.json
CHANGED
package/starter/biome.json
CHANGED
|
@@ -1,42 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
|
|
3
|
+
"root": false,
|
|
4
|
+
"assist": {
|
|
5
|
+
"actions": {
|
|
6
|
+
"source": {
|
|
7
|
+
"organizeImports": "on"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"linter": {
|
|
12
|
+
"enabled": true,
|
|
13
|
+
"rules": {
|
|
14
|
+
"recommended": true,
|
|
15
|
+
"suspicious": {
|
|
16
|
+
"noExplicitAny": "off"
|
|
17
|
+
},
|
|
18
|
+
"complexity": {
|
|
19
|
+
"noBannedTypes": "off",
|
|
20
|
+
"noArguments": "off",
|
|
21
|
+
"noStaticOnlyClass": "off"
|
|
22
|
+
},
|
|
23
|
+
"correctness": {
|
|
24
|
+
"noUnusedImports": "error"
|
|
25
|
+
},
|
|
26
|
+
"style": {
|
|
27
|
+
"useImportType": "off"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"formatter": {
|
|
32
|
+
"enabled": true,
|
|
33
|
+
"indentStyle": "space",
|
|
34
|
+
"indentWidth": 2
|
|
35
|
+
},
|
|
36
|
+
"javascript": {
|
|
37
|
+
"formatter": {
|
|
38
|
+
"quoteStyle": "double"
|
|
39
|
+
},
|
|
40
|
+
"parser": {
|
|
41
|
+
"unsafeParameterDecoratorsEnabled": true
|
|
42
|
+
}
|
|
43
|
+
}
|
|
42
44
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from "react";
|
|
2
2
|
|
|
3
3
|
export const Welcome = ({
|
|
4
4
|
message,
|
|
@@ -20,6 +20,7 @@ export const Welcome = ({
|
|
|
20
20
|
</p>
|
|
21
21
|
<div className="flex items-center justify-center gap-4">
|
|
22
22
|
<button
|
|
23
|
+
type="button"
|
|
23
24
|
onClick={() => setCount(count - 1)}
|
|
24
25
|
className="bg-white border border-indigo-200 px-3 py-1 rounded shadow-sm hover:bg-indigo-100"
|
|
25
26
|
>
|
|
@@ -29,6 +30,7 @@ export const Welcome = ({
|
|
|
29
30
|
{count}
|
|
30
31
|
</span>
|
|
31
32
|
<button
|
|
33
|
+
type="button"
|
|
32
34
|
onClick={() => setCount(count + 1)}
|
|
33
35
|
className="bg-white border border-indigo-200 px-3 py-1 rounded shadow-sm hover:bg-indigo-100"
|
|
34
36
|
>
|