olova 2.0.61 → 2.0.63
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/CHANGELOG.md +5 -0
- package/README.md +42 -61
- package/dist/compiler.d.ts +44 -0
- package/dist/compiler.js +2139 -0
- package/dist/compiler.js.map +1 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.js +859 -0
- package/dist/core.js.map +1 -0
- package/dist/global.d.ts +15 -0
- package/dist/global.js +226 -0
- package/dist/global.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2302 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +89 -0
- package/dist/runtime.js +633 -0
- package/dist/runtime.js.map +1 -0
- package/dist/signals-core-BdfWh1Yt.d.ts +43 -0
- package/dist/vite.d.ts +5 -0
- package/dist/vite.js +2302 -0
- package/dist/vite.js.map +1 -0
- package/package.json +83 -65
- package/dist/chunk-D7SIC5TC.js +0 -367
- package/dist/chunk-D7SIC5TC.js.map +0 -1
- package/dist/entry-server.cjs +0 -120
- package/dist/entry-server.cjs.map +0 -1
- package/dist/entry-server.js +0 -115
- package/dist/entry-server.js.map +0 -1
- package/dist/entry-worker.cjs +0 -133
- package/dist/entry-worker.cjs.map +0 -1
- package/dist/entry-worker.js +0 -127
- package/dist/entry-worker.js.map +0 -1
- package/dist/main.cjs +0 -18
- package/dist/main.cjs.map +0 -1
- package/dist/main.js +0 -16
- package/dist/main.js.map +0 -1
- package/dist/olova.cjs +0 -1680
- package/dist/olova.cjs.map +0 -1
- package/dist/olova.d.cts +0 -72
- package/dist/olova.d.ts +0 -72
- package/dist/olova.js +0 -1321
- package/dist/olova.js.map +0 -1
- package/dist/performance.cjs +0 -386
- package/dist/performance.cjs.map +0 -1
- package/dist/performance.js +0 -3
- package/dist/performance.js.map +0 -1
- package/dist/router.cjs +0 -646
- package/dist/router.cjs.map +0 -1
- package/dist/router.d.cts +0 -113
- package/dist/router.d.ts +0 -113
- package/dist/router.js +0 -632
- package/dist/router.js.map +0 -1
- package/main.tsx +0 -76
- package/olova.ts +0 -619
- package/src/entry-server.tsx +0 -165
- package/src/entry-worker.tsx +0 -201
- package/src/generator/index.ts +0 -409
- package/src/hydration/flight.ts +0 -320
- package/src/hydration/index.ts +0 -12
- package/src/hydration/types.ts +0 -225
- package/src/logger.ts +0 -182
- package/src/main.tsx +0 -24
- package/src/performance.ts +0 -488
- package/src/plugin/index.ts +0 -204
- package/src/router/ErrorBoundary.tsx +0 -145
- package/src/router/Link.tsx +0 -117
- package/src/router/OlovaRouter.tsx +0 -354
- package/src/router/Outlet.tsx +0 -8
- package/src/router/context.ts +0 -117
- package/src/router/index.ts +0 -29
- package/src/router/matching.ts +0 -63
- package/src/router/router.tsx +0 -23
- package/src/router/search-params.ts +0 -29
- package/src/scanner/index.ts +0 -114
- package/src/types/index.ts +0 -190
- package/src/utils/export.ts +0 -85
- package/src/utils/index.ts +0 -4
- package/src/utils/naming.ts +0 -54
- package/src/utils/path.ts +0 -45
- package/tsup.config.ts +0 -35
package/src/scanner/index.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import type { ErrorEntry, LayoutEntry, LoadingEntry, MiddlewareEntry, NotFoundEntry, RouteEntry, ScanResult } from '../types';
|
|
4
|
-
import { isRouteGroup, pathToRoute } from '../utils';
|
|
5
|
-
|
|
6
|
-
const RESERVED_NAMES = new Set([
|
|
7
|
-
'page', 'layout', 'loading', 'error', 'not-found', 'middleware',
|
|
8
|
-
'route.tree',
|
|
9
|
-
]);
|
|
10
|
-
|
|
11
|
-
function scanDirectory(
|
|
12
|
-
dir: string,
|
|
13
|
-
rootDir: string,
|
|
14
|
-
extensions: string[],
|
|
15
|
-
routes: RouteEntry[],
|
|
16
|
-
notFoundPages: NotFoundEntry[],
|
|
17
|
-
layouts: LayoutEntry[],
|
|
18
|
-
loadingPages: LoadingEntry[],
|
|
19
|
-
errorPages: ErrorEntry[],
|
|
20
|
-
middlewares: MiddlewareEntry[],
|
|
21
|
-
isRoot = false
|
|
22
|
-
) {
|
|
23
|
-
if (!fs.existsSync(dir)) return;
|
|
24
|
-
|
|
25
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
26
|
-
|
|
27
|
-
for (const entry of entries) {
|
|
28
|
-
const fullPath = path.join(dir, entry.name);
|
|
29
|
-
|
|
30
|
-
if (entry.isDirectory()) {
|
|
31
|
-
if (entry.name === 'node_modules' || entry.name === 'assets' || entry.name.startsWith('_')) continue;
|
|
32
|
-
scanDirectory(fullPath, rootDir, extensions, routes, notFoundPages, layouts, loadingPages, errorPages, middlewares, false);
|
|
33
|
-
} else if (entry.isFile()) {
|
|
34
|
-
const ext = path.extname(entry.name);
|
|
35
|
-
const baseName = path.basename(entry.name, ext);
|
|
36
|
-
|
|
37
|
-
if (baseName === 'layout' && extensions.includes(ext)) {
|
|
38
|
-
const relativePath = path.relative(rootDir, dir);
|
|
39
|
-
const { routePath } = pathToRoute(relativePath, path.sep);
|
|
40
|
-
layouts.push({
|
|
41
|
-
path: isRoot ? '/' : routePath,
|
|
42
|
-
filePath: fullPath
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
else if (baseName === 'loading' && extensions.includes(ext)) {
|
|
46
|
-
const relativePath = path.relative(rootDir, dir);
|
|
47
|
-
const { routePath } = pathToRoute(relativePath, path.sep);
|
|
48
|
-
loadingPages.push({
|
|
49
|
-
path: isRoot ? '/' : routePath,
|
|
50
|
-
filePath: fullPath
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
else if (baseName === 'error' && extensions.includes(ext)) {
|
|
54
|
-
const relativePath = path.relative(rootDir, dir);
|
|
55
|
-
const { routePath } = pathToRoute(relativePath, path.sep);
|
|
56
|
-
errorPages.push({
|
|
57
|
-
path: isRoot ? '/' : routePath,
|
|
58
|
-
filePath: fullPath
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
else if (baseName === 'middleware' && extensions.includes(ext)) {
|
|
62
|
-
const relativePath = path.relative(rootDir, dir);
|
|
63
|
-
const { routePath } = pathToRoute(relativePath, path.sep);
|
|
64
|
-
middlewares.push({
|
|
65
|
-
path: isRoot ? '/' : routePath,
|
|
66
|
-
filePath: fullPath
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
else if ((baseName === 'not-found' || baseName === '404') && extensions.includes(ext)) {
|
|
70
|
-
const relativeParts = path.relative(rootDir, dir).split(path.sep).filter(Boolean);
|
|
71
|
-
const filteredParts = relativeParts.filter(p => !isRouteGroup(p));
|
|
72
|
-
const pathPrefix = isRoot ? '' : '/' + filteredParts.join('/');
|
|
73
|
-
notFoundPages.push({ pathPrefix: pathPrefix || '', filePath: fullPath });
|
|
74
|
-
} else if (baseName === 'page' && extensions.includes(ext)) {
|
|
75
|
-
const relativePath = path.relative(rootDir, dir);
|
|
76
|
-
const { routePath, params } = pathToRoute(relativePath, path.sep);
|
|
77
|
-
routes.push({ path: routePath, filePath: fullPath, isDynamic: params.length > 0, params });
|
|
78
|
-
} else if (
|
|
79
|
-
!RESERVED_NAMES.has(baseName) &&
|
|
80
|
-
!baseName.endsWith('.d') &&
|
|
81
|
-
!baseName.startsWith('_') &&
|
|
82
|
-
extensions.includes(ext)
|
|
83
|
-
) {
|
|
84
|
-
const relativePath = path.relative(rootDir, fullPath);
|
|
85
|
-
const relativePathNoExt = relativePath.substring(0, relativePath.length - ext.length);
|
|
86
|
-
const { routePath, params } = pathToRoute(relativePathNoExt, path.sep);
|
|
87
|
-
routes.push({ path: routePath, filePath: fullPath, isDynamic: params.length > 0, params });
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function scanRoutes(rootDir: string, extensions: string[]): ScanResult {
|
|
94
|
-
const routes: RouteEntry[] = [];
|
|
95
|
-
const notFoundPages: NotFoundEntry[] = [];
|
|
96
|
-
const layouts: LayoutEntry[] = [];
|
|
97
|
-
const loadingPages: LoadingEntry[] = [];
|
|
98
|
-
const errorPages: ErrorEntry[] = [];
|
|
99
|
-
const middlewares: MiddlewareEntry[] = [];
|
|
100
|
-
const absoluteRoot = path.isAbsolute(rootDir) ? rootDir : path.resolve(rootDir);
|
|
101
|
-
|
|
102
|
-
if (!fs.existsSync(absoluteRoot)) {
|
|
103
|
-
throw new Error(`Olova Router: Root directory does not exist: ${absoluteRoot}`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
scanDirectory(absoluteRoot, absoluteRoot, extensions, routes, notFoundPages, layouts, loadingPages, errorPages, middlewares, true);
|
|
107
|
-
routes.sort((a, b) => (a.isDynamic !== b.isDynamic ? (a.isDynamic ? 1 : -1) : a.path.localeCompare(b.path)));
|
|
108
|
-
notFoundPages.sort((a, b) => b.pathPrefix.length - a.pathPrefix.length);
|
|
109
|
-
layouts.sort((a, b) => a.path.length - b.path.length);
|
|
110
|
-
loadingPages.sort((a, b) => b.path.length - a.path.length);
|
|
111
|
-
errorPages.sort((a, b) => b.path.length - a.path.length);
|
|
112
|
-
middlewares.sort((a, b) => a.path.length - b.path.length);
|
|
113
|
-
return { routes, notFoundPages, layouts, loadingPages, errorPages, middlewares };
|
|
114
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
-
export type { PluginOption, ResolvedConfig } from 'vite';
|
|
3
|
-
|
|
4
|
-
export interface RouteEntry {
|
|
5
|
-
path: string;
|
|
6
|
-
filePath: string;
|
|
7
|
-
isDynamic: boolean;
|
|
8
|
-
params: string[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ScannerOptions {
|
|
12
|
-
rootDir: string;
|
|
13
|
-
extensions: string[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface Metadata {
|
|
17
|
-
title?: string;
|
|
18
|
-
description?: string;
|
|
19
|
-
keywords?: string[];
|
|
20
|
-
openGraph?: {
|
|
21
|
-
title?: string;
|
|
22
|
-
description?: string;
|
|
23
|
-
image?: string;
|
|
24
|
-
url?: string;
|
|
25
|
-
type?: string;
|
|
26
|
-
};
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
-
[key: string]: any;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface RouteConfig {
|
|
32
|
-
path: string;
|
|
33
|
-
component: string;
|
|
34
|
-
params?: string[];
|
|
35
|
-
metadata?: Metadata;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface GeneratorOptions {
|
|
39
|
-
routes: RouteEntry[];
|
|
40
|
-
basePath: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface OlovaRouterOptions {
|
|
44
|
-
extensions?: string[];
|
|
45
|
-
packageName?: string;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface DynamicSegmentResult {
|
|
49
|
-
isDynamic: boolean;
|
|
50
|
-
paramName: string | null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface NotFoundEntry {
|
|
54
|
-
pathPrefix: string;
|
|
55
|
-
filePath: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface NotFoundPageConfig {
|
|
59
|
-
pathPrefix: string;
|
|
60
|
-
component: ComponentType;
|
|
61
|
-
metadata?: Metadata;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface LayoutEntry {
|
|
65
|
-
path: string;
|
|
66
|
-
filePath: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface LoadingEntry {
|
|
70
|
-
path: string;
|
|
71
|
-
filePath: string;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface ErrorEntry {
|
|
75
|
-
path: string;
|
|
76
|
-
filePath: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface MiddlewareEntry {
|
|
80
|
-
path: string;
|
|
81
|
-
filePath: string;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface ScanResult {
|
|
85
|
-
routes: RouteEntry[];
|
|
86
|
-
notFoundPages: NotFoundEntry[];
|
|
87
|
-
layouts: LayoutEntry[];
|
|
88
|
-
loadingPages: LoadingEntry[];
|
|
89
|
-
errorPages: ErrorEntry[];
|
|
90
|
-
middlewares: MiddlewareEntry[];
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface RouteWithExport extends RouteConfig {
|
|
94
|
-
hasDefault: boolean;
|
|
95
|
-
namedExport: string | null;
|
|
96
|
-
hasMetadata: boolean;
|
|
97
|
-
metadataSource?: string;
|
|
98
|
-
hasRoute: boolean;
|
|
99
|
-
hasGetStaticPaths: boolean;
|
|
100
|
-
hasLoader: boolean;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export interface NotFoundWithExport extends NotFoundEntry {
|
|
104
|
-
hasDefault: boolean;
|
|
105
|
-
namedExport: string | null;
|
|
106
|
-
hasMetadata: boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface LayoutWithExport extends LayoutEntry {
|
|
110
|
-
hasDefault: boolean;
|
|
111
|
-
namedExport: string | null;
|
|
112
|
-
hasMetadata: boolean;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export interface LoadingWithExport extends LoadingEntry {
|
|
116
|
-
hasDefault: boolean;
|
|
117
|
-
namedExport: string | null;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface ErrorWithExport extends ErrorEntry {
|
|
121
|
-
hasDefault: boolean;
|
|
122
|
-
namedExport: string | null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface MiddlewareWithExport extends MiddlewareEntry {
|
|
126
|
-
hasDefault: boolean;
|
|
127
|
-
namedExport: string | null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface RouteErrorProps {
|
|
131
|
-
error: Error;
|
|
132
|
-
reset: () => void;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export interface LoaderContext {
|
|
136
|
-
request: Request;
|
|
137
|
-
params: Record<string, string>;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export interface Route {
|
|
141
|
-
id?: string;
|
|
142
|
-
path: string;
|
|
143
|
-
component?: ComponentType;
|
|
144
|
-
metadata?: Metadata;
|
|
145
|
-
loading?: ComponentType;
|
|
146
|
-
error?: ComponentType<RouteErrorProps>;
|
|
147
|
-
filePath?: string;
|
|
148
|
-
params?: string[];
|
|
149
|
-
loader?: (ctx: LoaderContext) => Promise<Record<string, unknown>>;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export interface LayoutRoute {
|
|
153
|
-
path: string;
|
|
154
|
-
layout?: ComponentType;
|
|
155
|
-
children: Route[];
|
|
156
|
-
metadata?: Metadata;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export type SearchParams = Record<string, string | string[]>;
|
|
160
|
-
|
|
161
|
-
export interface SetSearchParamsOptions {
|
|
162
|
-
replace?: boolean;
|
|
163
|
-
merge?: boolean;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export interface NavigateOptions {
|
|
167
|
-
scroll?: boolean;
|
|
168
|
-
replace?: boolean;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export type NavigationListener = (from: string, to: string) => void | boolean;
|
|
172
|
-
|
|
173
|
-
export interface RouterContextType {
|
|
174
|
-
currentPath: string;
|
|
175
|
-
params: Record<string, string>;
|
|
176
|
-
searchParams: SearchParams;
|
|
177
|
-
navigate: (path: string, options?: NavigateOptions) => void;
|
|
178
|
-
push: (path: string, options?: NavigateOptions) => void;
|
|
179
|
-
replace: (path: string, options?: NavigateOptions) => void;
|
|
180
|
-
back: () => void;
|
|
181
|
-
forward: () => void;
|
|
182
|
-
refresh: () => void;
|
|
183
|
-
setSearchParams: (params: Record<string, string | string[] | null>, options?: SetSearchParamsOptions) => void;
|
|
184
|
-
isNavigating: boolean;
|
|
185
|
-
prefetch: (path: string) => void;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export interface OutletContextType {
|
|
189
|
-
content: ReactNode;
|
|
190
|
-
}
|
package/src/utils/export.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
|
|
3
|
-
function extractBalancedBraces(content: string, startIndex: number): string | null {
|
|
4
|
-
if (content[startIndex] !== '{') return null;
|
|
5
|
-
let depth = 0;
|
|
6
|
-
for (let i = startIndex; i < content.length; i++) {
|
|
7
|
-
if (content[i] === '{') depth++;
|
|
8
|
-
else if (content[i] === '}') {
|
|
9
|
-
depth--;
|
|
10
|
-
if (depth === 0) return content.substring(startIndex, i + 1);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function extractMetadataSource(content: string): string | undefined {
|
|
17
|
-
const match = content.match(/export\s+(?:const|let|var)\s+metadata\s*(?::\s*\w+\s*)?=\s*/);
|
|
18
|
-
if (!match || match.index === undefined) return undefined;
|
|
19
|
-
const afterEquals = match.index + match[0].length;
|
|
20
|
-
return extractBalancedBraces(content, afterEquals) || undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function detectExportType(filePath: string): {
|
|
24
|
-
hasDefault: boolean;
|
|
25
|
-
namedExport: string | null;
|
|
26
|
-
hasMetadata: boolean;
|
|
27
|
-
metadataSource?: string;
|
|
28
|
-
hasRoute: boolean;
|
|
29
|
-
hasGetStaticPaths: boolean;
|
|
30
|
-
hasLoader: boolean;
|
|
31
|
-
} {
|
|
32
|
-
try {
|
|
33
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
34
|
-
|
|
35
|
-
const hasMetadata = /export\s+(?:const|let|var)\s+metadata\s*/.test(content) ||
|
|
36
|
-
/export\s*\{\s*metadata\s*\}/.test(content);
|
|
37
|
-
|
|
38
|
-
const hasRoute = /export\s+(?:const|let|var)\s+route\s*=/.test(content) ||
|
|
39
|
-
/export\s*\{\s*route\s*\}/.test(content);
|
|
40
|
-
|
|
41
|
-
const hasGetStaticPaths = /export\s+(?:async\s+)?function\s+getStaticPaths/.test(content) ||
|
|
42
|
-
/export\s+(?:const|let|var)\s+getStaticPaths\s*=/.test(content) ||
|
|
43
|
-
/export\s*\{[^}]*getStaticPaths[^}]*\}/.test(content);
|
|
44
|
-
|
|
45
|
-
const hasLoader = /export\s+(?:async\s+)?function\s+loader/.test(content) ||
|
|
46
|
-
/export\s+(?:const|let|var)\s+loader\s*=/.test(content) ||
|
|
47
|
-
/export\s*\{[^}]*loader[^}]*\}/.test(content);
|
|
48
|
-
|
|
49
|
-
// Extract metadata source for inlining (works for any file type with object literal metadata)
|
|
50
|
-
const metadataSource = extractMetadataSource(content);
|
|
51
|
-
|
|
52
|
-
if (filePath.toLowerCase().endsWith('.mdx')) {
|
|
53
|
-
return {
|
|
54
|
-
hasDefault: true,
|
|
55
|
-
namedExport: null,
|
|
56
|
-
hasMetadata: !!metadataSource,
|
|
57
|
-
hasRoute: false,
|
|
58
|
-
hasGetStaticPaths: false,
|
|
59
|
-
hasLoader: false,
|
|
60
|
-
metadataSource
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (/export\s+default\s+/.test(content)) {
|
|
65
|
-
return { hasDefault: true, namedExport: null, hasMetadata, metadataSource, hasRoute, hasGetStaticPaths, hasLoader };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const namedMatch = content.match(/export\s+(?:const|function|class)\s+(\w+)/);
|
|
69
|
-
if (namedMatch) {
|
|
70
|
-
return { hasDefault: false, namedExport: namedMatch[1], hasMetadata, metadataSource, hasRoute, hasGetStaticPaths, hasLoader };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const exportMatch = content.match(/export\s*\{\s*(\w+)(?:\s+as\s+default)?\s*\}/);
|
|
74
|
-
if (exportMatch) {
|
|
75
|
-
if (content.includes('as default')) {
|
|
76
|
-
return { hasDefault: true, namedExport: null, hasMetadata, metadataSource, hasRoute, hasGetStaticPaths, hasLoader };
|
|
77
|
-
}
|
|
78
|
-
return { hasDefault: false, namedExport: exportMatch[1], hasMetadata, metadataSource, hasRoute, hasGetStaticPaths, hasLoader };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return { hasDefault: false, namedExport: null, hasMetadata, metadataSource, hasRoute, hasGetStaticPaths, hasLoader };
|
|
82
|
-
} catch {
|
|
83
|
-
return { hasDefault: true, namedExport: null, hasMetadata: false, hasRoute: false, hasGetStaticPaths: false, hasLoader: false };
|
|
84
|
-
}
|
|
85
|
-
}
|
package/src/utils/index.ts
DELETED
package/src/utils/naming.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export function getRouteName(path: string): string {
|
|
2
|
-
if (path === '/' || path === '') return 'Root';
|
|
3
|
-
|
|
4
|
-
// Remove leading/trailing slashes and split
|
|
5
|
-
const segments = path.replace(/^\/|\/$/g, '').split(/[\\/]/);
|
|
6
|
-
|
|
7
|
-
const nameSegments = segments.map(segment => {
|
|
8
|
-
let cleanSegment = segment;
|
|
9
|
-
|
|
10
|
-
// Handle dynamic segments :id -> Id
|
|
11
|
-
if (cleanSegment.startsWith(':')) {
|
|
12
|
-
cleanSegment = cleanSegment.slice(1);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Handle bracket syntax [id] -> Id, [...slug] -> Slug
|
|
16
|
-
if (cleanSegment.startsWith('[') && cleanSegment.endsWith(']')) {
|
|
17
|
-
cleanSegment = cleanSegment.slice(1, -1);
|
|
18
|
-
if (cleanSegment.startsWith('...')) {
|
|
19
|
-
cleanSegment = cleanSegment.slice(3);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Handle catch-all * -> All
|
|
24
|
-
if (cleanSegment === '*') {
|
|
25
|
-
return 'All';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Skip 'index' segment for cleaner names
|
|
29
|
-
if (cleanSegment.toLowerCase() === 'index') {
|
|
30
|
-
return '';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Handle route groups (auth) -> Auth or ignore? Usually people ignore path but name might want it?
|
|
34
|
-
// User request is about "main folder name". (auth) is usually invisible.
|
|
35
|
-
// Let's strip parens but keep name for uniqueness? Or just strip?
|
|
36
|
-
// scanner often treats (group) as transparent for path, but for Naming it might be good to include or exclude.
|
|
37
|
-
// Let's include it cleaned up to ensure Uniqueness (e.g. /app/(dashboard)/layout vs /app/(marketing)/layout).
|
|
38
|
-
if (cleanSegment.startsWith('(') && cleanSegment.endsWith(')')) {
|
|
39
|
-
cleanSegment = cleanSegment.slice(1, -1);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return capitalize(cleanSegment);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const finalName = nameSegments.join('');
|
|
46
|
-
if (/^\d/.test(finalName)) {
|
|
47
|
-
return 'Page' + finalName;
|
|
48
|
-
}
|
|
49
|
-
return finalName;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function capitalize(str: string): string {
|
|
53
|
-
return str.charAt(0).toUpperCase() + str.slice(1).replace(/[^a-zA-Z0-9]/g, '');
|
|
54
|
-
}
|
package/src/utils/path.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { DynamicSegmentResult } from '../types';
|
|
2
|
-
|
|
3
|
-
export function parseDynamicSegment(segment: string): DynamicSegmentResult & { isCatchAll: boolean } {
|
|
4
|
-
if (segment.match(/^\[\.\.\.(.+)\]$/)) {
|
|
5
|
-
const paramName = segment.match(/^\[\.\.\.(.+)\]$/)?.[1] || 'slug';
|
|
6
|
-
return { isDynamic: true, paramName, isCatchAll: true };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const bracketMatch = segment.match(/^\[(.+)\]$/);
|
|
10
|
-
if (bracketMatch) {
|
|
11
|
-
return { isDynamic: true, paramName: bracketMatch[1], isCatchAll: false };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return { isDynamic: false, paramName: null, isCatchAll: false };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isRouteGroup(segment: string): boolean {
|
|
20
|
-
return /^\(.+\)$/.test(segment);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function pathToRoute(relativePath: string, sep: string) {
|
|
24
|
-
const params: string[] = [];
|
|
25
|
-
let hasCatchAll = false;
|
|
26
|
-
const segments = relativePath.split(sep).filter(Boolean);
|
|
27
|
-
|
|
28
|
-
const routeSegments = segments
|
|
29
|
-
.filter(segment => !isRouteGroup(segment))
|
|
30
|
-
.map(segment => {
|
|
31
|
-
const { isDynamic, paramName, isCatchAll } = parseDynamicSegment(segment);
|
|
32
|
-
if (isDynamic && paramName) {
|
|
33
|
-
params.push(paramName);
|
|
34
|
-
if (isCatchAll) {
|
|
35
|
-
hasCatchAll = true;
|
|
36
|
-
return `*`;
|
|
37
|
-
}
|
|
38
|
-
return `:${paramName}`;
|
|
39
|
-
}
|
|
40
|
-
return segment;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const routePath = '/' + routeSegments.join('/');
|
|
44
|
-
return { routePath: routePath === '/' ? '/' : routePath, params, hasCatchAll };
|
|
45
|
-
}
|
package/tsup.config.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'tsup';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
entry: {
|
|
5
|
-
'olova': 'olova.ts',
|
|
6
|
-
'main': 'src/main.tsx',
|
|
7
|
-
'entry-server': 'src/entry-server.tsx',
|
|
8
|
-
'entry-worker': 'src/entry-worker.tsx',
|
|
9
|
-
'performance': 'src/performance.ts',
|
|
10
|
-
'router': 'src/router/router.tsx',
|
|
11
|
-
},
|
|
12
|
-
format: ['cjs', 'esm'],
|
|
13
|
-
dts: {
|
|
14
|
-
entry: {
|
|
15
|
-
'olova': 'olova.ts',
|
|
16
|
-
'router': 'src/router/router.tsx',
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
clean: true,
|
|
20
|
-
shims: true,
|
|
21
|
-
platform: 'node',
|
|
22
|
-
external: [
|
|
23
|
-
'vite',
|
|
24
|
-
'react',
|
|
25
|
-
'react-dom',
|
|
26
|
-
'react-dom/client',
|
|
27
|
-
'react-dom/server',
|
|
28
|
-
'virtual:olova-app', // External - resolved at runtime by plugin
|
|
29
|
-
'/src/index.css' // External - resolved by Vite in user project
|
|
30
|
-
],
|
|
31
|
-
treeshake: true,
|
|
32
|
-
sourcemap: true,
|
|
33
|
-
minify: false,
|
|
34
|
-
target: 'node18',
|
|
35
|
-
});
|