azurajs-scalar 2.0.0 → 2.0.2

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.d.ts CHANGED
@@ -26,6 +26,7 @@ interface ProxyOptions {
26
26
  apiSpecUrl: string;
27
27
  proxyUrlPath: string;
28
28
  app: AzuraClient;
29
+ baseUrl: string;
29
30
  }
30
31
  interface SetupDocsRouteOptions extends ScalarConfigType {
31
32
  docPath: string;
@@ -47,7 +48,7 @@ declare class Scalar {
47
48
 
48
49
  declare function setupScalarDocs({ app, docPath, customHtmlPath, apiSpecUrl, proxyUrl, }: SetupDocsRouteOptions): Promise<void>;
49
50
 
50
- declare function proxyMiddleware({ apiSpecUrl, app, proxyUrlPath, }: ProxyOptions): void;
51
+ declare function proxyMiddleware({ apiSpecUrl, app, baseUrl, proxyUrlPath, }: ProxyOptions): void;
51
52
 
52
53
  /**
53
54
  * @fileoverview Store utility for managing application state
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ function debug(message, ...optionalParams) {
23
23
  function proxyMiddleware({
24
24
  apiSpecUrl,
25
25
  app,
26
+ baseUrl,
26
27
  proxyUrlPath
27
28
  }) {
28
29
  debug("Setting up proxy middleware with options:", {
@@ -32,7 +33,13 @@ function proxyMiddleware({
32
33
  app.get(proxyUrlPath, () => {
33
34
  });
34
35
  return app.use(proxyUrlPath, async (req, res) => {
35
- debug("Proxy middleware hit with request:", req.method, req.url, "headers:", req.headers);
36
+ debug(
37
+ "Proxy middleware hit with request:",
38
+ req.method,
39
+ req.url,
40
+ "headers:",
41
+ req.headers
42
+ );
36
43
  try {
37
44
  if (!req.url || !req.method) {
38
45
  debug("Invalid request - missing url or method");
@@ -40,10 +47,10 @@ function proxyMiddleware({
40
47
  return;
41
48
  }
42
49
  logger("info", `[PROXY] ${req.method} ${req.url}`);
43
- const url = new URL(`http://localhost${req.url}`);
44
- const scalarUrl = url.searchParams.get("scalar_url");
50
+ const queryParams = new URLSearchParams(req.url.split("?")[1] || "");
51
+ const scalarUrl = queryParams.get("scalar_url");
45
52
  debug("Extracted scalar_url from query params:", scalarUrl);
46
- const targetUrl = scalarUrl || apiSpecUrl + url.pathname + url.search;
53
+ const targetUrl = scalarUrl || apiSpecUrl;
47
54
  debug("Determined target URL:", targetUrl);
48
55
  const target = new URL(targetUrl);
49
56
  const apiBase = new URL(apiSpecUrl);
@@ -53,8 +60,11 @@ function proxyMiddleware({
53
60
  "apiBase origin:",
54
61
  apiBase.origin
55
62
  );
56
- if (target.origin !== apiBase.origin) {
57
- logger("warn", `Blocked cross-origin: ${targetUrl}`);
63
+ const baseUrlOrigin = new URL(baseUrl).origin;
64
+ const isSameAsApiSpecOrigin = target.origin === apiBase.origin;
65
+ const isSameAsBaseUrlOrigin = target.origin === baseUrlOrigin;
66
+ if (!isSameAsApiSpecOrigin && !isSameAsBaseUrlOrigin) {
67
+ logger("warn", `Blocked cross-origin: ${targetUrl} (expected origins: ${apiBase.origin} or ${baseUrlOrigin})`);
58
68
  res.status(403).json({ error: "Cross-origin blocked" });
59
69
  return;
60
70
  }
@@ -75,18 +85,28 @@ function proxyMiddleware({
75
85
  headers,
76
86
  body
77
87
  });
78
- debug(
79
- "Fetch response received with status:",
80
- proxyRes.status
81
- );
88
+ debug("Fetch response received with status:", proxyRes.status);
82
89
  res.setHeader("Access-Control-Allow-Origin", "*");
83
90
  res.setHeader(
84
91
  "Access-Control-Allow-Methods",
85
- "GET,POST,PUT,PATCH,DELETE,OPTIONS"
92
+ "GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD"
86
93
  );
87
94
  res.setHeader("Access-Control-Allow-Headers", "*");
95
+ res.setHeader("Access-Control-Expose-Headers", "*");
88
96
  for (const [key, value] of proxyRes.headers.entries()) {
89
- if (!key.toLowerCase().startsWith("access-control-")) {
97
+ if (![
98
+ "connection",
99
+ "keep-alive",
100
+ "transfer-encoding",
101
+ "te",
102
+ "trailer",
103
+ "upgrade",
104
+ "host",
105
+ "access-control-allow-origin",
106
+ "access-control-allow-methods",
107
+ "access-control-allow-headers",
108
+ "access-control-expose-headers"
109
+ ].includes(key.toLowerCase())) {
90
110
  res.setHeader(key, value);
91
111
  }
92
112
  }
@@ -95,12 +115,12 @@ function proxyMiddleware({
95
115
  res.end();
96
116
  return;
97
117
  }
98
- const buffer = Buffer.from(await proxyRes.arrayBuffer());
99
- debug(
100
- "Response buffer created with length:",
101
- buffer.length
102
- );
103
- res.send(buffer);
118
+ const responseBody = await proxyRes.text();
119
+ debug("Response body length:", responseBody.length);
120
+ if (!res.getHeader("content-length")) {
121
+ res.setHeader("content-length", Buffer.byteLength(responseBody));
122
+ }
123
+ res.status(proxyRes.status).send(responseBody);
104
124
  } catch (err) {
105
125
  debug("Error in proxy middleware:", err);
106
126
  logger("error", `[PROXY] Error: ${err}`);
@@ -261,7 +281,8 @@ var Scalar = class {
261
281
  proxyMiddleware({
262
282
  apiSpecUrl,
263
283
  proxyUrlPath: proxyPath,
264
- app: normalizedConfig.app
284
+ app: normalizedConfig.app,
285
+ baseUrl: normalizedConfig.baseUrl
265
286
  });
266
287
  debug("proxyMiddleware called");
267
288
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/types.ts","../src/middleware/proxy.ts","../src/utils/debug.ts","../src/setupDocsRoute.ts","../src/utils/store.ts","../src/client.ts"],"sourcesContent":["import { AzuraClient } from \"azurajs\";\nimport { NextFunction, RequestServer, ResponseServer } from \"azurajs/types\";\n\nexport interface ScalarConfigType {\n baseUrl: string;\n proxyPath?: string;\n docPath?: string;\n apiSpecPath?: string;\n customHtmlPath?: string;\n app: AzuraClient;\n}\n\nexport interface ScalarStoreType {\n proxy_url?: string;\n api_spec_url?: string;\n doc_url?: string;\n custom_html_path?: string;\n}\n\nexport type ProxyMiddlewareType = (\n req: RequestServer,\n res: ResponseServer,\n next?: NextFunction,\n) => Promise<void>;\n\nexport class ScalarError extends Error {\n constructor(\n public readonly message: string,\n public readonly code: string,\n public readonly statusCode: number,\n ) {\n super(message);\n Object.setPrototypeOf(this, ScalarError.prototype);\n }\n}\n\nexport interface ProxyOptions {\n apiSpecUrl: string;\n proxyUrlPath: string;\n app: AzuraClient;\n}\n\nexport interface SetupDocsRouteOptions extends ScalarConfigType {\n docPath: string;\n proxyUrl: string;\n apiSpecUrl: string;\n}\n","import { ProxyOptions } from \"../config/types\";\nimport { logger } from \"azurajs/logger\";\nimport { debug } from \"../utils/debug\";\n\nexport function proxyMiddleware({\n apiSpecUrl,\n app,\n proxyUrlPath,\n}: ProxyOptions) {\n debug(\"Setting up proxy middleware with options:\", {\n apiSpecUrl,\n proxyUrlPath,\n });\n app.get(proxyUrlPath, () => {});\n return app.use(proxyUrlPath, async (req, res) => {\n debug(\"Proxy middleware hit with request:\", req.method, req.url, \"headers:\", req.headers);\n try {\n if (!req.url || !req.method) {\n debug(\"Invalid request - missing url or method\");\n res.status(400).json({ error: \"Invalid request\" });\n return;\n }\n\n logger(\"info\", `[PROXY] ${req.method} ${req.url}`);\n\n // Extract target URL from scalar_url query param\n const url = new URL(`http://localhost${req.url}`);\n const scalarUrl = url.searchParams.get(\"scalar_url\");\n debug(\"Extracted scalar_url from query params:\", scalarUrl);\n\n // Determine target URL\n const targetUrl = scalarUrl || apiSpecUrl + url.pathname + url.search;\n debug(\"Determined target URL:\", targetUrl);\n\n // Validate same origin for security\n const target = new URL(targetUrl);\n const apiBase = new URL(apiSpecUrl);\n debug(\n \"Validating same origin - target origin:\",\n target.origin,\n \"apiBase origin:\",\n apiBase.origin,\n );\n if (target.origin !== apiBase.origin) {\n logger(\"warn\", `Blocked cross-origin: ${targetUrl}`);\n res.status(403).json({ error: \"Cross-origin blocked\" });\n return;\n }\n\n logger(\"info\", `[PROXY] Forwarding to: ${targetUrl}`);\n\n // Prepare headers and body\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n headers[key] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n headers.host = apiBase.host;\n debug(\"Prepared headers:\", headers);\n\n const body = [\"GET\", \"HEAD\"].includes(req.method)\n ? undefined\n : typeof req.body === \"string\"\n ? req.body\n : JSON.stringify(req.body);\n debug(\"Request body:\", body);\n\n // Make request to target\n debug(\"Making fetch request to target URL:\", targetUrl);\n const proxyRes = await fetch(targetUrl, {\n method: req.method,\n headers,\n body,\n });\n debug(\n \"Fetch response received with status:\",\n proxyRes.status,\n );\n\n // Set response headers\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\n \"Access-Control-Allow-Methods\",\n \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n );\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n\n for (const [key, value] of proxyRes.headers.entries()) {\n if (!key.toLowerCase().startsWith(\"access-control-\")) {\n res.setHeader(key, value);\n }\n }\n\n if (req.method === \"OPTIONS\") {\n debug(\"OPTIONS request, ending response\");\n res.end();\n return;\n }\n\n const buffer = Buffer.from(await proxyRes.arrayBuffer());\n debug(\n \"Response buffer created with length:\",\n buffer.length,\n );\n res.send(buffer);\n } catch (err) {\n debug(\"Error in proxy middleware:\", err);\n logger(\"error\", `[PROXY] Error: ${err}`);\n res.status(500).json({ error: \"Proxy error\", details: String(err) });\n }\n });\n}\n","/**\n * Debug utility function that only logs when DEBUG environment variable is set to 'true'\n */\n\nexport function debug(message: string, ...optionalParams: any[]) {\n if (process.env.DEBUG === 'true' || process.env.DEBUG === '1') {\n console.log(`[DEBUG] ${message}`, ...optionalParams);\n }\n}","import { logger } from \"azurajs/logger\";\nimport fs from \"fs\";\nimport path from \"node:path\";\nimport { ScalarError, SetupDocsRouteOptions } from \"./config/types\";\nimport { debug } from \"./utils/debug\";\n\nexport async function setupScalarDocs({\n app,\n docPath,\n customHtmlPath,\n apiSpecUrl,\n proxyUrl,\n}: SetupDocsRouteOptions) {\n debug(\"Setting up docs route with options:\", { docPath, customHtmlPath, apiSpecUrl, proxyUrl });\n\n return app.get(docPath, (req, res) => {\n debug(\"Docs route hit with request:\", req.method, req.url);\n try {\n if (!proxyUrl || !apiSpecUrl) {\n debug(\"Missing required URLs - proxyUrl:\", proxyUrl, \"apiSpecUrl:\", apiSpecUrl);\n throw new ScalarError(\n \"Missing required URLs\",\n \"STORE_VALUES_MISSING\",\n 500,\n );\n }\n\n const htmlPath =\n customHtmlPath || path.join(__dirname, \"../api-docs.html\");\n debug(\"HTML template path:\", htmlPath);\n\n if (!fs.existsSync(htmlPath)) {\n debug(\"HTML template not found at path:\", htmlPath);\n throw new ScalarError(\n \"HTML template not found\",\n \"HTML_TEMPLATE_NOT_FOUND\",\n 404,\n );\n }\n\n const html = fs.readFileSync(htmlPath, \"utf-8\");\n debug(\"HTML template read successfully, length:\", html.length);\n\n const processedHtml = html\n .replace(/&{proxy_url}/g, proxyUrl)\n .replace(/&{api_spec_url}/g, apiSpecUrl);\n debug(\"HTML template processed with proxyUrl and apiSpecUrl\");\n\n return res.send(processedHtml);\n } catch (error) {\n debug(\"Error in docs route:\", error);\n if (error instanceof ScalarError) {\n logger(\"error\", `[ScalarError] ${error.message}`);\n return res.status(error.statusCode).json({ message: error.message });\n } else {\n logger(\"error\", String(error));\n return res.status(500).json({ message: \"Server error\" });\n }\n }\n });\n}\n","/**\n * @fileoverview Store utility for managing application state\n * This module provides a typed store for managing scalar configuration values\n */\n\nimport { ScalarStoreType } from \"../config/types\";\n\n/**\n * Typed store class for managing scalar configuration values\n */\nclass ScalarStore {\n private store: Map<keyof ScalarStoreType, string | undefined> = new Map();\n\n /**\n * Sets a value in the store\n * @param key The key to set\n * @param value The value to set (if undefined, the key will be removed)\n */\n set<K extends keyof ScalarStoreType>(\n key: K,\n value: ScalarStoreType[K],\n ): void {\n this.store.set(key, value as string | undefined);\n }\n\n /**\n * Gets a value from the store\n * @param key The key to get\n * @returns The value associated with the key\n */\n get<K extends keyof ScalarStoreType>(key: K): ScalarStoreType[K] {\n return this.store.get(key) as ScalarStoreType[K];\n }\n\n /**\n * Checks if a key exists in the store\n * @param key The key to check\n * @returns True if the key exists, false otherwise\n */\n has(key: keyof ScalarStoreType): boolean {\n return this.store.has(key);\n }\n\n /**\n * Deletes a key from the store\n * @param key The key to delete\n * @returns True if the key existed and was deleted, false otherwise\n */\n delete(key: keyof ScalarStoreType): boolean {\n return this.store.delete(key);\n }\n\n /**\n * Clears all values from the store\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Gets all values from the store\n * @returns An object containing all key-value pairs in the store\n */\n getAll(): ScalarStoreType {\n const result: Partial<ScalarStoreType> = {};\n for (const [key, value] of this.store.entries()) {\n result[key] = value as ScalarStoreType[keyof ScalarStoreType];\n }\n return result as ScalarStoreType;\n }\n\n // Index signature to allow direct property access\n [key: string]: any;\n}\n\nexport const store = new ScalarStore();\n","/**\n * Scalar client for API documentation\n */\nimport {\n ScalarConfigType,\n ScalarError,\n SetupDocsRouteOptions,\n} from \"./config/types\";\nimport { proxyMiddleware } from \"./middleware/proxy\";\nimport { setupScalarDocs } from \"./setupDocsRoute\";\nimport { store } from \"./utils/store\";\nimport { debug } from \"./utils/debug\";\n\nexport class Scalar {\n constructor(config: ScalarConfigType) {\n debug(\"Scalar constructor called with config:\", config);\n\n // Normalize baseUrl to ensure it's a valid absolute URL before validation\n const normalizedConfig = { ...config };\n normalizedConfig.baseUrl = this.normalizeBaseUrl(config.baseUrl);\n debug(\"Normalized config:\", normalizedConfig);\n\n // Validate the configuration\n this.validateConfig(normalizedConfig);\n\n // Set default paths if not provided\n const proxyPath = normalizedConfig.proxyPath || \"/scalar/proxy\";\n const docPath = normalizedConfig.docPath || \"/docs\";\n const apiSpecPath = normalizedConfig.apiSpecPath || \"\";\n debug(\n \"Using paths - proxyPath:\",\n proxyPath,\n \"docPath:\",\n docPath,\n \"apiSpecPath:\",\n apiSpecPath,\n );\n\n // Calculate full URLs from baseUrl and paths\n const proxyUrl = this.joinUrl(normalizedConfig.baseUrl, proxyPath);\n const docUrl = this.joinUrl(normalizedConfig.baseUrl, docPath);\n const apiSpecUrl = this.joinUrl(normalizedConfig.baseUrl, apiSpecPath);\n debug(\n \"Calculated URLs - proxyUrl:\",\n proxyUrl,\n \"docUrl:\",\n docUrl,\n \"apiSpecUrl:\",\n apiSpecUrl,\n );\n\n // Store the calculated URLs\n store.set(\"proxy_url\", proxyUrl);\n store.set(\"api_spec_url\", apiSpecUrl);\n store.set(\"doc_url\", docUrl);\n debug(\"Stored URLs in store\");\n\n // Call setup with the calculated URLs\n setupScalarDocs({\n ...normalizedConfig,\n proxyUrl,\n docPath,\n apiSpecUrl,\n });\n debug(\"setupScalarDocs called\");\n\n // Setup proxy middleware\n proxyMiddleware({\n apiSpecUrl,\n proxyUrlPath: proxyPath,\n app: normalizedConfig.app,\n });\n debug(\"proxyMiddleware called\");\n }\n\n private joinUrl(baseUrl: string, path: string): string {\n // Normalize the baseUrl to ensure it ends with a slash\n const normalizedBaseUrl = baseUrl.endsWith(\"/\") ? baseUrl : baseUrl + \"/\";\n\n // Normalize the path to ensure it starts with a slash\n const normalizedPath = path.startsWith(\"/\") ? path : \"/\" + path;\n\n // Join the baseUrl and path, removing any double slashes\n return normalizedBaseUrl.replace(/\\/$/, \"\") + normalizedPath;\n }\n\n private normalizeBaseUrl(baseUrl: string): string {\n if (!baseUrl) {\n throw new ScalarError(\n \"baseUrl is required\",\n \"MISSING_REQUIRED_CONFIG\",\n 400,\n );\n }\n\n // If baseUrl doesn't start with a protocol, prepend http://\n if (!/^https?:\\/\\//i.test(baseUrl)) {\n return \"http://\" + baseUrl;\n }\n\n return baseUrl;\n }\n\n private validateConfig(config: ScalarConfigType): void {\n if (!config.baseUrl) {\n throw new ScalarError(\n \"baseUrl is required\",\n \"MISSING_REQUIRED_CONFIG\",\n 400,\n );\n }\n\n try {\n // Validate baseUrl\n debug(\"Validating baseUrl:\", config.baseUrl);\n new URL(config.baseUrl);\n\n // Validate paths if provided\n if (config.proxyPath) {\n debug(\"Validating proxyPath:\", config.proxyPath);\n if (!this.isValidPath(config.proxyPath)) {\n debug(\"proxyPath validation FAILED\");\n throw new Error(\"Invalid proxyPath\");\n }\n }\n\n if (config.docPath) {\n debug(\"Validating docPath:\", config.docPath);\n if (!this.isValidPath(config.docPath)) {\n debug(\"docPath validation FAILED\");\n throw new Error(\"Invalid docPath\");\n }\n }\n\n if (config.apiSpecPath) {\n debug(\"Validating apiSpecPath:\", config.apiSpecPath);\n if (!this.isValidPath(config.apiSpecPath)) {\n debug(\"apiSpecPath validation FAILED\");\n throw new Error(\"Invalid apiSpecPath\");\n }\n }\n } catch (error) {\n debug(\"Validation error:\", error);\n throw new ScalarError(\"Invalid URL provided\", \"INVALID_URL\", 400);\n }\n }\n\n private isValidPath(path: string): boolean {\n // Aceita paths relativos com barras no meio e no final\n return (\n typeof path === \"string\" &&\n /^\\/[a-zA-Z0-9\\-._~:\\/@!$&'()*+,;=]*\\/?$/.test(path)\n );\n }\n}\n"],"mappings":"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","names":["logger","logger","path"]}
1
+ {"version":3,"sources":["../src/config/types.ts","../src/middleware/proxy.ts","../src/utils/debug.ts","../src/setupDocsRoute.ts","../src/utils/store.ts","../src/client.ts"],"sourcesContent":["import { AzuraClient } from \"azurajs\";\nimport { NextFunction, RequestServer, ResponseServer } from \"azurajs/types\";\n\nexport interface ScalarConfigType {\n baseUrl: string;\n proxyPath?: string;\n docPath?: string;\n apiSpecPath?: string;\n customHtmlPath?: string;\n app: AzuraClient;\n}\n\nexport interface ScalarStoreType {\n proxy_url?: string;\n api_spec_url?: string;\n doc_url?: string;\n custom_html_path?: string;\n}\n\nexport type ProxyMiddlewareType = (\n req: RequestServer,\n res: ResponseServer,\n next?: NextFunction,\n) => Promise<void>;\n\nexport class ScalarError extends Error {\n constructor(\n public readonly message: string,\n public readonly code: string,\n public readonly statusCode: number,\n ) {\n super(message);\n Object.setPrototypeOf(this, ScalarError.prototype);\n }\n}\n\nexport interface ProxyOptions {\n apiSpecUrl: string;\n proxyUrlPath: string;\n app: AzuraClient;\n baseUrl: string;\n}\n\nexport interface SetupDocsRouteOptions extends ScalarConfigType {\n docPath: string;\n proxyUrl: string;\n apiSpecUrl: string;\n}\n","import { ProxyOptions } from \"../config/types\";\nimport { logger } from \"azurajs/logger\";\nimport { debug } from \"../utils/debug\";\n\nexport function proxyMiddleware({\n apiSpecUrl,\n app,\n baseUrl,\n proxyUrlPath,\n}: ProxyOptions) {\n debug(\"Setting up proxy middleware with options:\", {\n apiSpecUrl,\n proxyUrlPath,\n });\n app.get(proxyUrlPath, () => {});\n return app.use(proxyUrlPath, async (req, res) => {\n debug(\n \"Proxy middleware hit with request:\",\n req.method,\n req.url,\n \"headers:\",\n req.headers,\n );\n try {\n if (!req.url || !req.method) {\n debug(\"Invalid request - missing url or method\");\n res.status(400).json({ error: \"Invalid request\" });\n return;\n }\n\n logger(\"info\", `[PROXY] ${req.method} ${req.url}`);\n\n // Extract target URL from scalar_url query param\n // req.url contains the query string (e.g., \"?scalar_url=...\")\n const queryParams = new URLSearchParams(req.url.split('?')[1] || '');\n const scalarUrl = queryParams.get(\"scalar_url\");\n debug(\"Extracted scalar_url from query params:\", scalarUrl);\n\n // Determine target URL - if scalar_url is provided in query, use it, otherwise use apiSpecUrl\n const targetUrl = scalarUrl || apiSpecUrl;\n debug(\"Determined target URL:\", targetUrl);\n\n // Validate same origin for security\n const target = new URL(targetUrl);\n const apiBase = new URL(apiSpecUrl);\n debug(\n \"Validating same origin - target origin:\",\n target.origin,\n \"apiBase origin:\",\n apiBase.origin,\n );\n // Allow requests to the same origin as the API spec OR the configured base URL\n const baseUrlOrigin = new URL(baseUrl).origin;\n const isSameAsApiSpecOrigin = target.origin === apiBase.origin;\n const isSameAsBaseUrlOrigin = target.origin === baseUrlOrigin;\n\n if (!isSameAsApiSpecOrigin && !isSameAsBaseUrlOrigin) {\n logger(\"warn\", `Blocked cross-origin: ${targetUrl} (expected origins: ${apiBase.origin} or ${baseUrlOrigin})`);\n res.status(403).json({ error: \"Cross-origin blocked\" });\n return;\n }\n\n logger(\"info\", `[PROXY] Forwarding to: ${targetUrl}`);\n\n // Prepare headers and body\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n headers[key] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n headers.host = apiBase.host;\n debug(\"Prepared headers:\", headers);\n\n const body = [\"GET\", \"HEAD\"].includes(req.method)\n ? undefined\n : typeof req.body === \"string\"\n ? req.body\n : JSON.stringify(req.body);\n debug(\"Request body:\", body);\n\n // Make request to target\n debug(\"Making fetch request to target URL:\", targetUrl);\n const proxyRes = await fetch(targetUrl, {\n method: req.method,\n headers,\n body,\n });\n debug(\"Fetch response received with status:\", proxyRes.status);\n\n // Set CORS headers FIRST before other headers to ensure they're not overridden\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\n \"Access-Control-Allow-Methods\",\n \"GET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD\",\n );\n res.setHeader(\"Access-Control-Allow-Headers\", \"*\");\n res.setHeader(\"Access-Control-Expose-Headers\", \"*\");\n\n // Copy all headers from the target response to our response\n for (const [key, value] of proxyRes.headers.entries()) {\n // Skip certain hop-by-hop headers that shouldn't be forwarded\n if (![\n 'connection',\n 'keep-alive',\n 'transfer-encoding',\n 'te',\n 'trailer',\n 'upgrade',\n 'host',\n 'access-control-allow-origin',\n 'access-control-allow-methods',\n 'access-control-allow-headers',\n 'access-control-expose-headers'\n ].includes(key.toLowerCase())) {\n res.setHeader(key, value);\n }\n }\n\n if (req.method === \"OPTIONS\") {\n debug(\"OPTIONS request, ending response\");\n res.end();\n return;\n }\n\n // Get the response body as text to preserve content type\n const responseBody = await proxyRes.text();\n debug(\"Response body length:\", responseBody.length);\n\n // Set the content-length header if not already set\n if (!res.getHeader('content-length')) {\n res.setHeader('content-length', Buffer.byteLength(responseBody));\n }\n\n res.status(proxyRes.status).send(responseBody);\n } catch (err) {\n debug(\"Error in proxy middleware:\", err);\n logger(\"error\", `[PROXY] Error: ${err}`);\n res.status(500).json({ error: \"Proxy error\", details: String(err) });\n }\n });\n}\n","/**\n * Debug utility function that only logs when DEBUG environment variable is set to 'true'\n */\n\nexport function debug(message: string, ...optionalParams: any[]) {\n if (process.env.DEBUG === 'true' || process.env.DEBUG === '1') {\n console.log(`[DEBUG] ${message}`, ...optionalParams);\n }\n}","import { logger } from \"azurajs/logger\";\nimport fs from \"fs\";\nimport path from \"node:path\";\nimport { ScalarError, SetupDocsRouteOptions } from \"./config/types\";\nimport { debug } from \"./utils/debug\";\n\nexport async function setupScalarDocs({\n app,\n docPath,\n customHtmlPath,\n apiSpecUrl,\n proxyUrl,\n}: SetupDocsRouteOptions) {\n debug(\"Setting up docs route with options:\", { docPath, customHtmlPath, apiSpecUrl, proxyUrl });\n\n return app.get(docPath, (req, res) => {\n debug(\"Docs route hit with request:\", req.method, req.url);\n try {\n if (!proxyUrl || !apiSpecUrl) {\n debug(\"Missing required URLs - proxyUrl:\", proxyUrl, \"apiSpecUrl:\", apiSpecUrl);\n throw new ScalarError(\n \"Missing required URLs\",\n \"STORE_VALUES_MISSING\",\n 500,\n );\n }\n\n const htmlPath =\n customHtmlPath || path.join(__dirname, \"../api-docs.html\");\n debug(\"HTML template path:\", htmlPath);\n\n if (!fs.existsSync(htmlPath)) {\n debug(\"HTML template not found at path:\", htmlPath);\n throw new ScalarError(\n \"HTML template not found\",\n \"HTML_TEMPLATE_NOT_FOUND\",\n 404,\n );\n }\n\n const html = fs.readFileSync(htmlPath, \"utf-8\");\n debug(\"HTML template read successfully, length:\", html.length);\n\n const processedHtml = html\n .replace(/&{proxy_url}/g, proxyUrl)\n .replace(/&{api_spec_url}/g, apiSpecUrl);\n debug(\"HTML template processed with proxyUrl and apiSpecUrl\");\n\n return res.send(processedHtml);\n } catch (error) {\n debug(\"Error in docs route:\", error);\n if (error instanceof ScalarError) {\n logger(\"error\", `[ScalarError] ${error.message}`);\n return res.status(error.statusCode).json({ message: error.message });\n } else {\n logger(\"error\", String(error));\n return res.status(500).json({ message: \"Server error\" });\n }\n }\n });\n}\n","/**\n * @fileoverview Store utility for managing application state\n * This module provides a typed store for managing scalar configuration values\n */\n\nimport { ScalarStoreType } from \"../config/types\";\n\n/**\n * Typed store class for managing scalar configuration values\n */\nclass ScalarStore {\n private store: Map<keyof ScalarStoreType, string | undefined> = new Map();\n\n /**\n * Sets a value in the store\n * @param key The key to set\n * @param value The value to set (if undefined, the key will be removed)\n */\n set<K extends keyof ScalarStoreType>(\n key: K,\n value: ScalarStoreType[K],\n ): void {\n this.store.set(key, value as string | undefined);\n }\n\n /**\n * Gets a value from the store\n * @param key The key to get\n * @returns The value associated with the key\n */\n get<K extends keyof ScalarStoreType>(key: K): ScalarStoreType[K] {\n return this.store.get(key) as ScalarStoreType[K];\n }\n\n /**\n * Checks if a key exists in the store\n * @param key The key to check\n * @returns True if the key exists, false otherwise\n */\n has(key: keyof ScalarStoreType): boolean {\n return this.store.has(key);\n }\n\n /**\n * Deletes a key from the store\n * @param key The key to delete\n * @returns True if the key existed and was deleted, false otherwise\n */\n delete(key: keyof ScalarStoreType): boolean {\n return this.store.delete(key);\n }\n\n /**\n * Clears all values from the store\n */\n clear(): void {\n this.store.clear();\n }\n\n /**\n * Gets all values from the store\n * @returns An object containing all key-value pairs in the store\n */\n getAll(): ScalarStoreType {\n const result: Partial<ScalarStoreType> = {};\n for (const [key, value] of this.store.entries()) {\n result[key] = value as ScalarStoreType[keyof ScalarStoreType];\n }\n return result as ScalarStoreType;\n }\n\n // Index signature to allow direct property access\n [key: string]: any;\n}\n\nexport const store = new ScalarStore();\n","/**\n * Scalar client for API documentation\n */\nimport {\n ScalarConfigType,\n ScalarError,\n SetupDocsRouteOptions,\n} from \"./config/types\";\nimport { proxyMiddleware } from \"./middleware/proxy\";\nimport { setupScalarDocs } from \"./setupDocsRoute\";\nimport { store } from \"./utils/store\";\nimport { debug } from \"./utils/debug\";\n\nexport class Scalar {\n constructor(config: ScalarConfigType) {\n debug(\"Scalar constructor called with config:\", config);\n\n // Normalize baseUrl to ensure it's a valid absolute URL before validation\n const normalizedConfig = { ...config };\n normalizedConfig.baseUrl = this.normalizeBaseUrl(config.baseUrl);\n debug(\"Normalized config:\", normalizedConfig);\n\n // Validate the configuration\n this.validateConfig(normalizedConfig);\n\n // Set default paths if not provided\n const proxyPath = normalizedConfig.proxyPath || \"/scalar/proxy\";\n const docPath = normalizedConfig.docPath || \"/docs\";\n const apiSpecPath = normalizedConfig.apiSpecPath || \"\";\n debug(\n \"Using paths - proxyPath:\",\n proxyPath,\n \"docPath:\",\n docPath,\n \"apiSpecPath:\",\n apiSpecPath,\n );\n\n // Calculate full URLs from baseUrl and paths\n const proxyUrl = this.joinUrl(normalizedConfig.baseUrl, proxyPath);\n const docUrl = this.joinUrl(normalizedConfig.baseUrl, docPath);\n const apiSpecUrl = this.joinUrl(normalizedConfig.baseUrl, apiSpecPath);\n debug(\n \"Calculated URLs - proxyUrl:\",\n proxyUrl,\n \"docUrl:\",\n docUrl,\n \"apiSpecUrl:\",\n apiSpecUrl,\n );\n\n // Store the calculated URLs\n store.set(\"proxy_url\", proxyUrl);\n store.set(\"api_spec_url\", apiSpecUrl);\n store.set(\"doc_url\", docUrl);\n debug(\"Stored URLs in store\");\n\n // Call setup with the calculated URLs\n setupScalarDocs({\n ...normalizedConfig,\n proxyUrl,\n docPath,\n apiSpecUrl,\n });\n debug(\"setupScalarDocs called\");\n\n // Setup proxy middleware\n proxyMiddleware({\n apiSpecUrl,\n proxyUrlPath: proxyPath,\n app: normalizedConfig.app,\n baseUrl: normalizedConfig.baseUrl,\n });\n debug(\"proxyMiddleware called\");\n }\n\n private joinUrl(baseUrl: string, path: string): string {\n // Normalize the baseUrl to ensure it ends with a slash\n const normalizedBaseUrl = baseUrl.endsWith(\"/\") ? baseUrl : baseUrl + \"/\";\n\n // Normalize the path to ensure it starts with a slash\n const normalizedPath = path.startsWith(\"/\") ? path : \"/\" + path;\n\n // Join the baseUrl and path, removing any double slashes\n return normalizedBaseUrl.replace(/\\/$/, \"\") + normalizedPath;\n }\n\n private normalizeBaseUrl(baseUrl: string): string {\n if (!baseUrl) {\n throw new ScalarError(\n \"baseUrl is required\",\n \"MISSING_REQUIRED_CONFIG\",\n 400,\n );\n }\n\n // If baseUrl doesn't start with a protocol, prepend http://\n if (!/^https?:\\/\\//i.test(baseUrl)) {\n return \"http://\" + baseUrl;\n }\n\n return baseUrl;\n }\n\n private validateConfig(config: ScalarConfigType): void {\n if (!config.baseUrl) {\n throw new ScalarError(\n \"baseUrl is required\",\n \"MISSING_REQUIRED_CONFIG\",\n 400,\n );\n }\n\n try {\n // Validate baseUrl\n debug(\"Validating baseUrl:\", config.baseUrl);\n new URL(config.baseUrl);\n\n // Validate paths if provided\n if (config.proxyPath) {\n debug(\"Validating proxyPath:\", config.proxyPath);\n if (!this.isValidPath(config.proxyPath)) {\n debug(\"proxyPath validation FAILED\");\n throw new Error(\"Invalid proxyPath\");\n }\n }\n\n if (config.docPath) {\n debug(\"Validating docPath:\", config.docPath);\n if (!this.isValidPath(config.docPath)) {\n debug(\"docPath validation FAILED\");\n throw new Error(\"Invalid docPath\");\n }\n }\n\n if (config.apiSpecPath) {\n debug(\"Validating apiSpecPath:\", config.apiSpecPath);\n if (!this.isValidPath(config.apiSpecPath)) {\n debug(\"apiSpecPath validation FAILED\");\n throw new Error(\"Invalid apiSpecPath\");\n }\n }\n } catch (error) {\n debug(\"Validation error:\", error);\n throw new ScalarError(\"Invalid URL provided\", \"INVALID_URL\", 400);\n }\n }\n\n private isValidPath(path: string): boolean {\n // Aceita paths relativos com barras no meio e no final\n return (\n typeof path === \"string\" &&\n /^\\/[a-zA-Z0-9\\-._~:\\/@!$&'()*+,;=]*\\/?$/.test(path)\n );\n }\n}\n"],"mappings":"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","names":["logger","logger","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azurajs-scalar",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Proxy middleware and controller to scalar documentation.",
5
5
  "type": "module",
6
6
  "publishConfig": {