@lolyjs/core 0.2.0-alpha.8 → 0.3.0-alpha.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/README.md +1593 -762
- package/dist/{bootstrap-DgvWWDim.d.mts → bootstrap-BfGTMUkj.d.mts} +12 -0
- package/dist/{bootstrap-DgvWWDim.d.ts → bootstrap-BfGTMUkj.d.ts} +12 -0
- package/dist/cli.cjs +16397 -2601
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +19096 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.cjs +17419 -3204
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +323 -56
- package/dist/index.d.ts +323 -56
- package/dist/index.mjs +20236 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.types-Duhjyfit.d.mts +280 -0
- package/dist/index.types-Duhjyfit.d.ts +280 -0
- package/dist/react/cache.cjs +82 -32
- package/dist/react/cache.cjs.map +1 -1
- package/dist/react/cache.d.mts +29 -21
- package/dist/react/cache.d.ts +29 -21
- package/dist/react/{cache.js → cache.mjs} +84 -34
- package/dist/react/cache.mjs.map +1 -0
- package/dist/react/components.cjs +11 -12
- package/dist/react/components.cjs.map +1 -1
- package/dist/react/{components.js → components.mjs} +12 -13
- package/dist/react/components.mjs.map +1 -0
- package/dist/react/hooks.cjs +28 -54
- package/dist/react/hooks.cjs.map +1 -1
- package/dist/react/hooks.d.mts +1 -24
- package/dist/react/hooks.d.ts +1 -24
- package/dist/react/{hooks.js → hooks.mjs} +27 -52
- package/dist/react/hooks.mjs.map +1 -0
- package/dist/react/sockets.cjs +5 -6
- package/dist/react/sockets.cjs.map +1 -1
- package/dist/react/sockets.mjs +21 -0
- package/dist/react/sockets.mjs.map +1 -0
- package/dist/react/themes.cjs +61 -18
- package/dist/react/themes.cjs.map +1 -1
- package/dist/react/{themes.js → themes.mjs} +64 -21
- package/dist/react/themes.mjs.map +1 -0
- package/dist/runtime.cjs +465 -117
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/{runtime.js → runtime.mjs} +466 -118
- package/dist/runtime.mjs.map +1 -0
- package/package.json +26 -19
- package/dist/cli.js +0 -5291
- package/dist/cli.js.map +0 -1
- package/dist/index.js +0 -6015
- package/dist/index.js.map +0 -1
- package/dist/react/cache.js.map +0 -1
- package/dist/react/components.js.map +0 -1
- package/dist/react/hooks.js.map +0 -1
- package/dist/react/sockets.js +0 -22
- package/dist/react/sockets.js.map +0 -1
- package/dist/react/themes.js.map +0 -1
- package/dist/runtime.js.map +0 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
|
|
3
|
+
type GenerateStaticParams = () => Array<Record<string, string>> | Promise<Array<Record<string, string>>>;
|
|
4
|
+
/**
|
|
5
|
+
* Response class for redirects in server loaders.
|
|
6
|
+
* Use ctx.Redirect() to return this from getServerSideProps.
|
|
7
|
+
*/
|
|
8
|
+
declare class RedirectResponse {
|
|
9
|
+
destination: string;
|
|
10
|
+
permanent: boolean;
|
|
11
|
+
constructor(destination: string, permanent?: boolean);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Response class for not found in server loaders.
|
|
15
|
+
* Use ctx.NotFound() to return this from getServerSideProps.
|
|
16
|
+
*/
|
|
17
|
+
declare class NotFoundResponse {
|
|
18
|
+
constructor();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Base context interface with common fields shared by ServerContext and ApiContext.
|
|
22
|
+
* This reduces duplication and ensures consistency across context types.
|
|
23
|
+
*/
|
|
24
|
+
interface BaseContext {
|
|
25
|
+
/** Express request object */
|
|
26
|
+
req: Request;
|
|
27
|
+
/** Express response object */
|
|
28
|
+
res: Response;
|
|
29
|
+
/** Route parameters extracted from the URL pattern */
|
|
30
|
+
params: Record<string, string>;
|
|
31
|
+
/** Current pathname (may be rewritten path for rewrites) */
|
|
32
|
+
pathname: string;
|
|
33
|
+
/** Local storage for passing data between middlewares and handlers */
|
|
34
|
+
locals: Record<string, any>;
|
|
35
|
+
}
|
|
36
|
+
interface ServerContext extends BaseContext {
|
|
37
|
+
/**
|
|
38
|
+
* Redirect helper method. Returns a RedirectResponse that will be handled automatically.
|
|
39
|
+
* @example
|
|
40
|
+
* if (!user) {
|
|
41
|
+
* return ctx.Redirect("/login");
|
|
42
|
+
* }
|
|
43
|
+
*/
|
|
44
|
+
Redirect: (destination: string, permanent?: boolean) => RedirectResponse;
|
|
45
|
+
/**
|
|
46
|
+
* Not found helper method. Returns a NotFoundResponse that will be handled automatically.
|
|
47
|
+
* @example
|
|
48
|
+
* if (!post) {
|
|
49
|
+
* return ctx.NotFound();
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
NotFound: () => NotFoundResponse;
|
|
53
|
+
}
|
|
54
|
+
interface WssActions {
|
|
55
|
+
/**
|
|
56
|
+
* Emit to current socket only (reply)
|
|
57
|
+
*/
|
|
58
|
+
reply(event: string, payload?: any): void;
|
|
59
|
+
/**
|
|
60
|
+
* Emit an event to all clients in the namespace
|
|
61
|
+
*/
|
|
62
|
+
emit: (event: string, ...args: any[]) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Emit to everyone except current socket
|
|
65
|
+
*/
|
|
66
|
+
broadcast(event: string, payload?: any, opts?: {
|
|
67
|
+
excludeSelf?: boolean;
|
|
68
|
+
}): void;
|
|
69
|
+
/**
|
|
70
|
+
* Join a room
|
|
71
|
+
*/
|
|
72
|
+
join(room: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Leave a room
|
|
75
|
+
*/
|
|
76
|
+
leave(room: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Emit to a specific room
|
|
79
|
+
*/
|
|
80
|
+
toRoom(room: string): {
|
|
81
|
+
emit(event: string, payload?: any): void;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Emit to a specific user (by userId)
|
|
85
|
+
* Uses presence mapping to find user's sockets
|
|
86
|
+
*/
|
|
87
|
+
toUser(userId: string): {
|
|
88
|
+
emit(event: string, payload?: any): void;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Emit error event (reserved event: __loly:error)
|
|
92
|
+
*/
|
|
93
|
+
error(code: string, message: string, details?: any): void;
|
|
94
|
+
/**
|
|
95
|
+
* Emit an event to a specific socket by Socket.IO socket ID
|
|
96
|
+
* @deprecated Use toUser() for user targeting
|
|
97
|
+
*/
|
|
98
|
+
emitTo?: (socketId: string, event: string, ...args: any[]) => void;
|
|
99
|
+
/**
|
|
100
|
+
* Emit an event to a specific client by custom clientId
|
|
101
|
+
* @deprecated Use toUser() for user targeting
|
|
102
|
+
*/
|
|
103
|
+
emitToClient?: (clientId: string, event: string, ...args: any[]) => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Route middleware function type.
|
|
107
|
+
* Middlewares run before getServerSideProps and can modify ctx.locals, set headers, redirect, etc.
|
|
108
|
+
*
|
|
109
|
+
* @param ctx - Server context with optional theme
|
|
110
|
+
* @param next - Function to call the next middleware in the chain (must be awaited if used)
|
|
111
|
+
* @returns Promise<void> | void
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // Simple middleware that adds data to ctx.locals
|
|
115
|
+
* export const beforeServerData: RouteMiddleware[] = [
|
|
116
|
+
* async (ctx, next) => {
|
|
117
|
+
* ctx.locals.user = await getUser(ctx.req);
|
|
118
|
+
* await next();
|
|
119
|
+
* }
|
|
120
|
+
* ];
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* // Middleware that redirects
|
|
124
|
+
* export const beforeServerData: RouteMiddleware[] = [
|
|
125
|
+
* async (ctx, next) => {
|
|
126
|
+
* if (!ctx.locals.user) {
|
|
127
|
+
* ctx.res.redirect('/login');
|
|
128
|
+
* return; // Don't call next() if redirecting
|
|
129
|
+
* }
|
|
130
|
+
* await next();
|
|
131
|
+
* }
|
|
132
|
+
* ];
|
|
133
|
+
*/
|
|
134
|
+
type RouteMiddleware = (ctx: ServerContext & {
|
|
135
|
+
theme?: string;
|
|
136
|
+
}, next: () => Promise<void>) => Promise<void> | void;
|
|
137
|
+
/**
|
|
138
|
+
* Global middleware type for middlewares that run before route matching.
|
|
139
|
+
* These middlewares establish context (ctx.locals) and always execute (both SSR and SPA navigation).
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* // global.middleware.ts
|
|
143
|
+
* export const globalMiddlewares: GlobalMiddleware[] = [
|
|
144
|
+
* async (ctx, next) => {
|
|
145
|
+
* ctx.locals.user = await getSession(ctx.req);
|
|
146
|
+
* await next();
|
|
147
|
+
* }
|
|
148
|
+
* ];
|
|
149
|
+
*/
|
|
150
|
+
type GlobalMiddleware = (ctx: ServerContext, next: () => Promise<void>) => Promise<void> | void;
|
|
151
|
+
/**
|
|
152
|
+
* Result returned by a server loader (getServerSideProps).
|
|
153
|
+
* @template TProps - Type of props that will be passed to the component (defaults to Record<string, any>)
|
|
154
|
+
*/
|
|
155
|
+
interface LoaderResult<TProps extends Record<string, any> = Record<string, any>> {
|
|
156
|
+
pathname?: string;
|
|
157
|
+
props?: TProps;
|
|
158
|
+
metadata?: PageMetadata | null;
|
|
159
|
+
className?: string;
|
|
160
|
+
theme?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Server loader function type (getServerSideProps).
|
|
164
|
+
* This function is exported from server.hook.ts files.
|
|
165
|
+
*
|
|
166
|
+
* @template TProps - Type of props that will be returned (defaults to Record<string, any>)
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* // Typed loader
|
|
170
|
+
* export const getServerSideProps: ServerLoader<{ user: User; posts: Post[] }> = async (ctx) => ({
|
|
171
|
+
* props: { user: await getUser(), posts: await getPosts() }
|
|
172
|
+
* });
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* // Untyped loader (backward compatible)
|
|
176
|
+
* export const getServerSideProps: ServerLoader = async (ctx) => ({
|
|
177
|
+
* props: { any: 'data' }
|
|
178
|
+
* });
|
|
179
|
+
*/
|
|
180
|
+
type ServerLoader<TProps extends Record<string, any> = Record<string, any>> = (ctx: ServerContext) => Promise<LoaderResult<TProps> | RedirectResponse | NotFoundResponse>;
|
|
181
|
+
/**
|
|
182
|
+
* Comprehensive page metadata for SEO and social sharing.
|
|
183
|
+
* Supports standard HTML meta tags, Open Graph, Twitter Cards, and more.
|
|
184
|
+
*/
|
|
185
|
+
interface PageMetadata {
|
|
186
|
+
/** Page title (sets <title> tag) */
|
|
187
|
+
title?: string;
|
|
188
|
+
/** Page description (sets <meta name="description">) */
|
|
189
|
+
description?: string;
|
|
190
|
+
/** Language code (sets <html lang="...">) */
|
|
191
|
+
lang?: string;
|
|
192
|
+
/** Canonical URL (sets <link rel="canonical">) */
|
|
193
|
+
canonical?: string;
|
|
194
|
+
/** Robots directive (sets <meta name="robots">) */
|
|
195
|
+
robots?: string;
|
|
196
|
+
/** Theme color (sets <meta name="theme-color">) */
|
|
197
|
+
themeColor?: string;
|
|
198
|
+
/** Viewport configuration (sets <meta name="viewport">) */
|
|
199
|
+
viewport?: string;
|
|
200
|
+
/** Open Graph metadata for social sharing */
|
|
201
|
+
openGraph?: {
|
|
202
|
+
title?: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
type?: string;
|
|
205
|
+
url?: string;
|
|
206
|
+
image?: string | {
|
|
207
|
+
url: string;
|
|
208
|
+
width?: number;
|
|
209
|
+
height?: number;
|
|
210
|
+
alt?: string;
|
|
211
|
+
};
|
|
212
|
+
siteName?: string;
|
|
213
|
+
locale?: string;
|
|
214
|
+
};
|
|
215
|
+
/** Twitter Card metadata */
|
|
216
|
+
twitter?: {
|
|
217
|
+
card?: "summary" | "summary_large_image" | "app" | "player";
|
|
218
|
+
title?: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
image?: string;
|
|
221
|
+
imageAlt?: string;
|
|
222
|
+
site?: string;
|
|
223
|
+
creator?: string;
|
|
224
|
+
};
|
|
225
|
+
/** Additional custom meta tags */
|
|
226
|
+
metaTags?: {
|
|
227
|
+
name?: string;
|
|
228
|
+
property?: string;
|
|
229
|
+
httpEquiv?: string;
|
|
230
|
+
content: string;
|
|
231
|
+
}[];
|
|
232
|
+
/** Additional link tags (e.g., preconnect, dns-prefetch) */
|
|
233
|
+
links?: {
|
|
234
|
+
rel: string;
|
|
235
|
+
href: string;
|
|
236
|
+
as?: string;
|
|
237
|
+
crossorigin?: string;
|
|
238
|
+
type?: string;
|
|
239
|
+
}[];
|
|
240
|
+
}
|
|
241
|
+
type MetadataLoader = (ctx: ServerContext) => PageMetadata | Promise<PageMetadata>;
|
|
242
|
+
interface ApiContext extends BaseContext {
|
|
243
|
+
/**
|
|
244
|
+
* Response helper method. Sends a JSON response with optional status code.
|
|
245
|
+
* @example
|
|
246
|
+
* return ctx.Response({ user }, 200);
|
|
247
|
+
* return ctx.Response({ error: "Not found" }, 404);
|
|
248
|
+
*/
|
|
249
|
+
Response: (body?: any, status?: number) => Response<any, Record<string, any>>;
|
|
250
|
+
/**
|
|
251
|
+
* Not found helper method. Sends a 404 JSON response.
|
|
252
|
+
* @example
|
|
253
|
+
* return ctx.NotFound({ error: "Resource not found" });
|
|
254
|
+
*/
|
|
255
|
+
NotFound: (body?: any) => Response<any, Record<string, any>>;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* API middleware function type.
|
|
259
|
+
* Middlewares run before the API handler and can modify ctx.locals, set headers, etc.
|
|
260
|
+
*
|
|
261
|
+
* @param ctx - API context
|
|
262
|
+
* @param next - Function to call the next middleware in the chain (must be awaited if used)
|
|
263
|
+
* @returns Promise<void> | void
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* // Authentication middleware
|
|
267
|
+
* export const middlewares: ApiMiddleware[] = [
|
|
268
|
+
* async (ctx, next) => {
|
|
269
|
+
* const token = ctx.req.headers.authorization;
|
|
270
|
+
* if (!token) {
|
|
271
|
+
* return ctx.Response({ error: 'Unauthorized' }, 401);
|
|
272
|
+
* }
|
|
273
|
+
* ctx.locals.user = await verifyToken(token);
|
|
274
|
+
* await next();
|
|
275
|
+
* }
|
|
276
|
+
* ];
|
|
277
|
+
*/
|
|
278
|
+
type ApiMiddleware = (ctx: ApiContext, next: () => Promise<void>) => void | Promise<void>;
|
|
279
|
+
|
|
280
|
+
export { type ApiMiddleware as A, type GlobalMiddleware as G, type LoaderResult as L, type MetadataLoader as M, NotFoundResponse as N, type PageMetadata as P, type RouteMiddleware as R, type ServerContext as S, type WssActions as W, type ApiContext as a, type GenerateStaticParams as b, type ServerLoader as c, RedirectResponse as d };
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
|
|
3
|
+
type GenerateStaticParams = () => Array<Record<string, string>> | Promise<Array<Record<string, string>>>;
|
|
4
|
+
/**
|
|
5
|
+
* Response class for redirects in server loaders.
|
|
6
|
+
* Use ctx.Redirect() to return this from getServerSideProps.
|
|
7
|
+
*/
|
|
8
|
+
declare class RedirectResponse {
|
|
9
|
+
destination: string;
|
|
10
|
+
permanent: boolean;
|
|
11
|
+
constructor(destination: string, permanent?: boolean);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Response class for not found in server loaders.
|
|
15
|
+
* Use ctx.NotFound() to return this from getServerSideProps.
|
|
16
|
+
*/
|
|
17
|
+
declare class NotFoundResponse {
|
|
18
|
+
constructor();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Base context interface with common fields shared by ServerContext and ApiContext.
|
|
22
|
+
* This reduces duplication and ensures consistency across context types.
|
|
23
|
+
*/
|
|
24
|
+
interface BaseContext {
|
|
25
|
+
/** Express request object */
|
|
26
|
+
req: Request;
|
|
27
|
+
/** Express response object */
|
|
28
|
+
res: Response;
|
|
29
|
+
/** Route parameters extracted from the URL pattern */
|
|
30
|
+
params: Record<string, string>;
|
|
31
|
+
/** Current pathname (may be rewritten path for rewrites) */
|
|
32
|
+
pathname: string;
|
|
33
|
+
/** Local storage for passing data between middlewares and handlers */
|
|
34
|
+
locals: Record<string, any>;
|
|
35
|
+
}
|
|
36
|
+
interface ServerContext extends BaseContext {
|
|
37
|
+
/**
|
|
38
|
+
* Redirect helper method. Returns a RedirectResponse that will be handled automatically.
|
|
39
|
+
* @example
|
|
40
|
+
* if (!user) {
|
|
41
|
+
* return ctx.Redirect("/login");
|
|
42
|
+
* }
|
|
43
|
+
*/
|
|
44
|
+
Redirect: (destination: string, permanent?: boolean) => RedirectResponse;
|
|
45
|
+
/**
|
|
46
|
+
* Not found helper method. Returns a NotFoundResponse that will be handled automatically.
|
|
47
|
+
* @example
|
|
48
|
+
* if (!post) {
|
|
49
|
+
* return ctx.NotFound();
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
NotFound: () => NotFoundResponse;
|
|
53
|
+
}
|
|
54
|
+
interface WssActions {
|
|
55
|
+
/**
|
|
56
|
+
* Emit to current socket only (reply)
|
|
57
|
+
*/
|
|
58
|
+
reply(event: string, payload?: any): void;
|
|
59
|
+
/**
|
|
60
|
+
* Emit an event to all clients in the namespace
|
|
61
|
+
*/
|
|
62
|
+
emit: (event: string, ...args: any[]) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Emit to everyone except current socket
|
|
65
|
+
*/
|
|
66
|
+
broadcast(event: string, payload?: any, opts?: {
|
|
67
|
+
excludeSelf?: boolean;
|
|
68
|
+
}): void;
|
|
69
|
+
/**
|
|
70
|
+
* Join a room
|
|
71
|
+
*/
|
|
72
|
+
join(room: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Leave a room
|
|
75
|
+
*/
|
|
76
|
+
leave(room: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Emit to a specific room
|
|
79
|
+
*/
|
|
80
|
+
toRoom(room: string): {
|
|
81
|
+
emit(event: string, payload?: any): void;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Emit to a specific user (by userId)
|
|
85
|
+
* Uses presence mapping to find user's sockets
|
|
86
|
+
*/
|
|
87
|
+
toUser(userId: string): {
|
|
88
|
+
emit(event: string, payload?: any): void;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Emit error event (reserved event: __loly:error)
|
|
92
|
+
*/
|
|
93
|
+
error(code: string, message: string, details?: any): void;
|
|
94
|
+
/**
|
|
95
|
+
* Emit an event to a specific socket by Socket.IO socket ID
|
|
96
|
+
* @deprecated Use toUser() for user targeting
|
|
97
|
+
*/
|
|
98
|
+
emitTo?: (socketId: string, event: string, ...args: any[]) => void;
|
|
99
|
+
/**
|
|
100
|
+
* Emit an event to a specific client by custom clientId
|
|
101
|
+
* @deprecated Use toUser() for user targeting
|
|
102
|
+
*/
|
|
103
|
+
emitToClient?: (clientId: string, event: string, ...args: any[]) => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Route middleware function type.
|
|
107
|
+
* Middlewares run before getServerSideProps and can modify ctx.locals, set headers, redirect, etc.
|
|
108
|
+
*
|
|
109
|
+
* @param ctx - Server context with optional theme
|
|
110
|
+
* @param next - Function to call the next middleware in the chain (must be awaited if used)
|
|
111
|
+
* @returns Promise<void> | void
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // Simple middleware that adds data to ctx.locals
|
|
115
|
+
* export const beforeServerData: RouteMiddleware[] = [
|
|
116
|
+
* async (ctx, next) => {
|
|
117
|
+
* ctx.locals.user = await getUser(ctx.req);
|
|
118
|
+
* await next();
|
|
119
|
+
* }
|
|
120
|
+
* ];
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* // Middleware that redirects
|
|
124
|
+
* export const beforeServerData: RouteMiddleware[] = [
|
|
125
|
+
* async (ctx, next) => {
|
|
126
|
+
* if (!ctx.locals.user) {
|
|
127
|
+
* ctx.res.redirect('/login');
|
|
128
|
+
* return; // Don't call next() if redirecting
|
|
129
|
+
* }
|
|
130
|
+
* await next();
|
|
131
|
+
* }
|
|
132
|
+
* ];
|
|
133
|
+
*/
|
|
134
|
+
type RouteMiddleware = (ctx: ServerContext & {
|
|
135
|
+
theme?: string;
|
|
136
|
+
}, next: () => Promise<void>) => Promise<void> | void;
|
|
137
|
+
/**
|
|
138
|
+
* Global middleware type for middlewares that run before route matching.
|
|
139
|
+
* These middlewares establish context (ctx.locals) and always execute (both SSR and SPA navigation).
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* // global.middleware.ts
|
|
143
|
+
* export const globalMiddlewares: GlobalMiddleware[] = [
|
|
144
|
+
* async (ctx, next) => {
|
|
145
|
+
* ctx.locals.user = await getSession(ctx.req);
|
|
146
|
+
* await next();
|
|
147
|
+
* }
|
|
148
|
+
* ];
|
|
149
|
+
*/
|
|
150
|
+
type GlobalMiddleware = (ctx: ServerContext, next: () => Promise<void>) => Promise<void> | void;
|
|
151
|
+
/**
|
|
152
|
+
* Result returned by a server loader (getServerSideProps).
|
|
153
|
+
* @template TProps - Type of props that will be passed to the component (defaults to Record<string, any>)
|
|
154
|
+
*/
|
|
155
|
+
interface LoaderResult<TProps extends Record<string, any> = Record<string, any>> {
|
|
156
|
+
pathname?: string;
|
|
157
|
+
props?: TProps;
|
|
158
|
+
metadata?: PageMetadata | null;
|
|
159
|
+
className?: string;
|
|
160
|
+
theme?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Server loader function type (getServerSideProps).
|
|
164
|
+
* This function is exported from server.hook.ts files.
|
|
165
|
+
*
|
|
166
|
+
* @template TProps - Type of props that will be returned (defaults to Record<string, any>)
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* // Typed loader
|
|
170
|
+
* export const getServerSideProps: ServerLoader<{ user: User; posts: Post[] }> = async (ctx) => ({
|
|
171
|
+
* props: { user: await getUser(), posts: await getPosts() }
|
|
172
|
+
* });
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* // Untyped loader (backward compatible)
|
|
176
|
+
* export const getServerSideProps: ServerLoader = async (ctx) => ({
|
|
177
|
+
* props: { any: 'data' }
|
|
178
|
+
* });
|
|
179
|
+
*/
|
|
180
|
+
type ServerLoader<TProps extends Record<string, any> = Record<string, any>> = (ctx: ServerContext) => Promise<LoaderResult<TProps> | RedirectResponse | NotFoundResponse>;
|
|
181
|
+
/**
|
|
182
|
+
* Comprehensive page metadata for SEO and social sharing.
|
|
183
|
+
* Supports standard HTML meta tags, Open Graph, Twitter Cards, and more.
|
|
184
|
+
*/
|
|
185
|
+
interface PageMetadata {
|
|
186
|
+
/** Page title (sets <title> tag) */
|
|
187
|
+
title?: string;
|
|
188
|
+
/** Page description (sets <meta name="description">) */
|
|
189
|
+
description?: string;
|
|
190
|
+
/** Language code (sets <html lang="...">) */
|
|
191
|
+
lang?: string;
|
|
192
|
+
/** Canonical URL (sets <link rel="canonical">) */
|
|
193
|
+
canonical?: string;
|
|
194
|
+
/** Robots directive (sets <meta name="robots">) */
|
|
195
|
+
robots?: string;
|
|
196
|
+
/** Theme color (sets <meta name="theme-color">) */
|
|
197
|
+
themeColor?: string;
|
|
198
|
+
/** Viewport configuration (sets <meta name="viewport">) */
|
|
199
|
+
viewport?: string;
|
|
200
|
+
/** Open Graph metadata for social sharing */
|
|
201
|
+
openGraph?: {
|
|
202
|
+
title?: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
type?: string;
|
|
205
|
+
url?: string;
|
|
206
|
+
image?: string | {
|
|
207
|
+
url: string;
|
|
208
|
+
width?: number;
|
|
209
|
+
height?: number;
|
|
210
|
+
alt?: string;
|
|
211
|
+
};
|
|
212
|
+
siteName?: string;
|
|
213
|
+
locale?: string;
|
|
214
|
+
};
|
|
215
|
+
/** Twitter Card metadata */
|
|
216
|
+
twitter?: {
|
|
217
|
+
card?: "summary" | "summary_large_image" | "app" | "player";
|
|
218
|
+
title?: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
image?: string;
|
|
221
|
+
imageAlt?: string;
|
|
222
|
+
site?: string;
|
|
223
|
+
creator?: string;
|
|
224
|
+
};
|
|
225
|
+
/** Additional custom meta tags */
|
|
226
|
+
metaTags?: {
|
|
227
|
+
name?: string;
|
|
228
|
+
property?: string;
|
|
229
|
+
httpEquiv?: string;
|
|
230
|
+
content: string;
|
|
231
|
+
}[];
|
|
232
|
+
/** Additional link tags (e.g., preconnect, dns-prefetch) */
|
|
233
|
+
links?: {
|
|
234
|
+
rel: string;
|
|
235
|
+
href: string;
|
|
236
|
+
as?: string;
|
|
237
|
+
crossorigin?: string;
|
|
238
|
+
type?: string;
|
|
239
|
+
}[];
|
|
240
|
+
}
|
|
241
|
+
type MetadataLoader = (ctx: ServerContext) => PageMetadata | Promise<PageMetadata>;
|
|
242
|
+
interface ApiContext extends BaseContext {
|
|
243
|
+
/**
|
|
244
|
+
* Response helper method. Sends a JSON response with optional status code.
|
|
245
|
+
* @example
|
|
246
|
+
* return ctx.Response({ user }, 200);
|
|
247
|
+
* return ctx.Response({ error: "Not found" }, 404);
|
|
248
|
+
*/
|
|
249
|
+
Response: (body?: any, status?: number) => Response<any, Record<string, any>>;
|
|
250
|
+
/**
|
|
251
|
+
* Not found helper method. Sends a 404 JSON response.
|
|
252
|
+
* @example
|
|
253
|
+
* return ctx.NotFound({ error: "Resource not found" });
|
|
254
|
+
*/
|
|
255
|
+
NotFound: (body?: any) => Response<any, Record<string, any>>;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* API middleware function type.
|
|
259
|
+
* Middlewares run before the API handler and can modify ctx.locals, set headers, etc.
|
|
260
|
+
*
|
|
261
|
+
* @param ctx - API context
|
|
262
|
+
* @param next - Function to call the next middleware in the chain (must be awaited if used)
|
|
263
|
+
* @returns Promise<void> | void
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* // Authentication middleware
|
|
267
|
+
* export const middlewares: ApiMiddleware[] = [
|
|
268
|
+
* async (ctx, next) => {
|
|
269
|
+
* const token = ctx.req.headers.authorization;
|
|
270
|
+
* if (!token) {
|
|
271
|
+
* return ctx.Response({ error: 'Unauthorized' }, 401);
|
|
272
|
+
* }
|
|
273
|
+
* ctx.locals.user = await verifyToken(token);
|
|
274
|
+
* await next();
|
|
275
|
+
* }
|
|
276
|
+
* ];
|
|
277
|
+
*/
|
|
278
|
+
type ApiMiddleware = (ctx: ApiContext, next: () => Promise<void>) => void | Promise<void>;
|
|
279
|
+
|
|
280
|
+
export { type ApiMiddleware as A, type GlobalMiddleware as G, type LoaderResult as L, type MetadataLoader as M, NotFoundResponse as N, type PageMetadata as P, type RouteMiddleware as R, type ServerContext as S, type WssActions as W, type ApiContext as a, type GenerateStaticParams as b, type ServerLoader as c, RedirectResponse as d };
|