azurajs-scalar 2.0.3-2 → 2.0.3-4

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
@@ -26,66 +26,66 @@ function proxyMiddleware({
26
26
  baseUrl,
27
27
  proxyUrlPath
28
28
  }) {
29
- debug("Setting up proxy middleware with options:", {
29
+ debug("Setting up proxy middleware:", {
30
30
  apiSpecUrl,
31
31
  proxyUrlPath
32
32
  });
33
- app.get(proxyUrlPath, () => {
34
- });
35
- return app.use(proxyUrlPath, async (req, res) => {
36
- debug(
37
- "Proxy middleware hit with request:",
38
- req.method,
39
- req.url,
40
- "headers:",
41
- req.headers
42
- );
33
+ return app.get(proxyUrlPath, async (req, res) => {
34
+ debug("=== PROXY HIT ===");
35
+ debug("Method:", req.method);
36
+ debug("URL:", req.url);
37
+ debug("Headers:", req.headers);
43
38
  try {
44
39
  if (!req.url || !req.method) {
45
- debug("Invalid request - missing url or method");
46
- res.status(400).json({ error: "Invalid request" });
47
- return;
40
+ return res.status(400).json({ error: "Invalid request" });
48
41
  }
49
42
  logger("info", `[PROXY] ${req.method} ${req.url}`);
50
- const queryParams = new URLSearchParams(req.url.split("?")[1] || "");
51
- const scalarUrl = queryParams.get("scalar_url");
52
- debug("Extracted scalar_url from query params:", scalarUrl);
43
+ const query = new URLSearchParams(req.url.split("?")[1] || "");
44
+ const scalarUrl = query.get("scalar_url");
53
45
  const targetUrl = scalarUrl || apiSpecUrl;
54
- debug("Determined target URL:", targetUrl);
46
+ debug("Target URL:", targetUrl);
55
47
  const target = new URL(targetUrl);
56
48
  const apiBase = new URL(apiSpecUrl);
57
- debug(
58
- "Validating same origin - target origin:",
59
- target.origin,
60
- "apiBase origin:",
61
- apiBase.origin
62
- );
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})`);
68
- res.status(403).json({ error: "Cross-origin blocked" });
69
- return;
49
+ const baseOrigin = new URL(baseUrl).origin;
50
+ const allowed = target.origin === apiBase.origin || target.origin === baseOrigin;
51
+ debug("Origin check:", {
52
+ target: target.origin,
53
+ apiSpec: apiBase.origin,
54
+ base: baseOrigin,
55
+ allowed
56
+ });
57
+ if (!allowed) {
58
+ logger("warn", `[PROXY] Blocked cross-origin: ${targetUrl}`);
59
+ return res.status(403).json({ error: "Cross-origin blocked" });
70
60
  }
71
- logger("info", `[PROXY] Forwarding to: ${targetUrl}`);
72
61
  const headers = {};
73
- for (const [key, value] of Object.entries(req.headers)) {
74
- if (value) {
75
- headers[key] = Array.isArray(value) ? value.join(", ") : value;
76
- }
62
+ for (const [k, v] of Object.entries(req.headers)) {
63
+ if (!v) continue;
64
+ headers[k] = Array.isArray(v) ? v.join(", ") : v;
77
65
  }
78
66
  headers.host = apiBase.host;
79
- debug("Prepared headers:", headers);
67
+ debug("Forward headers:", headers);
80
68
  const body = ["GET", "HEAD"].includes(req.method) ? void 0 : typeof req.body === "string" ? req.body : JSON.stringify(req.body);
81
- debug("Request body:", body);
82
- debug("Making fetch request to target URL:", targetUrl);
69
+ debug("Forward body type:", typeof body);
70
+ debug("Forward body length:", body?.length ?? 0);
83
71
  const proxyRes = await fetch(targetUrl, {
84
72
  method: req.method,
85
73
  headers,
86
74
  body
87
75
  });
88
- debug("Fetch response received with status:", proxyRes.status);
76
+ debug("=== FETCH RESPONSE ===");
77
+ debug("Status:", proxyRes.status);
78
+ debug("StatusText:", proxyRes.statusText);
79
+ debug("URL:", proxyRes.url);
80
+ const headersObj = {};
81
+ for (const [k, v] of proxyRes.headers.entries()) {
82
+ headersObj[k] = v;
83
+ }
84
+ debug("Response headers:", headersObj);
85
+ debug("content-type:", proxyRes.headers.get("content-type"));
86
+ debug("content-encoding:", proxyRes.headers.get("content-encoding"));
87
+ debug("transfer-encoding:", proxyRes.headers.get("transfer-encoding"));
88
+ debug("content-length:", proxyRes.headers.get("content-length"));
89
89
  res.setHeader("Access-Control-Allow-Origin", "*");
90
90
  res.setHeader(
91
91
  "Access-Control-Allow-Methods",
@@ -94,37 +94,43 @@ function proxyMiddleware({
94
94
  res.setHeader("Access-Control-Allow-Headers", "*");
95
95
  res.setHeader("Access-Control-Expose-Headers", "*");
96
96
  for (const [key, value] of proxyRes.headers.entries()) {
97
- if (![
97
+ const k = key.toLowerCase();
98
+ if (k === "content-encoding") continue;
99
+ if (k === "content-length") continue;
100
+ if ([
98
101
  "connection",
99
102
  "keep-alive",
100
103
  "transfer-encoding",
101
104
  "te",
102
105
  "trailer",
103
106
  "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())) {
110
- res.setHeader(key, value);
111
- }
107
+ "host"
108
+ ].includes(k))
109
+ continue;
110
+ res.setHeader(key, value);
112
111
  }
113
112
  if (req.method === "OPTIONS") {
114
- debug("OPTIONS request, ending response");
115
- res.end();
116
- return;
113
+ debug("OPTIONS request -> end");
114
+ return res.end();
117
115
  }
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);
116
+ const arrayBuf = await proxyRes.arrayBuffer();
117
+ const buffer = Buffer.from(arrayBuf);
118
+ debug("=== BODY DEBUG ===");
119
+ debug("ArrayBuffer byteLength:", arrayBuf.byteLength);
120
+ debug("Buffer length:", buffer.length);
121
+ debug("Buffer empty:", buffer.length === 0);
122
+ debug("First 50 bytes (hex):", buffer.subarray(0, 50).toString("hex"));
123
+ debug(
124
+ "First 200 chars (utf8):",
125
+ buffer.subarray(0, 200).toString("utf8")
126
+ );
127
+ debug("=== END BODY DEBUG ===");
128
+ res.status(proxyRes.status).send(buffer);
124
129
  } catch (err) {
125
- debug("Error in proxy middleware:", err);
130
+ debug("=== PROXY ERROR ===");
131
+ debug("Ocorreu um erro no proxy...", err);
126
132
  logger("error", `[PROXY] Error: ${err}`);
127
- res.status(500).json({ error: "Proxy error", details: String(err) });
133
+ res.status(500).json({ error: "Proxy error" });
128
134
  }
129
135
  });
130
136
  }
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 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":";AAyBO,IAAM,cAAN,MAAM,qBAAoB,MAAM;AAAA,EACrC,YACkB,SACA,MACA,YAChB;AACA,UAAM,OAAO;AAJG;AACA;AACA;AAGhB,WAAO,eAAe,MAAM,aAAY,SAAS;AAAA,EACnD;AACF;;;ACjCA,SAAS,cAAc;;;ACGhB,SAAS,MAAM,YAAoB,gBAAuB;AAC/D,MAAI,QAAQ,IAAI,UAAU,UAAU,QAAQ,IAAI,UAAU,KAAK;AAC7D,YAAQ,IAAI,WAAW,OAAO,IAAI,GAAG,cAAc;AAAA,EACrD;AACF;;;ADJO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiB;AACf,QAAM,6CAA6C;AAAA,IACjD;AAAA,IACA;AAAA,EACF,CAAC;AACD,MAAI,IAAI,cAAc,MAAM;AAAA,EAAC,CAAC;AAC9B,SAAO,IAAI,IAAI,cAAc,OAAO,KAAK,QAAQ;AAC/C;AAAA,MACE;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA,IAAI;AAAA,IACN;AACA,QAAI;AACF,UAAI,CAAC,IAAI,OAAO,CAAC,IAAI,QAAQ;AAC3B,cAAM,yCAAyC;AAC/C,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;AACjD;AAAA,MACF;AAEA,aAAO,QAAQ,WAAW,IAAI,MAAM,IAAI,IAAI,GAAG,EAAE;AAIjD,YAAM,cAAc,IAAI,gBAAgB,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE;AACnE,YAAM,YAAY,YAAY,IAAI,YAAY;AAC9C,YAAM,2CAA2C,SAAS;AAG1D,YAAM,YAAY,aAAa;AAC/B,YAAM,0BAA0B,SAAS;AAGzC,YAAM,SAAS,IAAI,IAAI,SAAS;AAChC,YAAM,UAAU,IAAI,IAAI,UAAU;AAClC;AAAA,QACE;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA,QAAQ;AAAA,MACV;AAEA,YAAM,gBAAgB,IAAI,IAAI,OAAO,EAAE;AACvC,YAAM,wBAAwB,OAAO,WAAW,QAAQ;AACxD,YAAM,wBAAwB,OAAO,WAAW;AAEhD,UAAI,CAAC,yBAAyB,CAAC,uBAAuB;AACpD,eAAO,QAAQ,yBAAyB,SAAS,uBAAuB,QAAQ,MAAM,OAAO,aAAa,GAAG;AAC7G,YAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,uBAAuB,CAAC;AACtD;AAAA,MACF;AAEA,aAAO,QAAQ,0BAA0B,SAAS,EAAE;AAGpD,YAAM,UAAkC,CAAC;AACzC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AACtD,YAAI,OAAO;AACT,kBAAQ,GAAG,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI;AAAA,QAC3D;AAAA,MACF;AACA,cAAQ,OAAO,QAAQ;AACvB,YAAM,qBAAqB,OAAO;AAElC,YAAM,OAAO,CAAC,OAAO,MAAM,EAAE,SAAS,IAAI,MAAM,IAC5C,SACA,OAAO,IAAI,SAAS,WAClB,IAAI,OACJ,KAAK,UAAU,IAAI,IAAI;AAC7B,YAAM,iBAAiB,IAAI;AAG3B,YAAM,uCAAuC,SAAS;AACtD,YAAM,WAAW,MAAM,MAAM,WAAW;AAAA,QACtC,QAAQ,IAAI;AAAA,QACZ;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,wCAAwC,SAAS,MAAM;AAG7D,UAAI,UAAU,+BAA+B,GAAG;AAChD,UAAI;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,UAAI,UAAU,gCAAgC,GAAG;AACjD,UAAI,UAAU,iCAAiC,GAAG;AAGlD,iBAAW,CAAC,KAAK,KAAK,KAAK,SAAS,QAAQ,QAAQ,GAAG;AAErD,YAAI,CAAC;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,SAAS,IAAI,YAAY,CAAC,GAAG;AAC7B,cAAI,UAAU,KAAK,KAAK;AAAA,QAC1B;AAAA,MACF;AAEA,UAAI,IAAI,WAAW,WAAW;AAC5B,cAAM,kCAAkC;AACxC,YAAI,IAAI;AACR;AAAA,MACF;AAGA,YAAM,eAAe,MAAM,SAAS,KAAK;AACzC,YAAM,yBAAyB,aAAa,MAAM;AAGlD,UAAI,CAAC,IAAI,UAAU,gBAAgB,GAAG;AACpC,YAAI,UAAU,kBAAkB,OAAO,WAAW,YAAY,CAAC;AAAA,MACjE;AAEA,UAAI,OAAO,SAAS,MAAM,EAAE,KAAK,YAAY;AAAA,IAC/C,SAAS,KAAK;AACZ,YAAM,8BAA8B,GAAG;AACvC,aAAO,SAAS,kBAAkB,GAAG,EAAE;AACvC,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,SAAS,OAAO,GAAG,EAAE,CAAC;AAAA,IACrE;AAAA,EACF,CAAC;AACH;;;AE7IA,SAAS,UAAAA,eAAc;AACvB,OAAO,QAAQ;AACf,OAAO,UAAU;AAIjB,eAAsB,gBAAgB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,uCAAuC,EAAE,SAAS,gBAAgB,YAAY,SAAS,CAAC;AAE9F,SAAO,IAAI,IAAI,SAAS,CAAC,KAAK,QAAQ;AACpC,UAAM,gCAAgC,IAAI,QAAQ,IAAI,GAAG;AACzD,QAAI;AACF,UAAI,CAAC,YAAY,CAAC,YAAY;AAC5B,cAAM,qCAAqC,UAAU,eAAe,UAAU;AAC9E,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,WACJ,kBAAkB,KAAK,KAAK,WAAW,kBAAkB;AAC3D,YAAM,uBAAuB,QAAQ;AAErC,UAAI,CAAC,GAAG,WAAW,QAAQ,GAAG;AAC5B,cAAM,oCAAoC,QAAQ;AAClD,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,OAAO,GAAG,aAAa,UAAU,OAAO;AAC9C,YAAM,4CAA4C,KAAK,MAAM;AAE7D,YAAM,gBAAgB,KACnB,QAAQ,iBAAiB,QAAQ,EACjC,QAAQ,oBAAoB,UAAU;AACzC,YAAM,sDAAsD;AAE5D,aAAO,IAAI,KAAK,aAAa;AAAA,IAC/B,SAAS,OAAO;AACd,YAAM,wBAAwB,KAAK;AACnC,UAAI,iBAAiB,aAAa;AAChC,QAAAC,QAAO,SAAS,iBAAiB,MAAM,OAAO,EAAE;AAChD,eAAO,IAAI,OAAO,MAAM,UAAU,EAAE,KAAK,EAAE,SAAS,MAAM,QAAQ,CAAC;AAAA,MACrE,OAAO;AACL,QAAAA,QAAO,SAAS,OAAO,KAAK,CAAC;AAC7B,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,eAAe,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;AClDA,IAAM,cAAN,MAAkB;AAAA,EAAlB;AACE,SAAQ,QAAwD,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxE,IACE,KACA,OACM;AACN,SAAK,MAAM,IAAI,KAAK,KAA2B;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAqC,KAA4B;AAC/D,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAqC;AACvC,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,KAAqC;AAC1C,WAAO,KAAK,MAAM,OAAO,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAA0B;AACxB,UAAM,SAAmC,CAAC;AAC1C,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM,QAAQ,GAAG;AAC/C,aAAO,GAAG,IAAI;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AAIF;AAEO,IAAM,QAAQ,IAAI,YAAY;;;AC9D9B,IAAM,SAAN,MAAa;AAAA,EAClB,YAAY,QAA0B;AACpC,UAAM,0CAA0C,MAAM;AAGtD,UAAM,mBAAmB,EAAE,GAAG,OAAO;AACrC,qBAAiB,UAAU,KAAK,iBAAiB,OAAO,OAAO;AAC/D,UAAM,sBAAsB,gBAAgB;AAG5C,SAAK,eAAe,gBAAgB;AAGpC,UAAM,YAAY,iBAAiB,aAAa;AAChD,UAAM,UAAU,iBAAiB,WAAW;AAC5C,UAAM,cAAc,iBAAiB,eAAe;AACpD;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,QAAQ,iBAAiB,SAAS,SAAS;AACjE,UAAM,SAAS,KAAK,QAAQ,iBAAiB,SAAS,OAAO;AAC7D,UAAM,aAAa,KAAK,QAAQ,iBAAiB,SAAS,WAAW;AACrE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,IAAI,aAAa,QAAQ;AAC/B,UAAM,IAAI,gBAAgB,UAAU;AACpC,UAAM,IAAI,WAAW,MAAM;AAC3B,UAAM,sBAAsB;AAG5B,oBAAgB;AAAA,MACd,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,wBAAwB;AAG9B,oBAAgB;AAAA,MACd;AAAA,MACA,cAAc;AAAA,MACd,KAAK,iBAAiB;AAAA,MACtB,SAAS,iBAAiB;AAAA,IAC5B,CAAC;AACD,UAAM,wBAAwB;AAAA,EAChC;AAAA,EAEQ,QAAQ,SAAiBC,OAAsB;AAErD,UAAM,oBAAoB,QAAQ,SAAS,GAAG,IAAI,UAAU,UAAU;AAGtE,UAAM,iBAAiBA,MAAK,WAAW,GAAG,IAAIA,QAAO,MAAMA;AAG3D,WAAO,kBAAkB,QAAQ,OAAO,EAAE,IAAI;AAAA,EAChD;AAAA,EAEQ,iBAAiB,SAAyB;AAChD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,gBAAgB,KAAK,OAAO,GAAG;AAClC,aAAO,YAAY;AAAA,IACrB;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,QAAgC;AACrD,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AAEF,YAAM,uBAAuB,OAAO,OAAO;AAC3C,UAAI,IAAI,OAAO,OAAO;AAGtB,UAAI,OAAO,WAAW;AACpB,cAAM,yBAAyB,OAAO,SAAS;AAC/C,YAAI,CAAC,KAAK,YAAY,OAAO,SAAS,GAAG;AACvC,gBAAM,6BAA6B;AACnC,gBAAM,IAAI,MAAM,mBAAmB;AAAA,QACrC;AAAA,MACF;AAEA,UAAI,OAAO,SAAS;AAClB,cAAM,uBAAuB,OAAO,OAAO;AAC3C,YAAI,CAAC,KAAK,YAAY,OAAO,OAAO,GAAG;AACrC,gBAAM,2BAA2B;AACjC,gBAAM,IAAI,MAAM,iBAAiB;AAAA,QACnC;AAAA,MACF;AAEA,UAAI,OAAO,aAAa;AACtB,cAAM,2BAA2B,OAAO,WAAW;AACnD,YAAI,CAAC,KAAK,YAAY,OAAO,WAAW,GAAG;AACzC,gBAAM,+BAA+B;AACrC,gBAAM,IAAI,MAAM,qBAAqB;AAAA,QACvC;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,qBAAqB,KAAK;AAChC,YAAM,IAAI,YAAY,wBAAwB,eAAe,GAAG;AAAA,IAClE;AAAA,EACF;AAAA,EAEQ,YAAYA,OAAuB;AAEzC,WACE,OAAOA,UAAS,YAChB,0CAA0C,KAAKA,KAAI;AAAA,EAEvD;AACF;","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:\", {\n apiSpecUrl,\n proxyUrlPath,\n });\n return app.get(proxyUrlPath, async (req, res) => {\n debug(\"=== PROXY HIT ===\");\n debug(\"Method:\", req.method);\n debug(\"URL:\", req.url);\n debug(\"Headers:\", req.headers);\n\n try {\n if (!req.url || !req.method) {\n return res.status(400).json({ error: \"Invalid request\" });\n }\n\n logger(\"info\", `[PROXY] ${req.method} ${req.url}`);\n\n /* =========================\n TARGET URL\n ========================= */\n const query = new URLSearchParams(req.url.split(\"?\")[1] || \"\");\n const scalarUrl = query.get(\"scalar_url\");\n const targetUrl = scalarUrl || apiSpecUrl;\n\n debug(\"Target URL:\", targetUrl);\n\n /* =========================\n SAME-ORIGIN\n ========================= */\n const target = new URL(targetUrl);\n const apiBase = new URL(apiSpecUrl);\n const baseOrigin = new URL(baseUrl).origin;\n\n const allowed =\n target.origin === apiBase.origin || target.origin === baseOrigin;\n\n debug(\"Origin check:\", {\n target: target.origin,\n apiSpec: apiBase.origin,\n base: baseOrigin,\n allowed,\n });\n\n if (!allowed) {\n logger(\"warn\", `[PROXY] Blocked cross-origin: ${targetUrl}`);\n return res.status(403).json({ error: \"Cross-origin blocked\" });\n }\n\n /* =========================\n HEADERS\n ========================= */\n const headers: Record<string, string> = {};\n\n for (const [k, v] of Object.entries(req.headers)) {\n if (!v) continue;\n headers[k] = Array.isArray(v) ? v.join(\", \") : v;\n }\n\n headers.host = apiBase.host;\n\n debug(\"Forward headers:\", headers);\n\n /* =========================\n BODY\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\n debug(\"Forward body type:\", typeof body);\n debug(\"Forward body length:\", body?.length ?? 0);\n\n /* =========================\n FETCH\n ========================= */\n const proxyRes = await fetch(targetUrl, {\n method: req.method,\n headers,\n body,\n });\n\n debug(\"=== FETCH RESPONSE ===\");\n debug(\"Status:\", proxyRes.status);\n debug(\"StatusText:\", proxyRes.statusText);\n debug(\"URL:\", proxyRes.url);\n\n const headersObj: Record<string, string> = {};\n for (const [k, v] of proxyRes.headers.entries()) {\n headersObj[k] = v;\n }\n debug(\"Response headers:\", headersObj);\n\n debug(\"content-type:\", proxyRes.headers.get(\"content-type\"));\n debug(\"content-encoding:\", proxyRes.headers.get(\"content-encoding\"));\n debug(\"transfer-encoding:\", proxyRes.headers.get(\"transfer-encoding\"));\n debug(\"content-length:\", proxyRes.headers.get(\"content-length\"));\n\n /* =========================\n CORS\n ========================= */\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 /* =========================\n SAFE HEADERS PASS\n ========================= */\n for (const [key, value] of proxyRes.headers.entries()) {\n const k = key.toLowerCase();\n\n // quebram proxy quando body já vem decodado\n if (k === \"content-encoding\") continue;\n if (k === \"content-length\") continue;\n\n // headers de conexão\n if (\n [\n \"connection\",\n \"keep-alive\",\n \"transfer-encoding\",\n \"te\",\n \"trailer\",\n \"upgrade\",\n \"host\",\n ].includes(k)\n )\n continue;\n\n res.setHeader(key, value);\n }\n\n if (req.method === \"OPTIONS\") {\n debug(\"OPTIONS request -> end\");\n return res.end();\n }\n\n /* =========================\n DEBUG SEVERO BODY\n ========================= */\n const arrayBuf = await proxyRes.arrayBuffer();\n const buffer = Buffer.from(arrayBuf);\n\n debug(\"=== BODY DEBUG ===\");\n debug(\"ArrayBuffer byteLength:\", arrayBuf.byteLength);\n debug(\"Buffer length:\", buffer.length);\n debug(\"Buffer empty:\", buffer.length === 0);\n debug(\"First 50 bytes (hex):\", buffer.subarray(0, 50).toString(\"hex\"));\n debug(\n \"First 200 chars (utf8):\",\n buffer.subarray(0, 200).toString(\"utf8\"),\n );\n debug(\"=== END BODY DEBUG ===\");\n\n /* =========================\n SEND\n ========================= */\n res.status(proxyRes.status).send(buffer);\n } catch (err) {\n debug(\"=== PROXY ERROR ===\");\n debug(\"Ocorreu um erro no proxy...\", err);\n logger(\"error\", `[PROXY] Error: ${err}`);\n res.status(500).json({ error: \"Proxy error\" });\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.3-2",
3
+ "version": "2.0.3-4",
4
4
  "description": "Proxy middleware and controller to scalar documentation.",
5
5
  "type": "module",
6
6
  "publishConfig": {