@unblind/nextjs 0.1.0-alpha.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/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server/index.d.mts +78 -0
- package/dist/server/index.d.ts +78 -0
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +2 -0
- package/dist/server/index.mjs.map +1 -0
- package/package.json +46 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AggregationOperator, Appearance, AttributeWithValue, Chart, ChartProps, ChartType, Colors, Divider, Log, MetricMetadata, MetricMetadataList, MetricType, PaginatedResponse, Serie, Severity, TimeRange, TimeseriesChart, TimeseriesChartProps, TimeseriesQuery, TooltipProps, UnblindClientConfig, UnblindClientProvider, UnblindClientProviderProps, UnblindProvider, UnblindProviderProps, UnblindScope, UnblindScopeConfig, UnblindScopeProps, Usage, UseLogsParams, UseLogsReturn, UseMetricsReturn, UseScopeReturn, UseTimeseriesParams, UseTimeseriesReturn, UseUsageParams, UseUsageReturn, useLogs, useMetrics, useRefresh, useScope, useTheme, useTimeseries, useUnblindClientConfig, useUsage } from '@unblind/react';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AggregationOperator, Appearance, AttributeWithValue, Chart, ChartProps, ChartType, Colors, Divider, Log, MetricMetadata, MetricMetadataList, MetricType, PaginatedResponse, Serie, Severity, TimeRange, TimeseriesChart, TimeseriesChartProps, TimeseriesQuery, TooltipProps, UnblindClientConfig, UnblindClientProvider, UnblindClientProviderProps, UnblindProvider, UnblindProviderProps, UnblindScope, UnblindScopeConfig, UnblindScopeProps, Usage, UseLogsParams, UseLogsReturn, UseMetricsReturn, UseScopeReturn, UseTimeseriesParams, UseTimeseriesReturn, UseUsageParams, UseUsageReturn, useLogs, useMetrics, useRefresh, useScope, useTheme, useTimeseries, useUnblindClientConfig, useUsage } from '@unblind/react';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";"use client";var n=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var d=(s,r)=>{for(var t in r)n(s,t,{get:r[t],enumerable:!0})},l=(s,r,t,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of p(r))!U.call(s,i)&&i!==t&&n(s,i,{get:()=>r[i],enumerable:!(o=a(r,i))||o.enumerable});return s};var u=s=>l(n({},"__esModule",{value:!0}),s);var g={};d(g,{Chart:()=>e.Chart,Divider:()=>e.Divider,TimeseriesChart:()=>e.TimeseriesChart,UnblindClientProvider:()=>e.UnblindClientProvider,UnblindProvider:()=>e.UnblindProvider,UnblindScope:()=>e.UnblindScope,useLogs:()=>e.useLogs,useMetrics:()=>e.useMetrics,useRefresh:()=>e.useRefresh,useScope:()=>e.useScope,useTheme:()=>e.useTheme,useTimeseries:()=>e.useTimeseries,useUnblindClientConfig:()=>e.useUnblindClientConfig,useUsage:()=>e.useUsage});module.exports=u(g);var e=require("@unblind/react"),P=require("@unblind/react/styles.css");0&&(module.exports={Chart,Divider,TimeseriesChart,UnblindClientProvider,UnblindProvider,UnblindScope,useLogs,useMetrics,useRefresh,useScope,useTheme,useTimeseries,useUnblindClientConfig,useUsage});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["\"use client\";\n\nexport {\n UnblindClientProvider,\n UnblindScope,\n UnblindProvider,\n useUnblindClientConfig,\n useScope,\n useMetrics,\n useTimeseries,\n useUsage,\n useLogs,\n useTheme,\n useRefresh,\n TimeseriesChart,\n Chart,\n Divider,\n} from \"@unblind/react\";\nimport \"@unblind/react/styles.css\";\n\nexport type {\n UnblindClientConfig,\n UnblindProviderProps,\n UnblindScopeConfig,\n Appearance,\n UnblindClientProviderProps,\n UnblindScopeProps,\n UseScopeReturn,\n UseMetricsReturn,\n UseTimeseriesParams,\n UseTimeseriesReturn,\n UseUsageParams,\n UseUsageReturn,\n Usage,\n UseLogsParams,\n UseLogsReturn,\n TimeseriesChartProps,\n TooltipProps,\n ChartProps,\n Colors,\n MetricType,\n MetricMetadata,\n MetricMetadataList,\n AggregationOperator,\n AttributeWithValue,\n Serie,\n TimeseriesQuery,\n ChartType,\n TimeRange,\n Log,\n Severity,\n PaginatedResponse,\n} from \"@unblind/react\";\n"],"mappings":"sbAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,ocAAAE,EAAAF,GAEA,IAAAG,EAeO,0BACPC,EAAO","names":["index_exports","__export","__toCommonJS","import_react","import_styles"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";import{UnblindClientProvider as i,UnblindScope as t,UnblindProvider as n,useUnblindClientConfig as o,useScope as a,useMetrics as p,useTimeseries as U,useUsage as d,useLogs as l,useTheme as u,useRefresh as g,TimeseriesChart as m,Chart as P,Divider as c}from"@unblind/react";import"@unblind/react/styles.css";export{P as Chart,c as Divider,m as TimeseriesChart,i as UnblindClientProvider,n as UnblindProvider,t as UnblindScope,l as useLogs,p as useMetrics,g as useRefresh,a as useScope,u as useTheme,U as useTimeseries,o as useUnblindClientConfig,d as useUsage};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["\"use client\";\n\nexport {\n UnblindClientProvider,\n UnblindScope,\n UnblindProvider,\n useUnblindClientConfig,\n useScope,\n useMetrics,\n useTimeseries,\n useUsage,\n useLogs,\n useTheme,\n useRefresh,\n TimeseriesChart,\n Chart,\n Divider,\n} from \"@unblind/react\";\nimport \"@unblind/react/styles.css\";\n\nexport type {\n UnblindClientConfig,\n UnblindProviderProps,\n UnblindScopeConfig,\n Appearance,\n UnblindClientProviderProps,\n UnblindScopeProps,\n UseScopeReturn,\n UseMetricsReturn,\n UseTimeseriesParams,\n UseTimeseriesReturn,\n UseUsageParams,\n UseUsageReturn,\n Usage,\n UseLogsParams,\n UseLogsReturn,\n TimeseriesChartProps,\n TooltipProps,\n ChartProps,\n Colors,\n MetricType,\n MetricMetadata,\n MetricMetadataList,\n AggregationOperator,\n AttributeWithValue,\n Serie,\n TimeseriesQuery,\n ChartType,\n TimeRange,\n Log,\n Severity,\n PaginatedResponse,\n} from \"@unblind/react\";\n"],"mappings":"aAEA,OACE,yBAAAA,EACA,gBAAAC,EACA,mBAAAC,EACA,0BAAAC,EACA,YAAAC,EACA,cAAAC,EACA,iBAAAC,EACA,YAAAC,EACA,WAAAC,EACA,YAAAC,EACA,cAAAC,EACA,mBAAAC,EACA,SAAAC,EACA,WAAAC,MACK,iBACP,MAAO","names":["UnblindClientProvider","UnblindScope","UnblindProvider","useUnblindClientConfig","useScope","useMetrics","useTimeseries","useUsage","useLogs","useTheme","useRefresh","TimeseriesChart","Chart","Divider"]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Custom NextRequest to avoid compatibility issues with older NextJS versions.
|
|
5
|
+
*/
|
|
6
|
+
interface NextRequest {
|
|
7
|
+
method: string;
|
|
8
|
+
headers: Headers;
|
|
9
|
+
text(): Promise<string>;
|
|
10
|
+
nextUrl: {
|
|
11
|
+
href: string;
|
|
12
|
+
pathname: string;
|
|
13
|
+
search: string;
|
|
14
|
+
searchParams: URLSearchParams;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Unblind API handler for Next.js applications.
|
|
19
|
+
*
|
|
20
|
+
* This handler intercepts requests to `/api/unblind` and proxies them to the Unblind API,
|
|
21
|
+
* automatically adding authentication and tenant context. It returns `null` for requests
|
|
22
|
+
* that don't match the path prefix, allowing Next.js to continue normal routing.
|
|
23
|
+
*
|
|
24
|
+
* **Available as:** `unblindProxy`, `unblindHandler`, or `unblindMiddleware` (all are aliases)
|
|
25
|
+
*
|
|
26
|
+
* @param request - The incoming Next.js request object
|
|
27
|
+
* @param tenantId - The tenant identifier to inject into API paths (e.g., user ID, organization ID)
|
|
28
|
+
* @param apiKey - Optional Unblind API key. Falls back to UNBLIND_API_KEY environment variable
|
|
29
|
+
*
|
|
30
|
+
* @returns A NextResponse with the proxied API response, or null if the request doesn't match `/api/unblind`
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Usage as Proxy (Starting with Next.js 16 as `proxy.ts`)
|
|
34
|
+
* import { unblindProxy } from "@unblind/nextjs/server";
|
|
35
|
+
* import { NextRequest } from "next/server";
|
|
36
|
+
*
|
|
37
|
+
* export function proxy(request: NextRequest) {
|
|
38
|
+
* const path = new URL(request.url).pathname;
|
|
39
|
+
*
|
|
40
|
+
* if (path.startsWith("/api/unblind")) {
|
|
41
|
+
* // Extract tenant ID from your auth system (e.g., session, JWT, cookies)
|
|
42
|
+
* const tenantId = request.cookies.get("tenantId")?.value;
|
|
43
|
+
* return unblindProxy(request, tenantId);
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* export const config = {
|
|
48
|
+
* matcher: "/api/unblind/:path*",
|
|
49
|
+
* };
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Usage in Middleware with multiple routes
|
|
53
|
+
* import { unblindMiddleware } from "@unblind/nextjs/server";
|
|
54
|
+
* import { NextRequest, NextResponse } from "next/server";
|
|
55
|
+
*
|
|
56
|
+
* export async function middleware(request: NextRequest) {
|
|
57
|
+
*
|
|
58
|
+
* // Let the handler process Unblind API requests
|
|
59
|
+
* if (request.nextUrl.pathname.startsWith("/api/unblind")) {
|
|
60
|
+
* // Extract tenant ID from your auth system
|
|
61
|
+
* const tenantId = request.cookies.get('userId')?.value;
|
|
62
|
+
*
|
|
63
|
+
* const response = await unblindMiddleware(request, tenantId);
|
|
64
|
+
* if (response) {
|
|
65
|
+
* return response;
|
|
66
|
+
* }
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* return NextResponse.next();
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* export const config = {
|
|
73
|
+
* matcher: ['/api/unblind/:path*', '/dashboard/:path*'],
|
|
74
|
+
* };
|
|
75
|
+
*/
|
|
76
|
+
declare function handler(request: NextRequest, tenantId?: string, apiKey?: string): Promise<NextResponse | null>;
|
|
77
|
+
|
|
78
|
+
export { handler as unblindHandler, handler as unblindMiddleware, handler as unblindProxy };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Custom NextRequest to avoid compatibility issues with older NextJS versions.
|
|
5
|
+
*/
|
|
6
|
+
interface NextRequest {
|
|
7
|
+
method: string;
|
|
8
|
+
headers: Headers;
|
|
9
|
+
text(): Promise<string>;
|
|
10
|
+
nextUrl: {
|
|
11
|
+
href: string;
|
|
12
|
+
pathname: string;
|
|
13
|
+
search: string;
|
|
14
|
+
searchParams: URLSearchParams;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Unblind API handler for Next.js applications.
|
|
19
|
+
*
|
|
20
|
+
* This handler intercepts requests to `/api/unblind` and proxies them to the Unblind API,
|
|
21
|
+
* automatically adding authentication and tenant context. It returns `null` for requests
|
|
22
|
+
* that don't match the path prefix, allowing Next.js to continue normal routing.
|
|
23
|
+
*
|
|
24
|
+
* **Available as:** `unblindProxy`, `unblindHandler`, or `unblindMiddleware` (all are aliases)
|
|
25
|
+
*
|
|
26
|
+
* @param request - The incoming Next.js request object
|
|
27
|
+
* @param tenantId - The tenant identifier to inject into API paths (e.g., user ID, organization ID)
|
|
28
|
+
* @param apiKey - Optional Unblind API key. Falls back to UNBLIND_API_KEY environment variable
|
|
29
|
+
*
|
|
30
|
+
* @returns A NextResponse with the proxied API response, or null if the request doesn't match `/api/unblind`
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Usage as Proxy (Starting with Next.js 16 as `proxy.ts`)
|
|
34
|
+
* import { unblindProxy } from "@unblind/nextjs/server";
|
|
35
|
+
* import { NextRequest } from "next/server";
|
|
36
|
+
*
|
|
37
|
+
* export function proxy(request: NextRequest) {
|
|
38
|
+
* const path = new URL(request.url).pathname;
|
|
39
|
+
*
|
|
40
|
+
* if (path.startsWith("/api/unblind")) {
|
|
41
|
+
* // Extract tenant ID from your auth system (e.g., session, JWT, cookies)
|
|
42
|
+
* const tenantId = request.cookies.get("tenantId")?.value;
|
|
43
|
+
* return unblindProxy(request, tenantId);
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* export const config = {
|
|
48
|
+
* matcher: "/api/unblind/:path*",
|
|
49
|
+
* };
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Usage in Middleware with multiple routes
|
|
53
|
+
* import { unblindMiddleware } from "@unblind/nextjs/server";
|
|
54
|
+
* import { NextRequest, NextResponse } from "next/server";
|
|
55
|
+
*
|
|
56
|
+
* export async function middleware(request: NextRequest) {
|
|
57
|
+
*
|
|
58
|
+
* // Let the handler process Unblind API requests
|
|
59
|
+
* if (request.nextUrl.pathname.startsWith("/api/unblind")) {
|
|
60
|
+
* // Extract tenant ID from your auth system
|
|
61
|
+
* const tenantId = request.cookies.get('userId')?.value;
|
|
62
|
+
*
|
|
63
|
+
* const response = await unblindMiddleware(request, tenantId);
|
|
64
|
+
* if (response) {
|
|
65
|
+
* return response;
|
|
66
|
+
* }
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* return NextResponse.next();
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* export const config = {
|
|
73
|
+
* matcher: ['/api/unblind/:path*', '/dashboard/:path*'],
|
|
74
|
+
* };
|
|
75
|
+
*/
|
|
76
|
+
declare function handler(request: NextRequest, tenantId?: string, apiKey?: string): Promise<NextResponse | null>;
|
|
77
|
+
|
|
78
|
+
export { handler as unblindHandler, handler as unblindMiddleware, handler as unblindProxy };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var d=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var E=(e,n)=>{for(var s in n)d(e,s,{get:n[s],enumerable:!0})},N=(e,n,s,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of g(n))!f.call(e,t)&&t!==s&&d(e,t,{get:()=>n[t],enumerable:!(a=u(n,t))||a.enumerable});return e};var U=e=>N(d({},"__esModule",{value:!0}),e);var y={};E(y,{unblindHandler:()=>l,unblindMiddleware:()=>l,unblindProxy:()=>l});module.exports=U(y);var i=require("next/server"),I=process.env.UNBLIND_API_ENDPOINT||"https://api.unblind.dev/v1",T=process.env.UNBLIND_API_KEY;async function l(e,n,s){let a="/api/unblind";if(!e.nextUrl.pathname.startsWith(a))return null;let t=s||T;if(!t)return console.error("UNBLIND_API_KEY is missing"),i.NextResponse.json({error:"Internal Server Error"},{status:500});try{if(!n&&e.nextUrl.pathname.includes("/tenants/"))return console.error("[Unblind] Unauthorized request (missing tenantId):",{path:e.nextUrl.pathname}),i.NextResponse.json({error:"Internal Server Error"},{status:500});let o=e.nextUrl.pathname.replace(new RegExp(`^${a}`),"").replace(new RegExp("^/tenants/"),"/tenants/"+n+"/"),c=new URL(`${I}${o}`);e.nextUrl.searchParams.forEach((r,P)=>{c.searchParams.append(P,r)});let h={Authorization:`Bearer ${t}`};if(["POST","PUT","PATCH","DELETE"].includes(e.method)){let r=e.headers.get("content-type");r&&(h["Content-Type"]=r)}let m={method:e.method,headers:h};if(["POST","PUT","PATCH","DELETE"].includes(e.method)){let r=await e.text();r&&(m.body=r)}let p=await fetch(c.toString(),m),x=await p.text();return new i.NextResponse(x,{status:p.status,headers:{"Content-Type":p.headers.get("content-type")||"application/json"}})}catch(o){let c=o instanceof Error?o.message:String(o);return console.error("[Unblind]",c),i.NextResponse.json({error:"Internal Server Error"},{status:500})}}0&&(module.exports={unblindHandler,unblindMiddleware,unblindProxy});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../src/server/handler/index.ts"],"sourcesContent":["export { handler as unblindHandler } from \"./handler\";\nexport { handler as unblindProxy } from \"./handler\";\nexport { handler as unblindMiddleware } from \"./handler\";\n","import { NextResponse } from \"next/server\";\n\n// This is Unblid API endpoints.\n//\n// This endpoint is used to interact with all Unblind Internal services.\nconst UNBLIND_API_ENDPOINT =\n process.env.UNBLIND_API_ENDPOINT || \"https://api.unblind.dev/v1\";\nconst UNBLIND_API_KEY = process.env.UNBLIND_API_KEY;\n\n/**\n * Custom NextRequest to avoid compatibility issues with older NextJS versions.\n */\nexport interface NextRequest {\n method: string;\n headers: Headers;\n text(): Promise<string>;\n nextUrl: {\n href: string;\n pathname: string;\n search: string;\n searchParams: URLSearchParams;\n };\n}\n\n/**\n * Unblind API handler for Next.js applications.\n *\n * This handler intercepts requests to `/api/unblind` and proxies them to the Unblind API,\n * automatically adding authentication and tenant context. It returns `null` for requests\n * that don't match the path prefix, allowing Next.js to continue normal routing.\n *\n * **Available as:** `unblindProxy`, `unblindHandler`, or `unblindMiddleware` (all are aliases)\n *\n * @param request - The incoming Next.js request object\n * @param tenantId - The tenant identifier to inject into API paths (e.g., user ID, organization ID)\n * @param apiKey - Optional Unblind API key. Falls back to UNBLIND_API_KEY environment variable\n *\n * @returns A NextResponse with the proxied API response, or null if the request doesn't match `/api/unblind`\n *\n * @example\n * // Usage as Proxy (Starting with Next.js 16 as `proxy.ts`)\n * import { unblindProxy } from \"@unblind/nextjs/server\";\n * import { NextRequest } from \"next/server\";\n *\n * export function proxy(request: NextRequest) {\n * const path = new URL(request.url).pathname;\n *\n * if (path.startsWith(\"/api/unblind\")) {\n * // Extract tenant ID from your auth system (e.g., session, JWT, cookies)\n * const tenantId = request.cookies.get(\"tenantId\")?.value;\n * return unblindProxy(request, tenantId);\n * }\n * }\n *\n * export const config = {\n * matcher: \"/api/unblind/:path*\",\n * };\n *\n * @example\n * // Usage in Middleware with multiple routes\n * import { unblindMiddleware } from \"@unblind/nextjs/server\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export async function middleware(request: NextRequest) {\n *\n * // Let the handler process Unblind API requests\n * if (request.nextUrl.pathname.startsWith(\"/api/unblind\")) {\n * // Extract tenant ID from your auth system\n * const tenantId = request.cookies.get('userId')?.value;\n *\n * const response = await unblindMiddleware(request, tenantId);\n * if (response) {\n * return response;\n * }\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: ['/api/unblind/:path*', '/dashboard/:path*'],\n * };\n */\nexport async function handler(\n request: NextRequest,\n tenantId?: string,\n apiKey?: string,\n): Promise<NextResponse | null> {\n const pathPrefix = \"/api/unblind\";\n\n // Only proxy requests matching the path prefix\n if (!request.nextUrl.pathname.startsWith(pathPrefix)) {\n return null;\n }\n\n const unblindApiKey = apiKey || UNBLIND_API_KEY;\n if (!unblindApiKey) {\n console.error(\"UNBLIND_API_KEY is missing\");\n return NextResponse.json(\n { error: \"Internal Server Error\" },\n { status: 500 },\n );\n }\n\n try {\n if (!tenantId && request.nextUrl.pathname.includes(\"/tenants/\")) {\n console.error(\"[Unblind] Unauthorized request (missing tenantId):\", {\n path: request.nextUrl.pathname,\n });\n return NextResponse.json(\n { error: \"Internal Server Error\" },\n { status: 500 },\n );\n }\n\n // Extract the API path (remove the prefix)\n const apiPath = request.nextUrl.pathname\n .replace(new RegExp(`^${pathPrefix}`), \"\")\n .replace(new RegExp(\"^\\/tenants\\/\"), \"/tenants/\" + tenantId + \"/\");\n const url = new URL(`${UNBLIND_API_ENDPOINT}${apiPath}`);\n\n // Copy query parameters\n request.nextUrl.searchParams.forEach((value: string, key: string) => {\n url.searchParams.append(key, value);\n });\n\n const headers: HeadersInit = {\n Authorization: `Bearer ${unblindApiKey}`,\n };\n\n // Forward Content-Type for requests with body\n if ([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(request.method)) {\n const contentType = request.headers.get(\"content-type\");\n if (contentType) {\n headers[\"Content-Type\"] = contentType;\n }\n }\n\n const options: RequestInit = {\n method: request.method,\n headers,\n };\n\n if ([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(request.method)) {\n const body = await request.text();\n if (body) {\n options.body = body;\n }\n }\n\n const response = await fetch(url.toString(), options);\n const data = await response.text();\n\n return new NextResponse(data, {\n status: response.status,\n headers: {\n \"Content-Type\":\n response.headers.get(\"content-type\") || \"application/json\",\n },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[Unblind]\", message);\n return NextResponse.json(\n { error: \"Internal Server Error\" },\n { status: 500 },\n );\n }\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oBAAAE,EAAA,sBAAAA,EAAA,iBAAAA,IAAA,eAAAC,EAAAH,GCAA,IAAAI,EAA6B,uBAKvBC,EACJ,QAAQ,IAAI,sBAAwB,6BAChCC,EAAkB,QAAQ,IAAI,gBA4EpC,eAAsBC,EACpBC,EACAC,EACAC,EAC8B,CAC9B,IAAMC,EAAa,eAGnB,GAAI,CAACH,EAAQ,QAAQ,SAAS,WAAWG,CAAU,EACjD,OAAO,KAGT,IAAMC,EAAgBF,GAAUJ,EAChC,GAAI,CAACM,EACH,eAAQ,MAAM,4BAA4B,EACnC,eAAa,KAClB,CAAE,MAAO,uBAAwB,EACjC,CAAE,OAAQ,GAAI,CAChB,EAGF,GAAI,CACF,GAAI,CAACH,GAAYD,EAAQ,QAAQ,SAAS,SAAS,WAAW,EAC5D,eAAQ,MAAM,qDAAsD,CAClE,KAAMA,EAAQ,QAAQ,QACxB,CAAC,EACM,eAAa,KAClB,CAAE,MAAO,uBAAwB,EACjC,CAAE,OAAQ,GAAI,CAChB,EAIF,IAAMK,EAAUL,EAAQ,QAAQ,SAC7B,QAAQ,IAAI,OAAO,IAAIG,CAAU,EAAE,EAAG,EAAE,EACxC,QAAQ,IAAI,OAAO,YAAc,EAAG,YAAcF,EAAW,GAAG,EAC7DK,EAAM,IAAI,IAAI,GAAGT,CAAoB,GAAGQ,CAAO,EAAE,EAGvDL,EAAQ,QAAQ,aAAa,QAAQ,CAACO,EAAeC,IAAgB,CACnEF,EAAI,aAAa,OAAOE,EAAKD,CAAK,CACpC,CAAC,EAED,IAAME,EAAuB,CAC3B,cAAe,UAAUL,CAAa,EACxC,EAGA,GAAI,CAAC,OAAQ,MAAO,QAAS,QAAQ,EAAE,SAASJ,EAAQ,MAAM,EAAG,CAC/D,IAAMU,EAAcV,EAAQ,QAAQ,IAAI,cAAc,EAClDU,IACFD,EAAQ,cAAc,EAAIC,EAE9B,CAEA,IAAMC,EAAuB,CAC3B,OAAQX,EAAQ,OAChB,QAAAS,CACF,EAEA,GAAI,CAAC,OAAQ,MAAO,QAAS,QAAQ,EAAE,SAAST,EAAQ,MAAM,EAAG,CAC/D,IAAMY,EAAO,MAAMZ,EAAQ,KAAK,EAC5BY,IACFD,EAAQ,KAAOC,EAEnB,CAEA,IAAMC,EAAW,MAAM,MAAMP,EAAI,SAAS,EAAGK,CAAO,EAC9CG,EAAO,MAAMD,EAAS,KAAK,EAEjC,OAAO,IAAI,eAAaC,EAAM,CAC5B,OAAQD,EAAS,OACjB,QAAS,CACP,eACEA,EAAS,QAAQ,IAAI,cAAc,GAAK,kBAC5C,CACF,CAAC,CACH,OAASE,EAAO,CACd,IAAMC,EAAUD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACrE,eAAQ,MAAM,YAAaC,CAAO,EAC3B,eAAa,KAClB,CAAE,MAAO,uBAAwB,EACjC,CAAE,OAAQ,GAAI,CAChB,CACF,CACF","names":["server_exports","__export","handler","__toCommonJS","import_server","UNBLIND_API_ENDPOINT","UNBLIND_API_KEY","handler","request","tenantId","apiKey","pathPrefix","unblindApiKey","apiPath","url","value","key","headers","contentType","options","body","response","data","error","message"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{NextResponse as s}from"next/server";var P=process.env.UNBLIND_API_ENDPOINT||"https://api.unblind.dev/v1",u=process.env.UNBLIND_API_KEY;async function o(e,i,h){let c="/api/unblind";if(!e.nextUrl.pathname.startsWith(c))return null;let l=h||u;if(!l)return console.error("UNBLIND_API_KEY is missing"),s.json({error:"Internal Server Error"},{status:500});try{if(!i&&e.nextUrl.pathname.includes("/tenants/"))return console.error("[Unblind] Unauthorized request (missing tenantId):",{path:e.nextUrl.pathname}),s.json({error:"Internal Server Error"},{status:500});let t=e.nextUrl.pathname.replace(new RegExp(`^${c}`),"").replace(new RegExp("^/tenants/"),"/tenants/"+i+"/"),r=new URL(`${P}${t}`);e.nextUrl.searchParams.forEach((n,x)=>{r.searchParams.append(x,n)});let p={Authorization:`Bearer ${l}`};if(["POST","PUT","PATCH","DELETE"].includes(e.method)){let n=e.headers.get("content-type");n&&(p["Content-Type"]=n)}let d={method:e.method,headers:p};if(["POST","PUT","PATCH","DELETE"].includes(e.method)){let n=await e.text();n&&(d.body=n)}let a=await fetch(r.toString(),d),m=await a.text();return new s(m,{status:a.status,headers:{"Content-Type":a.headers.get("content-type")||"application/json"}})}catch(t){let r=t instanceof Error?t.message:String(t);return console.error("[Unblind]",r),s.json({error:"Internal Server Error"},{status:500})}}export{o as unblindHandler,o as unblindMiddleware,o as unblindProxy};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/handler/index.ts"],"sourcesContent":["import { NextResponse } from \"next/server\";\n\n// This is Unblid API endpoints.\n//\n// This endpoint is used to interact with all Unblind Internal services.\nconst UNBLIND_API_ENDPOINT =\n process.env.UNBLIND_API_ENDPOINT || \"https://api.unblind.dev/v1\";\nconst UNBLIND_API_KEY = process.env.UNBLIND_API_KEY;\n\n/**\n * Custom NextRequest to avoid compatibility issues with older NextJS versions.\n */\nexport interface NextRequest {\n method: string;\n headers: Headers;\n text(): Promise<string>;\n nextUrl: {\n href: string;\n pathname: string;\n search: string;\n searchParams: URLSearchParams;\n };\n}\n\n/**\n * Unblind API handler for Next.js applications.\n *\n * This handler intercepts requests to `/api/unblind` and proxies them to the Unblind API,\n * automatically adding authentication and tenant context. It returns `null` for requests\n * that don't match the path prefix, allowing Next.js to continue normal routing.\n *\n * **Available as:** `unblindProxy`, `unblindHandler`, or `unblindMiddleware` (all are aliases)\n *\n * @param request - The incoming Next.js request object\n * @param tenantId - The tenant identifier to inject into API paths (e.g., user ID, organization ID)\n * @param apiKey - Optional Unblind API key. Falls back to UNBLIND_API_KEY environment variable\n *\n * @returns A NextResponse with the proxied API response, or null if the request doesn't match `/api/unblind`\n *\n * @example\n * // Usage as Proxy (Starting with Next.js 16 as `proxy.ts`)\n * import { unblindProxy } from \"@unblind/nextjs/server\";\n * import { NextRequest } from \"next/server\";\n *\n * export function proxy(request: NextRequest) {\n * const path = new URL(request.url).pathname;\n *\n * if (path.startsWith(\"/api/unblind\")) {\n * // Extract tenant ID from your auth system (e.g., session, JWT, cookies)\n * const tenantId = request.cookies.get(\"tenantId\")?.value;\n * return unblindProxy(request, tenantId);\n * }\n * }\n *\n * export const config = {\n * matcher: \"/api/unblind/:path*\",\n * };\n *\n * @example\n * // Usage in Middleware with multiple routes\n * import { unblindMiddleware } from \"@unblind/nextjs/server\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export async function middleware(request: NextRequest) {\n *\n * // Let the handler process Unblind API requests\n * if (request.nextUrl.pathname.startsWith(\"/api/unblind\")) {\n * // Extract tenant ID from your auth system\n * const tenantId = request.cookies.get('userId')?.value;\n *\n * const response = await unblindMiddleware(request, tenantId);\n * if (response) {\n * return response;\n * }\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: ['/api/unblind/:path*', '/dashboard/:path*'],\n * };\n */\nexport async function handler(\n request: NextRequest,\n tenantId?: string,\n apiKey?: string,\n): Promise<NextResponse | null> {\n const pathPrefix = \"/api/unblind\";\n\n // Only proxy requests matching the path prefix\n if (!request.nextUrl.pathname.startsWith(pathPrefix)) {\n return null;\n }\n\n const unblindApiKey = apiKey || UNBLIND_API_KEY;\n if (!unblindApiKey) {\n console.error(\"UNBLIND_API_KEY is missing\");\n return NextResponse.json(\n { error: \"Internal Server Error\" },\n { status: 500 },\n );\n }\n\n try {\n if (!tenantId && request.nextUrl.pathname.includes(\"/tenants/\")) {\n console.error(\"[Unblind] Unauthorized request (missing tenantId):\", {\n path: request.nextUrl.pathname,\n });\n return NextResponse.json(\n { error: \"Internal Server Error\" },\n { status: 500 },\n );\n }\n\n // Extract the API path (remove the prefix)\n const apiPath = request.nextUrl.pathname\n .replace(new RegExp(`^${pathPrefix}`), \"\")\n .replace(new RegExp(\"^\\/tenants\\/\"), \"/tenants/\" + tenantId + \"/\");\n const url = new URL(`${UNBLIND_API_ENDPOINT}${apiPath}`);\n\n // Copy query parameters\n request.nextUrl.searchParams.forEach((value: string, key: string) => {\n url.searchParams.append(key, value);\n });\n\n const headers: HeadersInit = {\n Authorization: `Bearer ${unblindApiKey}`,\n };\n\n // Forward Content-Type for requests with body\n if ([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(request.method)) {\n const contentType = request.headers.get(\"content-type\");\n if (contentType) {\n headers[\"Content-Type\"] = contentType;\n }\n }\n\n const options: RequestInit = {\n method: request.method,\n headers,\n };\n\n if ([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(request.method)) {\n const body = await request.text();\n if (body) {\n options.body = body;\n }\n }\n\n const response = await fetch(url.toString(), options);\n const data = await response.text();\n\n return new NextResponse(data, {\n status: response.status,\n headers: {\n \"Content-Type\":\n response.headers.get(\"content-type\") || \"application/json\",\n },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[Unblind]\", message);\n return NextResponse.json(\n { error: \"Internal Server Error\" },\n { status: 500 },\n );\n }\n}\n"],"mappings":"AAAA,OAAS,gBAAAA,MAAoB,cAK7B,IAAMC,EACJ,QAAQ,IAAI,sBAAwB,6BAChCC,EAAkB,QAAQ,IAAI,gBA4EpC,eAAsBC,EACpBC,EACAC,EACAC,EAC8B,CAC9B,IAAMC,EAAa,eAGnB,GAAI,CAACH,EAAQ,QAAQ,SAAS,WAAWG,CAAU,EACjD,OAAO,KAGT,IAAMC,EAAgBF,GAAUJ,EAChC,GAAI,CAACM,EACH,eAAQ,MAAM,4BAA4B,EACnCR,EAAa,KAClB,CAAE,MAAO,uBAAwB,EACjC,CAAE,OAAQ,GAAI,CAChB,EAGF,GAAI,CACF,GAAI,CAACK,GAAYD,EAAQ,QAAQ,SAAS,SAAS,WAAW,EAC5D,eAAQ,MAAM,qDAAsD,CAClE,KAAMA,EAAQ,QAAQ,QACxB,CAAC,EACMJ,EAAa,KAClB,CAAE,MAAO,uBAAwB,EACjC,CAAE,OAAQ,GAAI,CAChB,EAIF,IAAMS,EAAUL,EAAQ,QAAQ,SAC7B,QAAQ,IAAI,OAAO,IAAIG,CAAU,EAAE,EAAG,EAAE,EACxC,QAAQ,IAAI,OAAO,YAAc,EAAG,YAAcF,EAAW,GAAG,EAC7DK,EAAM,IAAI,IAAI,GAAGT,CAAoB,GAAGQ,CAAO,EAAE,EAGvDL,EAAQ,QAAQ,aAAa,QAAQ,CAACO,EAAeC,IAAgB,CACnEF,EAAI,aAAa,OAAOE,EAAKD,CAAK,CACpC,CAAC,EAED,IAAME,EAAuB,CAC3B,cAAe,UAAUL,CAAa,EACxC,EAGA,GAAI,CAAC,OAAQ,MAAO,QAAS,QAAQ,EAAE,SAASJ,EAAQ,MAAM,EAAG,CAC/D,IAAMU,EAAcV,EAAQ,QAAQ,IAAI,cAAc,EAClDU,IACFD,EAAQ,cAAc,EAAIC,EAE9B,CAEA,IAAMC,EAAuB,CAC3B,OAAQX,EAAQ,OAChB,QAAAS,CACF,EAEA,GAAI,CAAC,OAAQ,MAAO,QAAS,QAAQ,EAAE,SAAST,EAAQ,MAAM,EAAG,CAC/D,IAAMY,EAAO,MAAMZ,EAAQ,KAAK,EAC5BY,IACFD,EAAQ,KAAOC,EAEnB,CAEA,IAAMC,EAAW,MAAM,MAAMP,EAAI,SAAS,EAAGK,CAAO,EAC9CG,EAAO,MAAMD,EAAS,KAAK,EAEjC,OAAO,IAAIjB,EAAakB,EAAM,CAC5B,OAAQD,EAAS,OACjB,QAAS,CACP,eACEA,EAAS,QAAQ,IAAI,cAAc,GAAK,kBAC5C,CACF,CAAC,CACH,OAASE,EAAO,CACd,IAAMC,EAAUD,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,EACrE,eAAQ,MAAM,YAAaC,CAAO,EAC3BpB,EAAa,KAClB,CAAE,MAAO,uBAAwB,EACjC,CAAE,OAAQ,GAAI,CAChB,CACF,CACF","names":["NextResponse","UNBLIND_API_ENDPOINT","UNBLIND_API_KEY","handler","request","tenantId","apiKey","pathPrefix","unblindApiKey","apiPath","url","value","key","headers","contentType","options","body","response","data","error","message"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unblind/nextjs",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Unblind Next.js library",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./server": {
|
|
15
|
+
"types": "./dist/server/index.d.ts",
|
|
16
|
+
"import": "./dist/server/index.mjs",
|
|
17
|
+
"require": "./dist/server/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"dev": "tsup --watch",
|
|
26
|
+
"lint": "eslint src/",
|
|
27
|
+
"check-types": "tsc --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@unblind/react": "workspace:*"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"prettier": "^3.5.3",
|
|
34
|
+
"typescript": "5.8.2",
|
|
35
|
+
"tsup": "^8.3.5"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"next": "^16",
|
|
39
|
+
"react": "^18.0.0",
|
|
40
|
+
"react-dom": "^18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"packageManager": "pnpm@9.0.0",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18"
|
|
45
|
+
}
|
|
46
|
+
}
|