@veap/plugins 0.1.0 → 0.1.3
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/README.md +3 -2
- package/dist/common/index.d.ts +4 -3
- package/dist/common/index.js +4 -3
- package/dist/common/tokens.d.ts +14 -0
- package/dist/common/tokens.js +12 -0
- package/dist/common/types.d.ts +11 -4
- package/dist/common/types.js +1 -2
- package/dist/composition.d.ts +15 -0
- package/dist/composition.js +20 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +6 -5
- package/dist/providers/plugins.provider.js +11 -10
- package/dist/registry/registry.service.d.ts +1 -1
- package/dist/router/index.d.ts +10 -9
- package/dist/router/index.js +10 -9
- package/dist/router/middlewares.js +31 -15
- package/dist/router/react/soft-navigation.d.ts +4 -2
- package/dist/router/react/soft-navigation.js +14 -7
- package/dist/router/react/with-router.js +8 -3
- package/dist/router/route-tree.d.ts +27 -1
- package/dist/router/route-tree.js +8 -2
- package/package.json +5 -9
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
[](https://github.com/veapjs/veap-plugins/actions/workflows/CI.yml)
|
|
2
|
+
[](https://github.com/veapjs/veap-plugins/actions/workflows/RELEASE.yml)
|
|
3
|
+
[](https://www.npmjs.com/package/@veap/plugins)
|
|
3
4
|
|
|
4
5
|
# @veap/plugins
|
|
5
6
|
|
package/dist/common/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from "./context";
|
|
2
|
-
export * from "./events";
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./context.js";
|
|
2
|
+
export * from "./events.js";
|
|
3
|
+
export * from "./tokens.js";
|
|
4
|
+
export * from "./types.js";
|
package/dist/common/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from "./context";
|
|
2
|
-
export * from "./events";
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./context.js";
|
|
2
|
+
export * from "./events.js";
|
|
3
|
+
export * from "./tokens.js";
|
|
4
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Token } from "@veap/kernel";
|
|
2
|
+
import type { RouterService } from "../router/router.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* IoC Token for the application plugins array.
|
|
5
|
+
*/
|
|
6
|
+
export declare const APP_PLUGINS: Token<any[]>;
|
|
7
|
+
/**
|
|
8
|
+
* IoC Token for the virtual RouterService.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ROUTER_SERVICE: Token<RouterService>;
|
|
11
|
+
/**
|
|
12
|
+
* IoC Token for the main site layout component.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SITE_LAYOUT: Token<any>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IoC Token for the application plugins array.
|
|
3
|
+
*/
|
|
4
|
+
export const APP_PLUGINS = Symbol.for("veap:kernel:app-plugins");
|
|
5
|
+
/**
|
|
6
|
+
* IoC Token for the virtual RouterService.
|
|
7
|
+
*/
|
|
8
|
+
export const ROUTER_SERVICE = Symbol.for("veap:router:service");
|
|
9
|
+
/**
|
|
10
|
+
* IoC Token for the main site layout component.
|
|
11
|
+
*/
|
|
12
|
+
export const SITE_LAYOUT = Symbol.for("veap:router:site-layout");
|
package/dist/common/types.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { UserPermission, UserRole } from "@veap/auth";
|
|
2
2
|
import type { SystemEvent } from "@veap/kernel";
|
|
3
3
|
export type { SystemEvent };
|
|
4
|
+
declare module "@veap/kernel" {
|
|
5
|
+
interface VeapConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Prefix for all administrative routes.
|
|
8
|
+
* Default: "/app"
|
|
9
|
+
*/
|
|
10
|
+
privatePath?: string;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
4
13
|
import type * as React from "react";
|
|
5
14
|
import { z } from "zod";
|
|
6
15
|
export type SidebarGroupType = {
|
|
@@ -49,8 +58,7 @@ export interface PluginManifest {
|
|
|
49
58
|
[key: string]: any;
|
|
50
59
|
}
|
|
51
60
|
/**
|
|
52
|
-
* Shape of the `veap` field in a plugin `package.json
|
|
53
|
-
* This replaces the standalone `manifest.json` file.
|
|
61
|
+
* Shape of the `veap` field in a plugin `package.json`.\n * This replaces the standalone `manifest.json` file.
|
|
54
62
|
*/
|
|
55
63
|
export interface VeapPackageMetadata {
|
|
56
64
|
type?: string;
|
|
@@ -77,8 +85,7 @@ export interface VeapPackageJson {
|
|
|
77
85
|
[key: string]: any;
|
|
78
86
|
}
|
|
79
87
|
/**
|
|
80
|
-
* Helper to build a `PluginManifest` from a `package.json` import.
|
|
81
|
-
* Eliminates the need for a standalone `manifest.json` file.
|
|
88
|
+
* Helper to build a `PluginManifest` from a `package.json` import.\n * Eliminates the need for a standalone `manifest.json` file.
|
|
82
89
|
*
|
|
83
90
|
* @example
|
|
84
91
|
* ```ts
|
package/dist/common/types.js
CHANGED
|
@@ -12,8 +12,7 @@ export const PluginManifestSchema = z.object({
|
|
|
12
12
|
author: z.string().optional(),
|
|
13
13
|
});
|
|
14
14
|
/**
|
|
15
|
-
* Helper to build a `PluginManifest` from a `package.json` import.
|
|
16
|
-
* Eliminates the need for a standalone `manifest.json` file.
|
|
15
|
+
* Helper to build a `PluginManifest` from a `package.json` import.\n * Eliminates the need for a standalone `manifest.json` file.
|
|
17
16
|
*
|
|
18
17
|
* @example
|
|
19
18
|
* ```ts
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ServiceProvider } from "@veap/kernel";
|
|
2
|
+
declare module "@veap/kernel" {
|
|
3
|
+
interface ApplicationBuilder {
|
|
4
|
+
/**
|
|
5
|
+
* Registers plugins with the application IoC container and configures PluginsServiceProvider.
|
|
6
|
+
*/
|
|
7
|
+
withPlugins(plugins: any[]): this;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
declare class PluginsConfigProvider extends ServiceProvider {
|
|
11
|
+
private plugins;
|
|
12
|
+
constructor(container: any, plugins?: any[]);
|
|
13
|
+
register(): void;
|
|
14
|
+
}
|
|
15
|
+
export { PluginsConfigProvider };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ApplicationBuilder, ServiceProvider } from "@veap/kernel";
|
|
2
|
+
import { APP_PLUGINS } from "./common/tokens.js";
|
|
3
|
+
import { PluginsServiceProvider } from "./providers/plugins.provider.js";
|
|
4
|
+
class PluginsConfigProvider extends ServiceProvider {
|
|
5
|
+
plugins;
|
|
6
|
+
constructor(container, plugins = []) {
|
|
7
|
+
super(container);
|
|
8
|
+
this.plugins = plugins;
|
|
9
|
+
}
|
|
10
|
+
register() {
|
|
11
|
+
this.container.register({ token: APP_PLUGINS, useValue: this.plugins });
|
|
12
|
+
this.container.register({ token: "AppPlugins", useValue: this.plugins });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (!ApplicationBuilder.prototype.withPlugins) {
|
|
16
|
+
ApplicationBuilder.prototype.withPlugins = function (plugins) {
|
|
17
|
+
return this.use((c) => new PluginsConfigProvider(c, plugins)).use(PluginsServiceProvider);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export { PluginsConfigProvider };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from "./common";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./
|
|
1
|
+
export * from "./common/index.js";
|
|
2
|
+
export * from "./composition.js";
|
|
3
|
+
export * from "./migrations/index.js";
|
|
4
|
+
export * from "./navigation/index.js";
|
|
5
|
+
export * from "./providers/index.js";
|
|
6
|
+
export * from "./registry/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from "./common";
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./
|
|
1
|
+
export * from "./common/index.js";
|
|
2
|
+
export * from "./composition.js";
|
|
3
|
+
export * from "./migrations/index.js";
|
|
4
|
+
export * from "./navigation/index.js";
|
|
5
|
+
export * from "./providers/index.js";
|
|
6
|
+
export * from "./registry/index.js";
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { isDatabaseInitialized } from "@veap/database";
|
|
2
2
|
import { IntlService } from "@veap/intl/server";
|
|
3
|
-
import {
|
|
4
|
-
import { bindPluginsContext } from "../common/context";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
3
|
+
import { eventBus, ServiceProvider } from "@veap/kernel";
|
|
4
|
+
import { bindPluginsContext } from "../common/context.js";
|
|
5
|
+
import { APP_PLUGINS, ROUTER_SERVICE, SITE_LAYOUT } from "../common/tokens.js";
|
|
6
|
+
import { runPluginMigrations } from "../migrations/index.js";
|
|
7
|
+
import { NavigationService } from "../navigation/navigation.service.js";
|
|
8
|
+
import { MIGRATION_RUNNER, PLUGIN_REPOSITORY } from "../registry/contracts.js";
|
|
9
|
+
import { ensurePluginsInitialized, registerPlugins, } from "../registry/facade.js";
|
|
10
|
+
import { KnexMigrationRunner } from "../registry/migration-runner.js";
|
|
11
|
+
import { ActiveRecordPluginRepository } from "../registry/plugin.repository.js";
|
|
12
|
+
import { PluginRegistry } from "../registry/registry.service.js";
|
|
13
|
+
import { RouterService } from "../router/router.service.js";
|
|
13
14
|
export class PluginsServiceProvider extends ServiceProvider {
|
|
14
15
|
config;
|
|
15
16
|
constructor(container, config) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type IEventBus, type ILogger } from "@veap/kernel";
|
|
2
|
-
import { type IMigrationRunner, type IPluginRepository } from "./contracts";
|
|
3
2
|
import type { IPlugin } from "../common";
|
|
3
|
+
import { type IMigrationRunner, type IPluginRepository } from "./contracts";
|
|
4
4
|
export declare class PluginRegistry {
|
|
5
5
|
private readonly repository;
|
|
6
6
|
private readonly migrationRunner;
|
package/dist/router/index.d.ts
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* @module router
|
|
3
3
|
* @description Virtual Router API for Veap Plugin system.
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
5
|
+
export { ROUTER_SERVICE, SITE_LAYOUT } from "../common/tokens.js";
|
|
6
|
+
export { addRouteRewrite, buildRouteTree, getModulesWithHomepage, getPluginsWithHomepage, getRouteRewrites, matchRoute, } from "./discovery.js";
|
|
7
|
+
export { handleVeapApiRequest } from "./handler.js";
|
|
8
|
+
export { matchRoute as matchVirtualRoute } from "./matcher.js";
|
|
9
|
+
export { ApiEnsuredAuth, ApiSameOrigin, EnsuredAuth, EnsuredGuest, EnsuredUser, runApiPipeline, runPipeline, SameOrigin, SkipSecurity, } from "./middlewares.js";
|
|
10
|
+
export { RouterErrorBoundary, SoftNavigationInterceptor, VeapRouter, type WithRouterConfig, withRouter, } from "./react/index.js";
|
|
11
|
+
export { extractParamName, isCatchAllSegment, isDynamicSegment, isGroupSegment, isOptionalCatchAllSegment, isParallelSlot, type LayoutChainEntry, type MatchResult, type RouteNode, RouteTree, resolveMagicPrefix, segmentMatchesUrlPart, } from "./route-tree.js";
|
|
12
|
+
export { RouterService } from "./router.service.js";
|
|
13
|
+
export { discoverRoutes, generateRouteManifest, globToTree, } from "./scanner.js";
|
|
14
|
+
export { collectApiMiddlewares, collectAuthRequirements, collectMiddlewares, } from "./utils.js";
|
package/dist/router/index.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* @module router
|
|
3
3
|
* @description Virtual Router API for Veap Plugin system.
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
5
|
+
export { ROUTER_SERVICE, SITE_LAYOUT } from "../common/tokens.js";
|
|
6
|
+
export { addRouteRewrite, buildRouteTree, getModulesWithHomepage, getPluginsWithHomepage, getRouteRewrites, matchRoute, } from "./discovery.js";
|
|
7
|
+
export { handleVeapApiRequest } from "./handler.js";
|
|
8
|
+
export { matchRoute as matchVirtualRoute } from "./matcher.js";
|
|
9
|
+
export { ApiEnsuredAuth, ApiSameOrigin, EnsuredAuth, EnsuredGuest, EnsuredUser, runApiPipeline, runPipeline, SameOrigin, SkipSecurity, } from "./middlewares.js";
|
|
10
|
+
export { RouterErrorBoundary, SoftNavigationInterceptor, VeapRouter, withRouter, } from "./react/index.js";
|
|
11
|
+
export { extractParamName, isCatchAllSegment, isDynamicSegment, isGroupSegment, isOptionalCatchAllSegment, isParallelSlot, RouteTree, resolveMagicPrefix, segmentMatchesUrlPart, } from "./route-tree.js";
|
|
12
|
+
export { RouterService } from "./router.service.js";
|
|
13
|
+
export { discoverRoutes, generateRouteManifest, globToTree, } from "./scanner.js";
|
|
14
|
+
export { collectApiMiddlewares, collectAuthRequirements, collectMiddlewares, } from "./utils.js";
|
|
@@ -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
|
|
9
|
-
const 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
75
|
-
const origin =
|
|
76
|
-
const secFetchSite =
|
|
77
|
-
const secFetchMode =
|
|
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
|
-
|
|
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
|
|
2
|
+
export interface SoftNavigationInterceptorProps {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
-
|
|
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
|
-
|
|
27
|
-
|
|
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
|
-
}, [
|
|
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 {
|
|
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
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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
|
/**
|
|
@@ -186,7 +186,10 @@ function matchRecursive(node, remainingSegments, currentParams, currentChain, cu
|
|
|
186
186
|
!isOptionalCatchAllSegment(child.segment) &&
|
|
187
187
|
child.segment === currentSegment) {
|
|
188
188
|
const nextChain = hasLayoutChainContent(child)
|
|
189
|
-
? [
|
|
189
|
+
? [
|
|
190
|
+
...currentChain,
|
|
191
|
+
buildChainEntry(child, [...currentMatched, currentSegment]),
|
|
192
|
+
]
|
|
190
193
|
: currentChain;
|
|
191
194
|
const result = matchRecursive(child, rest, currentParams, nextChain, [...currentMatched, currentSegment], bestPartialMatch);
|
|
192
195
|
if (result)
|
|
@@ -205,7 +208,10 @@ function matchRecursive(node, remainingSegments, currentParams, currentChain, cu
|
|
|
205
208
|
if (isDynamicSegment(child.segment)) {
|
|
206
209
|
const paramName = extractParamName(child.segment);
|
|
207
210
|
const nextChain = hasLayoutChainContent(child)
|
|
208
|
-
? [
|
|
211
|
+
? [
|
|
212
|
+
...currentChain,
|
|
213
|
+
buildChainEntry(child, [...currentMatched, currentSegment]),
|
|
214
|
+
]
|
|
209
215
|
: currentChain;
|
|
210
216
|
const result = matchRecursive(child, rest, { ...currentParams, [paramName]: currentSegment }, nextChain, [...currentMatched, currentSegment], bestPartialMatch);
|
|
211
217
|
if (result)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veap/plugins",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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": {
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"@dnd-kit/core": "^6.3.1",
|
|
57
57
|
"@dnd-kit/sortable": "^10.0.0",
|
|
58
58
|
"@dnd-kit/utilities": "^3.2.2",
|
|
59
|
-
"@veap/auth": "0.1.
|
|
60
|
-
"@veap/database": "0.1.
|
|
61
|
-
"@veap/intl": "0.1.
|
|
62
|
-
"@veap/kernel": "0.1.
|
|
59
|
+
"@veap/auth": "0.1.1",
|
|
60
|
+
"@veap/database": "0.1.1",
|
|
61
|
+
"@veap/intl": "0.1.2",
|
|
62
|
+
"@veap/kernel": "0.1.2",
|
|
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
|
},
|