@veap/plugins 0.1.1 → 0.1.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.
@@ -1,16 +1,14 @@
1
1
  import { checkSecurity, getAuthRoutes, getCurrentSession } from "@veap/auth";
2
- import { AppError, verifySameOrigin } from "@veap/kernel";
3
- import { headers } from "next/headers";
4
- import { redirect } from "next/navigation";
2
+ import { AppError, app, REQUEST_CONTEXT, verifySameOrigin, } from "@veap/kernel";
5
3
  export const EnsuredGuest = async (ctx, next) => {
6
4
  const { user, session } = await getCurrentSession();
7
5
  if (user && session) {
8
- const headersList = await headers();
9
- const referer = headersList.get("referer");
6
+ const requestContext = await app(REQUEST_CONTEXT);
7
+ const referer = await requestContext.getHeader("referer");
10
8
  if (referer && !referer.includes(ctx.path)) {
11
- return redirect(referer);
9
+ return requestContext.redirect(referer);
12
10
  }
13
- return redirect("/");
11
+ return requestContext.redirect("/");
14
12
  }
15
13
  return await next();
16
14
  };
@@ -18,7 +16,8 @@ export const EnsuredUser = async (_ctx, next) => {
18
16
  const { user, session } = await getCurrentSession();
19
17
  if (!user || !session) {
20
18
  const authRoutes = getAuthRoutes();
21
- return redirect(authRoutes.signIn);
19
+ const requestContext = await app(REQUEST_CONTEXT);
20
+ return requestContext.redirect(authRoutes.signIn);
22
21
  }
23
22
  return await next();
24
23
  };
@@ -38,11 +37,13 @@ export const EnsuredAuth = async (ctx, next) => {
38
37
  const { user, session } = await getCurrentSession();
39
38
  const authRoutes = getAuthRoutes();
40
39
  if (!user || !session) {
41
- return redirect(authRoutes.signIn);
40
+ const requestContext = await app(REQUEST_CONTEXT);
41
+ return requestContext.redirect(authRoutes.signIn);
42
42
  }
43
43
  const security = await checkSecurity(session, user, ctx.roles, ctx.permissions, undefined, ctx.path);
44
44
  if (!security.satisfied) {
45
- return redirect(security.redirect || authRoutes.signIn);
45
+ const requestContext = await app(REQUEST_CONTEXT);
46
+ return requestContext.redirect(security.redirect || authRoutes.signIn);
46
47
  }
47
48
  return await next();
48
49
  };
