@korioinc/next-core 1.0.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/LICENSE +21 -0
- package/README.md +90 -0
- package/dist/ads/components/AdContainer.d.ts +12 -0
- package/dist/ads/components/AdContainer.d.ts.map +1 -0
- package/dist/ads/components/AdContainer.js +287 -0
- package/dist/ads/components/GoogleAdSense.d.ts +6 -0
- package/dist/ads/components/GoogleAdSense.d.ts.map +1 -0
- package/dist/ads/components/GoogleAdSense.js +6 -0
- package/dist/ads/components/MockAdDisplay.d.ts +8 -0
- package/dist/ads/components/MockAdDisplay.d.ts.map +1 -0
- package/dist/ads/components/MockAdDisplay.js +13 -0
- package/dist/ads/config.d.ts +3 -0
- package/dist/ads/config.d.ts.map +1 -0
- package/dist/ads/config.js +134 -0
- package/dist/ads/index.d.ts +6 -0
- package/dist/ads/index.d.ts.map +1 -0
- package/dist/ads/index.js +7 -0
- package/dist/ads/types.d.ts +15 -0
- package/dist/ads/types.d.ts.map +1 -0
- package/dist/ads/types.js +1 -0
- package/dist/api-client/index.d.ts +31 -0
- package/dist/api-client/index.d.ts.map +1 -0
- package/dist/api-client/index.js +90 -0
- package/dist/auth/auth-manager.d.ts +45 -0
- package/dist/auth/auth-manager.d.ts.map +1 -0
- package/dist/auth/auth-manager.js +75 -0
- package/dist/auth/index.client.d.ts +7 -0
- package/dist/auth/index.client.d.ts.map +1 -0
- package/dist/auth/index.client.js +5 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +11 -0
- package/dist/auth/index.server.d.ts +7 -0
- package/dist/auth/index.server.d.ts.map +1 -0
- package/dist/auth/index.server.js +5 -0
- package/dist/auth/providers/auth-context-provider.d.ts +21 -0
- package/dist/auth/providers/auth-context-provider.d.ts.map +1 -0
- package/dist/auth/providers/auth-context-provider.js +74 -0
- package/dist/auth/routing.d.ts +3 -0
- package/dist/auth/routing.d.ts.map +1 -0
- package/dist/auth/routing.js +40 -0
- package/dist/auth/types/auth.d.ts +23 -0
- package/dist/auth/types/auth.d.ts.map +1 -0
- package/dist/auth/types/auth.js +1 -0
- package/dist/auth/types/user.d.ts +6 -0
- package/dist/auth/types/user.d.ts.map +1 -0
- package/dist/auth/types/user.js +1 -0
- package/dist/auth/utils/auth.d.ts +32 -0
- package/dist/auth/utils/auth.d.ts.map +1 -0
- package/dist/auth/utils/auth.js +116 -0
- package/dist/auth/utils/permission.d.ts +29 -0
- package/dist/auth/utils/permission.d.ts.map +1 -0
- package/dist/auth/utils/permission.js +44 -0
- package/dist/components/head-manifest/index.d.ts +6 -0
- package/dist/components/head-manifest/index.d.ts.map +1 -0
- package/dist/components/head-manifest/index.js +4 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +7 -0
- package/dist/components/json-ld/index.d.ts +7 -0
- package/dist/components/json-ld/index.d.ts.map +1 -0
- package/dist/components/json-ld/index.js +6 -0
- package/dist/components/locale-switcher/_components/china-flag.d.ts +2 -0
- package/dist/components/locale-switcher/_components/china-flag.d.ts.map +1 -0
- package/dist/components/locale-switcher/_components/china-flag.js +4 -0
- package/dist/components/locale-switcher/_components/japan-flag.d.ts +2 -0
- package/dist/components/locale-switcher/_components/japan-flag.d.ts.map +1 -0
- package/dist/components/locale-switcher/_components/japan-flag.js +4 -0
- package/dist/components/locale-switcher/_components/korea-flag.d.ts +4 -0
- package/dist/components/locale-switcher/_components/korea-flag.d.ts.map +1 -0
- package/dist/components/locale-switcher/_components/korea-flag.js +4 -0
- package/dist/components/locale-switcher/_components/taiwan-flag.d.ts +2 -0
- package/dist/components/locale-switcher/_components/taiwan-flag.d.ts.map +1 -0
- package/dist/components/locale-switcher/_components/taiwan-flag.js +4 -0
- package/dist/components/locale-switcher/_components/usa-flag.d.ts +4 -0
- package/dist/components/locale-switcher/_components/usa-flag.d.ts.map +1 -0
- package/dist/components/locale-switcher/_components/usa-flag.js +4 -0
- package/dist/components/locale-switcher/index.d.ts +11 -0
- package/dist/components/locale-switcher/index.d.ts.map +1 -0
- package/dist/components/locale-switcher/index.js +69 -0
- package/dist/components/theme-switcher/index.d.ts +3 -0
- package/dist/components/theme-switcher/index.d.ts.map +1 -0
- package/dist/components/theme-switcher/index.js +20 -0
- package/dist/components/tooltip/index.d.ts +8 -0
- package/dist/components/tooltip/index.d.ts.map +1 -0
- package/dist/components/tooltip/index.js +40 -0
- package/dist/i18n/init-lingui.d.ts +7 -0
- package/dist/i18n/init-lingui.d.ts.map +1 -0
- package/dist/i18n/init-lingui.js +7 -0
- package/dist/i18n/lingui.setup.d.ts +15 -0
- package/dist/i18n/lingui.setup.d.ts.map +1 -0
- package/dist/i18n/lingui.setup.js +29 -0
- package/dist/i18n/providers/lingui-client-provider.d.ts +9 -0
- package/dist/i18n/providers/lingui-client-provider.d.ts.map +1 -0
- package/dist/i18n/providers/lingui-client-provider.js +14 -0
- package/dist/i18n/routing.d.ts +25 -0
- package/dist/i18n/routing.d.ts.map +1 -0
- package/dist/i18n/routing.js +252 -0
- package/dist/local-storage/index.d.ts +4 -0
- package/dist/local-storage/index.d.ts.map +1 -0
- package/dist/local-storage/index.js +4 -0
- package/dist/local-storage/local-storage-manager.d.ts +41 -0
- package/dist/local-storage/local-storage-manager.d.ts.map +1 -0
- package/dist/local-storage/local-storage-manager.js +200 -0
- package/dist/local-storage/valtio-persist.d.ts +31 -0
- package/dist/local-storage/valtio-persist.d.ts.map +1 -0
- package/dist/local-storage/valtio-persist.js +84 -0
- package/dist/navigation/index.d.ts +4 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +4 -0
- package/dist/navigation/permissions.d.ts +25 -0
- package/dist/navigation/permissions.d.ts.map +1 -0
- package/dist/navigation/permissions.js +97 -0
- package/dist/navigation/types.d.ts +57 -0
- package/dist/navigation/types.d.ts.map +1 -0
- package/dist/navigation/types.js +1 -0
- package/dist/navigation/utils.d.ts +42 -0
- package/dist/navigation/utils.d.ts.map +1 -0
- package/dist/navigation/utils.js +107 -0
- package/dist/utils/cookie.d.ts +3 -0
- package/dist/utils/cookie.d.ts.map +1 -0
- package/dist/utils/cookie.js +22 -0
- package/dist/utils/helpers.d.ts +5 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +18 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/sitemap.d.ts +13 -0
- package/dist/utils/sitemap.d.ts.map +1 -0
- package/dist/utils/sitemap.js +19 -0
- package/package.json +126 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { NavigationConfig, NavigationMenuItem, NavigationUserContext, PermissionCheckFn } from '../navigation/types';
|
|
2
|
+
/**
|
|
3
|
+
* Default permission check function
|
|
4
|
+
* Checks if user has any of the required permissions or roles
|
|
5
|
+
*/
|
|
6
|
+
export declare const defaultPermissionCheck: PermissionCheckFn;
|
|
7
|
+
/**
|
|
8
|
+
* Check if user has required permissions for a navigation item
|
|
9
|
+
*/
|
|
10
|
+
export declare function hasPermission(user: NavigationUserContext, item: NavigationMenuItem, config?: NavigationConfig): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Filter navigation items based on user permissions
|
|
13
|
+
* Recursively filters nested items
|
|
14
|
+
*/
|
|
15
|
+
export declare function filterNavigationByPermissions(items: NavigationMenuItem[], user: NavigationUserContext, config?: NavigationConfig, parentPermissions?: string[]): NavigationMenuItem[];
|
|
16
|
+
/**
|
|
17
|
+
* Get a flat list of all accessible paths for a user
|
|
18
|
+
* Useful for route guarding
|
|
19
|
+
*/
|
|
20
|
+
export declare function getAccessiblePaths(items: NavigationMenuItem[], user: NavigationUserContext, config?: NavigationConfig): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Check if a specific path is accessible to user
|
|
23
|
+
*/
|
|
24
|
+
export declare function isPathAccessible(path: string, items: NavigationMenuItem[], user: NavigationUserContext, config?: NavigationConfig): boolean;
|
|
25
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/navigation/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,iBA2BpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,qBAAqB,EAC3B,IAAI,EAAE,kBAAkB,EACxB,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAIT;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,kBAAkB,EAAE,EAC3B,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,gBAAgB,EACzB,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAC3B,kBAAkB,EAAE,CAuCtB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,kBAAkB,EAAE,EAC3B,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,gBAAgB,GACxB,MAAM,EAAE,CAkBV;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,kBAAkB,EAAE,EAC3B,IAAI,EAAE,qBAAqB,EAC3B,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAIT"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default permission check function
|
|
3
|
+
* Checks if user has any of the required permissions or roles
|
|
4
|
+
*/
|
|
5
|
+
export const defaultPermissionCheck = (user, requiredPermissions) => {
|
|
6
|
+
// No permissions required - always allow
|
|
7
|
+
if (!requiredPermissions || requiredPermissions.length === 0) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
// Not authenticated - deny access
|
|
11
|
+
if (!user.isAuthenticated) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
// Check if user has any required permission
|
|
15
|
+
if (user.permissions) {
|
|
16
|
+
const hasPermission = requiredPermissions.some((permission) => user.permissions.includes(permission));
|
|
17
|
+
if (hasPermission)
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
// Check if user has any required role (roles can act as permissions)
|
|
21
|
+
if (user.roles) {
|
|
22
|
+
const hasRole = requiredPermissions.some((permission) => user.roles.includes(permission));
|
|
23
|
+
if (hasRole)
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Check if user has required permissions for a navigation item
|
|
30
|
+
*/
|
|
31
|
+
export function hasPermission(user, item, config) {
|
|
32
|
+
const checkFn = config?.permissionCheckFn || defaultPermissionCheck;
|
|
33
|
+
return checkFn(user, item.permissions);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Filter navigation items based on user permissions
|
|
37
|
+
* Recursively filters nested items
|
|
38
|
+
*/
|
|
39
|
+
export function filterNavigationByPermissions(items, user, config, parentPermissions) {
|
|
40
|
+
const filtered = [];
|
|
41
|
+
for (const item of items) {
|
|
42
|
+
// Determine effective permissions
|
|
43
|
+
let effectivePermissions = item.permissions;
|
|
44
|
+
// Cascade parent permissions if enabled and item has no explicit permissions
|
|
45
|
+
if (config?.cascadePermissions && parentPermissions && (!item.permissions || item.permissions.length === 0)) {
|
|
46
|
+
effectivePermissions = parentPermissions;
|
|
47
|
+
}
|
|
48
|
+
// Check permissions
|
|
49
|
+
const itemWithEffectivePermissions = { ...item, permissions: effectivePermissions };
|
|
50
|
+
if (!hasPermission(user, itemWithEffectivePermissions, config)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// Process children if exists
|
|
54
|
+
let filteredChildren = null;
|
|
55
|
+
if (item.children && item.children.length > 0) {
|
|
56
|
+
const childResults = filterNavigationByPermissions(item.children, user, config, effectivePermissions);
|
|
57
|
+
// Skip parent if all children are hidden and hideEmptyParents is true
|
|
58
|
+
if (config?.hideEmptyParents && childResults.length === 0) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
filteredChildren = childResults.length > 0 ? childResults : null;
|
|
62
|
+
}
|
|
63
|
+
// Add item with filtered children
|
|
64
|
+
filtered.push({
|
|
65
|
+
...item,
|
|
66
|
+
children: filteredChildren,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return filtered;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get a flat list of all accessible paths for a user
|
|
73
|
+
* Useful for route guarding
|
|
74
|
+
*/
|
|
75
|
+
export function getAccessiblePaths(items, user, config) {
|
|
76
|
+
const paths = [];
|
|
77
|
+
const filtered = filterNavigationByPermissions(items, user, config);
|
|
78
|
+
function collectPaths(navItems) {
|
|
79
|
+
for (const item of navItems) {
|
|
80
|
+
if (item.path) {
|
|
81
|
+
paths.push(item.path);
|
|
82
|
+
}
|
|
83
|
+
if (item.children) {
|
|
84
|
+
collectPaths(item.children);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
collectPaths(filtered);
|
|
89
|
+
return paths;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Check if a specific path is accessible to user
|
|
93
|
+
*/
|
|
94
|
+
export function isPathAccessible(path, items, user, config) {
|
|
95
|
+
const accessiblePaths = getAccessiblePaths(items, user, config);
|
|
96
|
+
return accessiblePaths.includes(path);
|
|
97
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navigation menu item interface
|
|
3
|
+
* Represents a single navigation item with optional children and permission requirements
|
|
4
|
+
*/
|
|
5
|
+
export interface NavigationMenuItem {
|
|
6
|
+
/** Display name for the navigation item */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Path to navigate to, null for parent items with children */
|
|
9
|
+
path: string | null;
|
|
10
|
+
/** Required permissions to view this item */
|
|
11
|
+
permissions: string[];
|
|
12
|
+
/** Icon identifier (string) instead of React component for SSR compatibility */
|
|
13
|
+
icon?: string | null;
|
|
14
|
+
/** Child navigation items */
|
|
15
|
+
children?: NavigationMenuItem[] | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* User context for permission checking
|
|
19
|
+
*/
|
|
20
|
+
export interface NavigationUserContext {
|
|
21
|
+
/** User's roles */
|
|
22
|
+
roles?: string[];
|
|
23
|
+
/** User's individual permissions */
|
|
24
|
+
permissions?: string[];
|
|
25
|
+
/** Whether user is authenticated */
|
|
26
|
+
isAuthenticated: boolean;
|
|
27
|
+
/** Additional user data for custom permission checks */
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Permission check function type
|
|
32
|
+
* Can be used for dynamic permission evaluation
|
|
33
|
+
*/
|
|
34
|
+
export type PermissionCheckFn = (user: NavigationUserContext, requiredPermissions: string[]) => boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Filtered navigation result after permission check
|
|
37
|
+
*/
|
|
38
|
+
export interface FilteredNavigation {
|
|
39
|
+
/** Filtered menu items based on permissions */
|
|
40
|
+
items: NavigationMenuItem[];
|
|
41
|
+
/** Total items before filtering */
|
|
42
|
+
totalItems: number;
|
|
43
|
+
/** Items removed due to permissions */
|
|
44
|
+
hiddenItems: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Navigation configuration options
|
|
48
|
+
*/
|
|
49
|
+
export interface NavigationConfig {
|
|
50
|
+
/** Whether to cascade parent permissions to children */
|
|
51
|
+
cascadePermissions?: boolean;
|
|
52
|
+
/** Whether to hide parent items if all children are hidden */
|
|
53
|
+
hideEmptyParents?: boolean;
|
|
54
|
+
/** Custom permission check function */
|
|
55
|
+
permissionCheckFn?: PermissionCheckFn;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/navigation/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IAEb,+DAA+D;IAC/D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAErB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB,oCAAoC;IACpC,eAAe,EAAE,OAAO,CAAC;IAEzB,wDAAwD;IACxD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;AAExG;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAE5B,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IAEnB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { FilteredNavigation, NavigationConfig, NavigationMenuItem, NavigationUserContext } from '../navigation/types';
|
|
2
|
+
/**
|
|
3
|
+
* Get user context from auth for navigation permission checks
|
|
4
|
+
* Works in server components
|
|
5
|
+
*/
|
|
6
|
+
export declare function getNavigationUserContext(): Promise<NavigationUserContext>;
|
|
7
|
+
/**
|
|
8
|
+
* Filter navigation items based on current user's permissions
|
|
9
|
+
* This is the main function to use in components
|
|
10
|
+
*/
|
|
11
|
+
export declare function getFilteredNavigation(items: NavigationMenuItem[], config?: NavigationConfig): Promise<FilteredNavigation>;
|
|
12
|
+
/**
|
|
13
|
+
* Create navigation items builder
|
|
14
|
+
* Provides a fluent API for building navigation structures
|
|
15
|
+
*/
|
|
16
|
+
export declare class NavigationBuilder {
|
|
17
|
+
private items;
|
|
18
|
+
/**
|
|
19
|
+
* Add a navigation item
|
|
20
|
+
*/
|
|
21
|
+
add(item: NavigationMenuItem): this;
|
|
22
|
+
/**
|
|
23
|
+
* Add a parent item with children
|
|
24
|
+
*/
|
|
25
|
+
addParent(name: string, options?: {
|
|
26
|
+
permissions?: string[];
|
|
27
|
+
icon?: string;
|
|
28
|
+
children?: NavigationMenuItem[];
|
|
29
|
+
}): this;
|
|
30
|
+
/**
|
|
31
|
+
* Add a link item
|
|
32
|
+
*/
|
|
33
|
+
addLink(name: string, path: string, options?: {
|
|
34
|
+
permissions?: string[];
|
|
35
|
+
icon?: string;
|
|
36
|
+
}): this;
|
|
37
|
+
/**
|
|
38
|
+
* Build and return the navigation items
|
|
39
|
+
*/
|
|
40
|
+
build(): NavigationMenuItem[];
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/navigation/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAEhC;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CA2B/E;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,kBAAkB,EAAE,EAC3B,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAW7B;AAkBD;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAA4B;IAEzC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAMnC;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAC;KAC5B,GACL,IAAI;IAYP;;OAEG;IACH,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;QACP,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,EAAE,MAAM,CAAC;KACV,GACL,IAAI;IAYP;;OAEG;IACH,KAAK,IAAI,kBAAkB,EAAE;CAG9B"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { getAuthData, isAuthenticated } from '../auth/index.server';
|
|
2
|
+
import { filterNavigationByPermissions } from '../navigation/permissions';
|
|
3
|
+
/**
|
|
4
|
+
* Get user context from auth for navigation permission checks
|
|
5
|
+
* Works in server components
|
|
6
|
+
*/
|
|
7
|
+
export async function getNavigationUserContext() {
|
|
8
|
+
try {
|
|
9
|
+
const authData = await getAuthData();
|
|
10
|
+
const authenticated = await isAuthenticated();
|
|
11
|
+
if (!authData || !authenticated) {
|
|
12
|
+
return {
|
|
13
|
+
isAuthenticated: false,
|
|
14
|
+
roles: [],
|
|
15
|
+
permissions: [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
isAuthenticated: true,
|
|
20
|
+
roles: authData.roles || [],
|
|
21
|
+
permissions: authData.permissions || [],
|
|
22
|
+
...authData.user,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
// Return unauthenticated context on error
|
|
27
|
+
return {
|
|
28
|
+
isAuthenticated: false,
|
|
29
|
+
roles: [],
|
|
30
|
+
permissions: [],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Filter navigation items based on current user's permissions
|
|
36
|
+
* This is the main function to use in components
|
|
37
|
+
*/
|
|
38
|
+
export async function getFilteredNavigation(items, config) {
|
|
39
|
+
const user = await getNavigationUserContext();
|
|
40
|
+
const totalItems = countNavigationItems(items);
|
|
41
|
+
const filtered = filterNavigationByPermissions(items, user, config);
|
|
42
|
+
const filteredCount = countNavigationItems(filtered);
|
|
43
|
+
return {
|
|
44
|
+
items: filtered,
|
|
45
|
+
totalItems,
|
|
46
|
+
hiddenItems: totalItems - filteredCount,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Count total navigation items including nested children
|
|
51
|
+
*/
|
|
52
|
+
function countNavigationItems(items) {
|
|
53
|
+
let count = 0;
|
|
54
|
+
for (const item of items) {
|
|
55
|
+
count++;
|
|
56
|
+
if (item.children) {
|
|
57
|
+
count += countNavigationItems(item.children);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return count;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Create navigation items builder
|
|
64
|
+
* Provides a fluent API for building navigation structures
|
|
65
|
+
*/
|
|
66
|
+
export class NavigationBuilder {
|
|
67
|
+
items = [];
|
|
68
|
+
/**
|
|
69
|
+
* Add a navigation item
|
|
70
|
+
*/
|
|
71
|
+
add(item) {
|
|
72
|
+
this.items.push(item);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add a parent item with children
|
|
77
|
+
*/
|
|
78
|
+
addParent(name, options = {}) {
|
|
79
|
+
this.items.push({
|
|
80
|
+
name,
|
|
81
|
+
path: null,
|
|
82
|
+
permissions: options.permissions || [],
|
|
83
|
+
icon: options.icon || null,
|
|
84
|
+
children: options.children || null,
|
|
85
|
+
});
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Add a link item
|
|
90
|
+
*/
|
|
91
|
+
addLink(name, path, options = {}) {
|
|
92
|
+
this.items.push({
|
|
93
|
+
name,
|
|
94
|
+
path,
|
|
95
|
+
permissions: options.permissions || [],
|
|
96
|
+
icon: options.icon || null,
|
|
97
|
+
children: null,
|
|
98
|
+
});
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Build and return the navigation items
|
|
103
|
+
*/
|
|
104
|
+
build() {
|
|
105
|
+
return this.items;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie.d.ts","sourceRoot":"","sources":["../../src/utils/cookie.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,GAAI,cAAc,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAahG,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,OAAO,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,SAM9E,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const parseCookieHeader = (cookieHeader) => {
|
|
2
|
+
const result = {};
|
|
3
|
+
if (!cookieHeader)
|
|
4
|
+
return result;
|
|
5
|
+
for (const part of cookieHeader.split(';')) {
|
|
6
|
+
const [rawKey, ...rest] = part.trim().split('=');
|
|
7
|
+
if (!rawKey)
|
|
8
|
+
continue;
|
|
9
|
+
const key = decodeURIComponent(rawKey.trim());
|
|
10
|
+
const value = decodeURIComponent(rest.join('=') || '');
|
|
11
|
+
if (key)
|
|
12
|
+
result[key] = value;
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
export const getCookieFromHeaders = (headers, name) => {
|
|
17
|
+
const cookieHeader = headers.get('cookie');
|
|
18
|
+
if (!cookieHeader)
|
|
19
|
+
return undefined;
|
|
20
|
+
const map = parseCookieHeader(cookieHeader);
|
|
21
|
+
return map[name];
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,eAAO,MAAM,EAAE,GAAI,GAAG,QAAQ,UAAU,EAAE,WAA0B,CAAC;AAErE,eAAO,MAAM,SAAS,QAAO,OAE5B,CAAC;AAEF,eAAO,MAAM,UAAU,cActB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
export const cn = (...inputs) => twMerge(clsx(inputs));
|
|
4
|
+
export const isBrowser = () => {
|
|
5
|
+
return typeof window !== 'undefined';
|
|
6
|
+
};
|
|
7
|
+
export const getBaseUrl = () => {
|
|
8
|
+
if (process.env.NEXT_PUBLIC_APP_URL) {
|
|
9
|
+
return process.env.NEXT_PUBLIC_APP_URL;
|
|
10
|
+
}
|
|
11
|
+
if (process.env.VERCEL_ENV === 'production' && process.env.VERCEL_PROJECT_PRODUCTION_URL) {
|
|
12
|
+
return `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`;
|
|
13
|
+
}
|
|
14
|
+
if (process.env.VERCEL_URL) {
|
|
15
|
+
return `https://${process.env.VERCEL_URL}`;
|
|
16
|
+
}
|
|
17
|
+
return 'http://localhost:3000';
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getPathname } from '../i18n/routing';
|
|
2
|
+
type Href = Parameters<typeof getPathname>[0]['href'];
|
|
3
|
+
export declare function getEntry(href: Href, options?: Record<string, string>): {
|
|
4
|
+
url: string;
|
|
5
|
+
alternates: {
|
|
6
|
+
languages: {
|
|
7
|
+
[k: string]: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export declare function getUrl(href: Href, locale: string): string;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=sitemap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../src/utils/sitemap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQjD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM;;;;;;;EAUxE;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,UAKhD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getPathname } from '../i18n/routing';
|
|
2
|
+
import { getBaseUrl } from '../utils/helpers';
|
|
3
|
+
import linguiConfig from 'lingui.config';
|
|
4
|
+
const { locales, fallbackLocales } = linguiConfig;
|
|
5
|
+
const defaultLocale = fallbackLocales.default;
|
|
6
|
+
export function getEntry(href, options = {}) {
|
|
7
|
+
return {
|
|
8
|
+
url: getUrl(href, defaultLocale),
|
|
9
|
+
alternates: {
|
|
10
|
+
languages: Object.fromEntries(locales.filter((locale) => locale !== 'pseudo').map((cur) => [cur, getUrl(href, cur)])),
|
|
11
|
+
},
|
|
12
|
+
...options,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function getUrl(href, locale) {
|
|
16
|
+
const pathname = getPathname({ locale, href });
|
|
17
|
+
const host = getBaseUrl();
|
|
18
|
+
return host + pathname;
|
|
19
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@korioinc/next-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
"./ads": {
|
|
7
|
+
"types": "./dist/ads/index.d.ts",
|
|
8
|
+
"import": "./dist/ads/index.js",
|
|
9
|
+
"default": "./dist/ads/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./auth": {
|
|
12
|
+
"types": "./dist/auth/index.d.ts",
|
|
13
|
+
"import": "./dist/auth/index.js",
|
|
14
|
+
"default": "./dist/auth/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./auth/server": {
|
|
17
|
+
"types": "./dist/auth/index.server.d.ts",
|
|
18
|
+
"import": "./dist/auth/index.server.js",
|
|
19
|
+
"default": "./dist/auth/index.server.js"
|
|
20
|
+
},
|
|
21
|
+
"./auth/client": {
|
|
22
|
+
"types": "./dist/auth/index.client.d.ts",
|
|
23
|
+
"import": "./dist/auth/index.client.js",
|
|
24
|
+
"default": "./dist/auth/index.client.js"
|
|
25
|
+
},
|
|
26
|
+
"./navigation": {
|
|
27
|
+
"types": "./dist/navigation/index.d.ts",
|
|
28
|
+
"import": "./dist/navigation/index.js",
|
|
29
|
+
"default": "./dist/navigation/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./api-client": {
|
|
32
|
+
"types": "./dist/api-client/index.d.ts",
|
|
33
|
+
"import": "./dist/api-client/index.js",
|
|
34
|
+
"default": "./dist/api-client/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./i18n/*": {
|
|
37
|
+
"types": "./dist/i18n/*.d.ts",
|
|
38
|
+
"import": "./dist/i18n/*.js",
|
|
39
|
+
"default": "./dist/i18n/*.js"
|
|
40
|
+
},
|
|
41
|
+
"./utils": {
|
|
42
|
+
"types": "./dist/utils/index.d.ts",
|
|
43
|
+
"import": "./dist/utils/index.js",
|
|
44
|
+
"default": "./dist/utils/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./local-storage": {
|
|
47
|
+
"types": "./dist/local-storage/index.d.ts",
|
|
48
|
+
"import": "./dist/local-storage/index.js",
|
|
49
|
+
"default": "./dist/local-storage/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./components": {
|
|
52
|
+
"types": "./dist/components/index.d.ts",
|
|
53
|
+
"import": "./dist/components/index.js",
|
|
54
|
+
"default": "./dist/components/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./styles/*": "./src/styles/*"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"dist",
|
|
60
|
+
"README.md",
|
|
61
|
+
"LICENSE"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
65
|
+
"prepare": "pnpm run build",
|
|
66
|
+
"dev": "tsc -p tsconfig.json -w & tsc-alias -p tsconfig.json -w",
|
|
67
|
+
"lint": "eslint . --max-warnings 0",
|
|
68
|
+
"generate:component": "turbo gen react-component"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@korioinc/next-configs": "workspace:*",
|
|
72
|
+
"@headlessui/react": "^2.2.7",
|
|
73
|
+
"@lingui/conf": "^5.5.0",
|
|
74
|
+
"@lingui/core": "^5.5.0",
|
|
75
|
+
"@lingui/react": "^5.5.0",
|
|
76
|
+
"@tailwindcss/typography": "^0.5.16",
|
|
77
|
+
"@types/negotiator": "^0.6.4",
|
|
78
|
+
"@types/node": "^22.18.1",
|
|
79
|
+
"@types/react": "^19.1.12",
|
|
80
|
+
"@types/react-dom": "^19.1.9",
|
|
81
|
+
"eslint": "^9.35.0",
|
|
82
|
+
"next-themes": "^0.4.6",
|
|
83
|
+
"tailwindcss": "^4.1.13",
|
|
84
|
+
"tsc-alias": "^1.8.16",
|
|
85
|
+
"tw-animate-css": "^1.3.8",
|
|
86
|
+
"typescript": "^5.9.2",
|
|
87
|
+
"react": "^19.1.0",
|
|
88
|
+
"react-dom": "^19.1.0"
|
|
89
|
+
},
|
|
90
|
+
"dependencies": {
|
|
91
|
+
"@korioinc/next-conf": "workspace:*",
|
|
92
|
+
"schema-dts": "^1.1.5",
|
|
93
|
+
"@floating-ui/react": "^0.27.16",
|
|
94
|
+
"@formatjs/intl-localematcher": "^0.6.1",
|
|
95
|
+
"clsx": "^2.1.1",
|
|
96
|
+
"cookies-next": "^6.1.0",
|
|
97
|
+
"cosmiconfig": "^9.0.0",
|
|
98
|
+
"jiti": "^1.21.7",
|
|
99
|
+
"jose": "^6.1.0",
|
|
100
|
+
"localforage": "^1.10.0",
|
|
101
|
+
"negotiator": "^1.0.0",
|
|
102
|
+
"pretendard": "^1.3.9",
|
|
103
|
+
"tailwind-merge": "^3.3.1",
|
|
104
|
+
"valtio": "^2.0.0"
|
|
105
|
+
},
|
|
106
|
+
"publishConfig": {
|
|
107
|
+
"access": "public",
|
|
108
|
+
"registry": "https://registry.npmjs.org/"
|
|
109
|
+
},
|
|
110
|
+
"repository": {
|
|
111
|
+
"type": "git",
|
|
112
|
+
"url": "git+https://github.com/korioinc/korio-nextjs-kit.git",
|
|
113
|
+
"directory": "packages/core"
|
|
114
|
+
},
|
|
115
|
+
"author": "Korio Inc.",
|
|
116
|
+
"peerDependencies": {
|
|
117
|
+
"@lingui/core": ">=5.0.0",
|
|
118
|
+
"@lingui/react": ">=5.0.0",
|
|
119
|
+
"@headlessui/react": ">=2.2.0",
|
|
120
|
+
"next": ">=15",
|
|
121
|
+
"next-themes": ">=0.4.5",
|
|
122
|
+
"tailwindcss": ">=4.0.0",
|
|
123
|
+
"react": ">=19",
|
|
124
|
+
"react-dom": ">=19"
|
|
125
|
+
}
|
|
126
|
+
}
|