@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 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: options.swagger.path || "/swagger",
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;
@@ -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: options.swagger.path || "/swagger",
188
+ path: swaggerPath,
152
189
  documentation: options.swagger.documentation,
153
190
  }),
154
191
  );
@@ -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
@@ -13,7 +13,7 @@
13
13
  "types": "./dist/*.d.ts"
14
14
  }
15
15
  },
16
- "version": "0.3.5",
16
+ "version": "0.3.6",
17
17
  "homepage": "https://bunstone.diario.one/",
18
18
  "repository": {
19
19
  "url": "https://github.com/diariodaregiao/bunstone.git",
@@ -1,5 +1,3 @@
1
1
  {
2
- "recommendations": [
3
- "biomejs.biome"
4
- ]
2
+ "recommendations": ["biomejs.biome"]
5
3
  }
@@ -1,42 +1,44 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
3
- "assist": {
4
- "actions": {
5
- "source": {
6
- "organizeImports": "on"
7
- }
8
- }
9
- },
10
- "linter": {
11
- "enabled": true,
12
- "rules": {
13
- "recommended": true,
14
- "suspicious": {
15
- "noExplicitAny": "off"
16
- },
17
- "complexity": {
18
- "noBannedTypes": "off",
19
- "noArguments": "off",
20
- "noStaticOnlyClass": "off"
21
- },
22
- "correctness": {
23
- "noUnusedImports": "error"
24
- },
25
- "style": {
26
- "useImportType": "off"
27
- }
28
- }
29
- },
30
- "formatter": {
31
- "enabled": true,
32
- "indentStyle": "tab"
33
- },
34
- "javascript": {
35
- "formatter": {
36
- "quoteStyle": "double"
37
- },
38
- "parser": {
39
- "unsafeParameterDecoratorsEnabled": true
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 React, { useState } from "react";
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
  >