elit 3.0.0 → 3.0.2
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/build.d.ts +4 -12
- package/dist/build.d.ts.map +1 -0
- package/dist/chokidar.d.ts +7 -9
- package/dist/chokidar.d.ts.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +17 -4
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/dom.d.ts +7 -14
- package/dist/dom.d.ts.map +1 -0
- package/dist/el.d.ts +19 -191
- package/dist/el.d.ts.map +1 -0
- package/dist/fs.d.ts +35 -35
- package/dist/fs.d.ts.map +1 -0
- package/dist/hmr.d.ts +3 -3
- package/dist/hmr.d.ts.map +1 -0
- package/dist/http.d.ts +20 -22
- package/dist/http.d.ts.map +1 -0
- package/dist/https.d.ts +12 -15
- package/dist/https.d.ts.map +1 -0
- package/dist/index.d.ts +10 -629
- package/dist/index.d.ts.map +1 -0
- package/dist/mime-types.d.ts +9 -9
- package/dist/mime-types.d.ts.map +1 -0
- package/dist/path.d.ts +22 -19
- package/dist/path.d.ts.map +1 -0
- package/dist/router.d.ts +10 -17
- package/dist/router.d.ts.map +1 -0
- package/dist/runtime.d.ts +5 -6
- package/dist/runtime.d.ts.map +1 -0
- package/dist/server.d.ts +105 -7
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +14 -2
- package/dist/server.mjs +14 -2
- package/dist/state.d.ts +21 -27
- package/dist/state.d.ts.map +1 -0
- package/dist/style.d.ts +14 -55
- package/dist/style.d.ts.map +1 -0
- package/dist/types.d.ts +26 -240
- package/dist/types.d.ts.map +1 -0
- package/dist/ws.d.ts +14 -17
- package/dist/ws.d.ts.map +1 -0
- package/dist/wss.d.ts +16 -16
- package/dist/wss.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/build.ts +337 -0
- package/src/chokidar.ts +401 -0
- package/src/cli.ts +638 -0
- package/src/config.ts +205 -0
- package/src/dom.ts +817 -0
- package/src/el.ts +164 -0
- package/src/fs.ts +727 -0
- package/src/hmr.ts +137 -0
- package/src/http.ts +775 -0
- package/src/https.ts +411 -0
- package/src/index.ts +14 -0
- package/src/mime-types.ts +222 -0
- package/src/path.ts +493 -0
- package/src/router.ts +237 -0
- package/src/runtime.ts +97 -0
- package/src/server.ts +1290 -0
- package/src/state.ts +468 -0
- package/src/style.ts +524 -0
- package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
- package/src/ws.ts +506 -0
- package/src/wss.ts +241 -0
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -207
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -163
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -629
- package/dist/mime-types.d.mts +0 -48
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -47
- package/dist/runtime.d.mts +0 -97
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -111
- package/dist/style.d.mts +0 -159
- package/dist/types-C0nGi6MX.d.mts +0 -346
- package/dist/types.d.mts +0 -452
- package/dist/ws.d.mts +0 -195
- package/dist/wss.d.mts +0 -108
package/src/router.ts
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elit - Router - Client-side routing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { VNode, Child, Props, State } from './types';
|
|
6
|
+
import { dom } from './dom';
|
|
7
|
+
|
|
8
|
+
export interface Route {
|
|
9
|
+
path: string;
|
|
10
|
+
component: (params: RouteParams) => VNode | Child;
|
|
11
|
+
beforeEnter?: (to: RouteLocation, from: RouteLocation | null) => boolean | string | void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface RouteParams {
|
|
15
|
+
[key: string]: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RouteLocation {
|
|
19
|
+
path: string;
|
|
20
|
+
params: RouteParams;
|
|
21
|
+
query: Record<string, string>;
|
|
22
|
+
hash: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface RouterOptions {
|
|
26
|
+
mode?: 'history' | 'hash';
|
|
27
|
+
base?: string;
|
|
28
|
+
routes: Route[];
|
|
29
|
+
notFound?: (params: RouteParams) => VNode | Child;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface Router {
|
|
33
|
+
currentRoute: State<RouteLocation>;
|
|
34
|
+
push: (path: string) => void;
|
|
35
|
+
replace: (path: string) => void;
|
|
36
|
+
back: () => void;
|
|
37
|
+
forward: () => void;
|
|
38
|
+
go: (delta: number) => void;
|
|
39
|
+
beforeEach: (guard: (to: RouteLocation, from: RouteLocation | null) => boolean | string | void) => void;
|
|
40
|
+
destroy: () => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Helper: Match route pattern against path
|
|
45
|
+
*/
|
|
46
|
+
function matchRoute(pattern: string, path: string): RouteParams | null {
|
|
47
|
+
const patternParts = pattern.split('/').filter(Boolean);
|
|
48
|
+
const pathParts = path.split('/').filter(Boolean);
|
|
49
|
+
|
|
50
|
+
if (pattern.endsWith('*')) {
|
|
51
|
+
const basePattern = pattern.slice(0, -1);
|
|
52
|
+
if (path.startsWith(basePattern) || basePattern === '/' || pattern === '*') {
|
|
53
|
+
return { '*': path.slice(basePattern.length) };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (patternParts.length !== pathParts.length) return null;
|
|
58
|
+
|
|
59
|
+
const params: RouteParams = {};
|
|
60
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
61
|
+
const patternPart = patternParts[i];
|
|
62
|
+
const pathPart = pathParts[i];
|
|
63
|
+
|
|
64
|
+
if (patternPart.startsWith(':')) {
|
|
65
|
+
params[patternPart.slice(1)] = decodeURIComponent(pathPart);
|
|
66
|
+
} else if (patternPart !== pathPart) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return params;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Helper: Execute guard and handle result (eliminates duplication in navigate)
|
|
75
|
+
*/
|
|
76
|
+
function executeGuard(
|
|
77
|
+
guard: (to: RouteLocation, from: RouteLocation | null) => boolean | string | void,
|
|
78
|
+
to: RouteLocation,
|
|
79
|
+
from: RouteLocation | null,
|
|
80
|
+
navigate: (path: string, replace?: boolean) => void,
|
|
81
|
+
replace = false
|
|
82
|
+
): boolean {
|
|
83
|
+
const result = guard(to, from);
|
|
84
|
+
if (result === false) return false;
|
|
85
|
+
if (typeof result === 'string') {
|
|
86
|
+
navigate(result, replace);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Helper: Wrap component in VNode if needed (eliminates duplication in createRouterView)
|
|
94
|
+
*/
|
|
95
|
+
function wrapComponent(component: VNode | Child): VNode {
|
|
96
|
+
if (typeof component === 'object' && component !== null && 'tagName' in component) {
|
|
97
|
+
return component as VNode;
|
|
98
|
+
}
|
|
99
|
+
return { tagName: 'span', props: {}, children: [component] };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function createRouter(options: RouterOptions): Router {
|
|
103
|
+
const { mode = 'history', base = '', routes } = options;
|
|
104
|
+
const globalGuards: Array<(to: RouteLocation, from: RouteLocation | null) => boolean | string | void> = [];
|
|
105
|
+
|
|
106
|
+
const parseQuery = (search: string): Record<string, string> => {
|
|
107
|
+
const query: Record<string, string> = {};
|
|
108
|
+
const params = new URLSearchParams(search);
|
|
109
|
+
params.forEach((value, key) => { query[key] = value; });
|
|
110
|
+
return query;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const getCurrentPath = (): string => {
|
|
114
|
+
if (mode === 'hash') {
|
|
115
|
+
return window.location.hash.slice(1) || '/';
|
|
116
|
+
}
|
|
117
|
+
return window.location.pathname.replace(base, '') || '/';
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const parseLocation = (path: string): RouteLocation => {
|
|
121
|
+
const [pathPart, queryPart = ''] = path.split('?');
|
|
122
|
+
const [cleanPath, hash = ''] = pathPart.split('#');
|
|
123
|
+
return {
|
|
124
|
+
path: cleanPath || '/',
|
|
125
|
+
params: {},
|
|
126
|
+
query: parseQuery(queryPart),
|
|
127
|
+
hash: hash ? '#' + hash : ''
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const findRoute = (path: string): { route: Route; params: RouteParams } | null => {
|
|
132
|
+
for (const route of routes) {
|
|
133
|
+
const params = matchRoute(route.path, path);
|
|
134
|
+
if (params !== null) {
|
|
135
|
+
return { route, params };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const currentRoute = dom.createState<RouteLocation>(parseLocation(getCurrentPath()));
|
|
142
|
+
|
|
143
|
+
const navigate = (path: string, replace = false): void => {
|
|
144
|
+
const location = parseLocation(path);
|
|
145
|
+
const match = findRoute(location.path);
|
|
146
|
+
|
|
147
|
+
if (match) {
|
|
148
|
+
location.params = match.params;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
for (const guard of globalGuards) {
|
|
152
|
+
if (!executeGuard(guard, location, currentRoute.value, navigate, replace)) return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (match?.route.beforeEnter) {
|
|
156
|
+
if (!executeGuard(match.route.beforeEnter, location, currentRoute.value, navigate, replace)) return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const url = mode === 'hash' ? '#' + path : base + path;
|
|
160
|
+
if (replace) {
|
|
161
|
+
window.history.replaceState({ path }, '', url);
|
|
162
|
+
} else {
|
|
163
|
+
window.history.pushState({ path }, '', url);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
currentRoute.value = location;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const handlePopState = (): void => {
|
|
170
|
+
const path = getCurrentPath();
|
|
171
|
+
const location = parseLocation(path);
|
|
172
|
+
const match = findRoute(location.path);
|
|
173
|
+
if (match) {
|
|
174
|
+
location.params = match.params;
|
|
175
|
+
}
|
|
176
|
+
currentRoute.value = location;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
if (typeof window !== 'undefined') {
|
|
180
|
+
window.addEventListener('popstate', handlePopState);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
currentRoute,
|
|
185
|
+
push: (path: string) => navigate(path, false),
|
|
186
|
+
replace: (path: string) => navigate(path, true),
|
|
187
|
+
back: () => window.history.back(),
|
|
188
|
+
forward: () => window.history.forward(),
|
|
189
|
+
go: (delta: number) => window.history.go(delta),
|
|
190
|
+
beforeEach: (guard) => { globalGuards.push(guard); },
|
|
191
|
+
destroy: () => {
|
|
192
|
+
if (typeof window !== 'undefined') {
|
|
193
|
+
window.removeEventListener('popstate', handlePopState);
|
|
194
|
+
}
|
|
195
|
+
currentRoute.destroy();
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// RouterView component - renders current route
|
|
201
|
+
export function createRouterView(router: Router, options: RouterOptions): () => VNode {
|
|
202
|
+
const { routes, notFound } = options;
|
|
203
|
+
|
|
204
|
+
return (): VNode => {
|
|
205
|
+
const location = router.currentRoute.value;
|
|
206
|
+
const match = routes.find(r => matchRoute(r.path, location.path) !== null);
|
|
207
|
+
|
|
208
|
+
if (match) {
|
|
209
|
+
const params = matchRoute(match.path, location.path) || {};
|
|
210
|
+
const component = match.component({ ...params, ...location.query });
|
|
211
|
+
return wrapComponent(component);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (notFound) {
|
|
215
|
+
const component = notFound(location.params);
|
|
216
|
+
return wrapComponent(component);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return { tagName: 'div', props: {}, children: ['404 - Not Found'] };
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Link component - prevents default and uses router
|
|
224
|
+
export const routerLink = (router: Router, props: Props & { to: string }, ...children: Child[]): VNode => {
|
|
225
|
+
return {
|
|
226
|
+
tagName: 'a',
|
|
227
|
+
props: {
|
|
228
|
+
...props,
|
|
229
|
+
href: props.to,
|
|
230
|
+
onclick: (e: MouseEvent) => {
|
|
231
|
+
e.preventDefault();
|
|
232
|
+
router.push(props.to);
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
children
|
|
236
|
+
};
|
|
237
|
+
};
|
package/src/runtime.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime detection and global type declarations
|
|
3
|
+
* Shared across all modules for consistency
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Runtime detection (cached at module load)
|
|
8
|
+
*/
|
|
9
|
+
export const runtime = (() => {
|
|
10
|
+
// @ts-ignore - Deno global
|
|
11
|
+
if (typeof Deno !== 'undefined') return 'deno';
|
|
12
|
+
// @ts-ignore - Bun global
|
|
13
|
+
if (typeof Bun !== 'undefined') return 'bun';
|
|
14
|
+
return 'node';
|
|
15
|
+
})() as 'node' | 'bun' | 'deno';
|
|
16
|
+
|
|
17
|
+
export const isNode = runtime === 'node';
|
|
18
|
+
export const isBun = runtime === 'bun';
|
|
19
|
+
export const isDeno = runtime === 'deno';
|
|
20
|
+
|
|
21
|
+
// Global declarations for runtime-specific APIs
|
|
22
|
+
declare global {
|
|
23
|
+
// @ts-ignore - Bun global
|
|
24
|
+
const Bun: {
|
|
25
|
+
build(options: {
|
|
26
|
+
entrypoints: string[];
|
|
27
|
+
outdir?: string;
|
|
28
|
+
target?: string;
|
|
29
|
+
format?: string;
|
|
30
|
+
minify?: boolean;
|
|
31
|
+
sourcemap?: string;
|
|
32
|
+
external?: string[];
|
|
33
|
+
naming?: string;
|
|
34
|
+
plugins?: any[];
|
|
35
|
+
define?: Record<string, string>;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
success: boolean;
|
|
38
|
+
outputs: Array<{ path: string; size: number }>;
|
|
39
|
+
logs: any[];
|
|
40
|
+
}>;
|
|
41
|
+
Transpiler: new (options?: {
|
|
42
|
+
loader?: string;
|
|
43
|
+
target?: string;
|
|
44
|
+
minify?: boolean;
|
|
45
|
+
}) => {
|
|
46
|
+
transform(code: string, loader?: string): Promise<string>;
|
|
47
|
+
transformSync(code: string, loader?: string): string;
|
|
48
|
+
};
|
|
49
|
+
file(path: string): {
|
|
50
|
+
size: number;
|
|
51
|
+
arrayBuffer(): ArrayBuffer | Promise<ArrayBuffer>;
|
|
52
|
+
exists(): Promise<boolean>;
|
|
53
|
+
};
|
|
54
|
+
write(path: string, data: string | Buffer | Uint8Array): Promise<void>;
|
|
55
|
+
} | undefined;
|
|
56
|
+
|
|
57
|
+
// @ts-ignore - Deno global
|
|
58
|
+
const Deno: {
|
|
59
|
+
emit(rootSpecifier: string | URL, options?: {
|
|
60
|
+
bundle?: 'module' | 'classic';
|
|
61
|
+
check?: boolean;
|
|
62
|
+
compilerOptions?: any;
|
|
63
|
+
importMap?: string;
|
|
64
|
+
importMapPath?: string;
|
|
65
|
+
sources?: Record<string, string>;
|
|
66
|
+
}): Promise<{
|
|
67
|
+
files: Record<string, string>;
|
|
68
|
+
diagnostics: any[];
|
|
69
|
+
}>;
|
|
70
|
+
writeTextFile(path: string, data: string): Promise<void>;
|
|
71
|
+
readFile(path: string): Promise<Uint8Array>;
|
|
72
|
+
readFileSync(path: string): Uint8Array;
|
|
73
|
+
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
74
|
+
writeFileSync(path: string, data: Uint8Array): void;
|
|
75
|
+
stat(path: string): Promise<any>;
|
|
76
|
+
statSync(path: string): any;
|
|
77
|
+
mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;
|
|
78
|
+
mkdirSync(path: string, options?: { recursive?: boolean }): void;
|
|
79
|
+
readDir(path: string): AsyncIterable<any>;
|
|
80
|
+
readDirSync(path: string): Iterable<any>;
|
|
81
|
+
remove(path: string, options?: { recursive?: boolean }): Promise<void>;
|
|
82
|
+
removeSync(path: string, options?: { recursive?: boolean }): void;
|
|
83
|
+
rename(oldPath: string, newPath: string): Promise<void>;
|
|
84
|
+
renameSync(oldPath: string, newPath: string): void;
|
|
85
|
+
copyFile(src: string, dest: string): Promise<void>;
|
|
86
|
+
copyFileSync(src: string, dest: string): void;
|
|
87
|
+
realPath(path: string): Promise<string>;
|
|
88
|
+
realPathSync(path: string): string;
|
|
89
|
+
watchFs(paths: string | string[]): AsyncIterable<{
|
|
90
|
+
kind: string;
|
|
91
|
+
paths: string[];
|
|
92
|
+
}>;
|
|
93
|
+
build: {
|
|
94
|
+
os: string;
|
|
95
|
+
};
|
|
96
|
+
} | undefined;
|
|
97
|
+
}
|