@@ -71,12 +72,27 @@ export const ApiEnsuredAuth = async (_request, context, next) => {
71
72
  * Throws AppError.Forbidden if request originates from an untrusted origin.
72
73
  */
73
74
  export const SameOrigin = async (_ctx, next) => {
74
- const headersList = await headers();
75
- const origin = headersList.get("origin");
76
- const secFetchSite = headersList.get("sec-fetch-site");
77
- const secFetchMode = headersList.get("sec-fetch-mode");
75
+ const requestContext = await app(REQUEST_CONTEXT);
76
+ const origin = await requestContext.getHeader("origin");
77
+ const secFetchSite = await requestContext.getHeader("sec-fetch-site");
78
+ const secFetchMode = await requestContext.getHeader("sec-fetch-mode");
78
79
  if (origin || (secFetchSite && secFetchMode !== "navigate")) {
79
- if (!verifySameOrigin({ headers: headersList, method: "POST" })) {
80
+ const host = await requestContext.getHeader("host");
81
+ const xForwardedHost = await requestContext.getHeader("x-forwarded-host");
82
+ const headersMap = new Map([
83
+ ["origin", origin],
84
+ ["sec-fetch-site", secFetchSite],
85
+ ["sec-fetch-mode", secFetchMode],
86
+ ["host", host],
87
+ ["x-forwarded-host", xForwardedHost],
88
+ ]);
89
+ const requestLike = {
90
+ headers: {
91
+ get: (name) => headersMap.get(name.toLowerCase()) ?? null,
92
+ },
93
+ method: "POST",
94
+ };
95
+ if (!verifySameOrigin(requestLike)) {
80
96
  throw AppError.Forbidden("Cross-origin request rejected");
81
97
  }
82
98
  }
@@ -1,4 +1,6 @@
1
1
  import * as React from "react";
2
- export declare function SoftNavigationInterceptor({ children, }: {
2
+ export interface SoftNavigationInterceptorProps {
3
3
  children: React.ReactNode;
4
- }): React.JSX.Element;
4
+ onNavigate?: (href: string) => void;
5
+ }
6
+ export declare function SoftNavigationInterceptor({ children, onNavigate, }: SoftNavigationInterceptorProps): React.JSX.Element;
@@ -1,9 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
- import { useRouter } from "next/navigation";
4
3
  import * as React from "react";
5
- export function SoftNavigationInterceptor({ children, }) {
6
- const router = useRouter();
4
+ export function SoftNavigationInterceptor({ children, onNavigate, }) {
7
5
  React.useEffect(() => {
8
6
  const handleClick = (e) => {
9
7
  // Ignore clicks with modifiers
@@ -22,13 +20,22 @@ export function SoftNavigationInterceptor({ children, }) {
22
20
  // Only intercept internal links
23
21
  if (href?.startsWith("/") &&
24
22
  !href.startsWith("//") &&
25
- anchor.target !== "_blank") {
26
- e.preventDefault();
27
- router.push(href);
23
+ anchor.target !== "_blank" &&
24
+ !anchor.hasAttribute("download") &&
25
+ anchor.getAttribute("rel") !== "external") {
26
+ if (onNavigate) {
27
+ e.preventDefault();
28
+ onNavigate(href);
29
+ }
30
+ else if (typeof window !== "undefined") {
31
+ e.preventDefault();
32
+ window.history.pushState(null, "", href);
33
+ window.dispatchEvent(new PopStateEvent("popstate"));
34
+ }
28
35
  }
29
36
  };
30
37
  document.addEventListener("click", handleClick);
31
38
  return () => document.removeEventListener("click", handleClick);
32
- }, [router]);
39
+ }, [onNavigate]);
33
40
  return _jsx(_Fragment, { children: children });
34
41
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { headers } from "next/headers";
2
+ import { app, REQUEST_CONTEXT } from "@veap/kernel";
3
3
  import { buildRouteTree } from "../discovery";
4
4
  import { VeapRouter } from "./renderer";
5
5
  export function withRouter(Component, configOrPath) {
@@ -10,8 +10,13 @@ export function withRouter(Component, configOrPath) {
10
10
  : configOrPath || {};
11
11
  let routePath = config.path;
12
12
  if (!routePath) {
13
- const headersList = await headers();
14
- routePath = headersList.get("x-invoke-path") || "/";
13
+ try {
14
+ const requestContext = await app(REQUEST_CONTEXT);
15
+ routePath = (await requestContext.getHeader("x-invoke-path")) || "/";
16
+ }
17
+ catch (_e) {
18
+ routePath = "/";
19
+ }
15
20
  }
16
21
  const tree = await buildRouteTree(true);
17
22
  return (_jsx(VeapRouter, { tree: tree, path: routePath || "/", searchParams: searchParams, CustomPageComponent: Component, customConfig: config }));
@@ -24,7 +24,33 @@
24
24
  * ```
25
25
  */
26
26
  import type { UserPermission, UserRole } from "@veap/auth";
27
- import type { Metadata } from "next";
27
+ /**
28
+ * Framework-agnostic metadata shape for route nodes.
29
+ * Compatible with Next.js Metadata and standard HTML meta tags.
30
+ */
31
+ export interface VeapMetadata {
32
+ title?: string | {
33
+ default: string;
34
+ template?: string;
35
+ absolute?: string;
36
+ };
37
+ description?: string;
38
+ keywords?: string | string[];
39
+ authors?: Array<{
40
+ name?: string;
41
+ url?: string;
42
+ }>;
43
+ creator?: string;
44
+ publisher?: string;
45
+ robots?: any;
46
+ icons?: any;
47
+ openGraph?: any;
48
+ twitter?: any;
49
+ alternates?: any;
50
+ other?: Record<string, string | number | (string | number)[]>;
51
+ [key: string]: any;
52
+ }
53
+ export type Metadata = VeapMetadata;
28
54
  import type * as React from "react";
29
55
  import type { ApiMiddleware, BreadcrumbValue, VeapMiddleware } from "../common/types";
30
56
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veap/plugins",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "Plugin lifecycle, extension points, and virtual router for Veap",
5
5
  "bugs": "https://github.com/veapjs/veap-plugins/issues",
6
6
  "repository": {
@@ -58,8 +58,8 @@
58
58
  "@dnd-kit/utilities": "^3.2.2",
59
59
  "@veap/auth": "0.1.1",
60
60
  "@veap/database": "0.1.1",
61
- "@veap/intl": "0.1.1",
62
- "@veap/kernel": "0.1.1",
61
+ "@veap/intl": "0.1.3",
62
+ "@veap/kernel": "0.1.3",
63
63
  "chalk": "^5.3.0",
64
64
  "ora": "^8.1.1",
65
65
  "zod": "^4.6.5"
@@ -68,7 +68,6 @@
68
68
  "@iconify/react": "^6.0.2",
69
69
  "@veap/ui": "^0.1.0",
70
70
  "lucide-react": "^1.55.0",
71
- "next": "^16",
72
71
  "react": "^19",
73
72
  "react-dom": "^19",
74
73
  "sonner": "^2.0.8"
@@ -83,9 +82,6 @@
83
82
  "lucide-react": {
84
83
  "optional": true
85
84
  },
86
- "next": {
87
- "optional": true
88
- },
89
85
  "react": {
90
86
  "optional": true
91
87
  },