@teamvelix/velix-core 5.1.7
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/dist/index.d.ts +1300 -0
- package/dist/index.js +1731 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1300 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import * as http from 'http';
|
|
3
|
+
import { IncomingMessage, ServerResponse } from 'http';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Velix v5 Configuration System
|
|
7
|
+
* Handles loading, validation, and merging of velix.config.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare const VelixConfigSchema: z.ZodObject<{
|
|
11
|
+
app: z.ZodDefault<z.ZodObject<{
|
|
12
|
+
name: z.ZodDefault<z.ZodString>;
|
|
13
|
+
url: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
name: string;
|
|
16
|
+
url?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
url?: string | undefined;
|
|
19
|
+
name?: string | undefined;
|
|
20
|
+
}>>;
|
|
21
|
+
devtools: z.ZodDefault<z.ZodBoolean>;
|
|
22
|
+
server: z.ZodDefault<z.ZodObject<{
|
|
23
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
24
|
+
host: z.ZodDefault<z.ZodString>;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
port: number;
|
|
27
|
+
host: string;
|
|
28
|
+
}, {
|
|
29
|
+
port?: number | undefined;
|
|
30
|
+
host?: string | undefined;
|
|
31
|
+
}>>;
|
|
32
|
+
routing: z.ZodDefault<z.ZodObject<{
|
|
33
|
+
trailingSlash: z.ZodDefault<z.ZodBoolean>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
trailingSlash: boolean;
|
|
36
|
+
}, {
|
|
37
|
+
trailingSlash?: boolean | undefined;
|
|
38
|
+
}>>;
|
|
39
|
+
seo: z.ZodDefault<z.ZodObject<{
|
|
40
|
+
sitemap: z.ZodDefault<z.ZodBoolean>;
|
|
41
|
+
robots: z.ZodDefault<z.ZodBoolean>;
|
|
42
|
+
openGraph: z.ZodDefault<z.ZodBoolean>;
|
|
43
|
+
}, "strip", z.ZodTypeAny, {
|
|
44
|
+
sitemap: boolean;
|
|
45
|
+
robots: boolean;
|
|
46
|
+
openGraph: boolean;
|
|
47
|
+
}, {
|
|
48
|
+
sitemap?: boolean | undefined;
|
|
49
|
+
robots?: boolean | undefined;
|
|
50
|
+
openGraph?: boolean | undefined;
|
|
51
|
+
}>>;
|
|
52
|
+
build: z.ZodDefault<z.ZodObject<{
|
|
53
|
+
target: z.ZodDefault<z.ZodString>;
|
|
54
|
+
minify: z.ZodDefault<z.ZodBoolean>;
|
|
55
|
+
sourcemap: z.ZodDefault<z.ZodBoolean>;
|
|
56
|
+
splitting: z.ZodDefault<z.ZodBoolean>;
|
|
57
|
+
outDir: z.ZodDefault<z.ZodString>;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
target: string;
|
|
60
|
+
minify: boolean;
|
|
61
|
+
sourcemap: boolean;
|
|
62
|
+
splitting: boolean;
|
|
63
|
+
outDir: string;
|
|
64
|
+
}, {
|
|
65
|
+
target?: string | undefined;
|
|
66
|
+
minify?: boolean | undefined;
|
|
67
|
+
sourcemap?: boolean | undefined;
|
|
68
|
+
splitting?: boolean | undefined;
|
|
69
|
+
outDir?: string | undefined;
|
|
70
|
+
}>>;
|
|
71
|
+
experimental: z.ZodDefault<z.ZodObject<{
|
|
72
|
+
islands: z.ZodDefault<z.ZodBoolean>;
|
|
73
|
+
streaming: z.ZodDefault<z.ZodBoolean>;
|
|
74
|
+
}, "strip", z.ZodTypeAny, {
|
|
75
|
+
islands: boolean;
|
|
76
|
+
streaming: boolean;
|
|
77
|
+
}, {
|
|
78
|
+
islands?: boolean | undefined;
|
|
79
|
+
streaming?: boolean | undefined;
|
|
80
|
+
}>>;
|
|
81
|
+
plugins: z.ZodDefault<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
82
|
+
name: z.ZodString;
|
|
83
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
84
|
+
name: z.ZodString;
|
|
85
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
86
|
+
name: z.ZodString;
|
|
87
|
+
}, z.ZodTypeAny, "passthrough">>]>, "many">>;
|
|
88
|
+
appDir: z.ZodDefault<z.ZodString>;
|
|
89
|
+
publicDir: z.ZodDefault<z.ZodString>;
|
|
90
|
+
styles: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
91
|
+
favicon: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
app: {
|
|
94
|
+
name: string;
|
|
95
|
+
url?: string | undefined;
|
|
96
|
+
};
|
|
97
|
+
devtools: boolean;
|
|
98
|
+
server: {
|
|
99
|
+
port: number;
|
|
100
|
+
host: string;
|
|
101
|
+
};
|
|
102
|
+
routing: {
|
|
103
|
+
trailingSlash: boolean;
|
|
104
|
+
};
|
|
105
|
+
seo: {
|
|
106
|
+
sitemap: boolean;
|
|
107
|
+
robots: boolean;
|
|
108
|
+
openGraph: boolean;
|
|
109
|
+
};
|
|
110
|
+
build: {
|
|
111
|
+
target: string;
|
|
112
|
+
minify: boolean;
|
|
113
|
+
sourcemap: boolean;
|
|
114
|
+
splitting: boolean;
|
|
115
|
+
outDir: string;
|
|
116
|
+
};
|
|
117
|
+
experimental: {
|
|
118
|
+
islands: boolean;
|
|
119
|
+
streaming: boolean;
|
|
120
|
+
};
|
|
121
|
+
plugins: (string | z.objectOutputType<{
|
|
122
|
+
name: z.ZodString;
|
|
123
|
+
}, z.ZodTypeAny, "passthrough">)[];
|
|
124
|
+
appDir: string;
|
|
125
|
+
publicDir: string;
|
|
126
|
+
styles: string[];
|
|
127
|
+
favicon: string | null;
|
|
128
|
+
}, {
|
|
129
|
+
app?: {
|
|
130
|
+
url?: string | undefined;
|
|
131
|
+
name?: string | undefined;
|
|
132
|
+
} | undefined;
|
|
133
|
+
devtools?: boolean | undefined;
|
|
134
|
+
server?: {
|
|
135
|
+
port?: number | undefined;
|
|
136
|
+
host?: string | undefined;
|
|
137
|
+
} | undefined;
|
|
138
|
+
routing?: {
|
|
139
|
+
trailingSlash?: boolean | undefined;
|
|
140
|
+
} | undefined;
|
|
141
|
+
seo?: {
|
|
142
|
+
sitemap?: boolean | undefined;
|
|
143
|
+
robots?: boolean | undefined;
|
|
144
|
+
openGraph?: boolean | undefined;
|
|
145
|
+
} | undefined;
|
|
146
|
+
build?: {
|
|
147
|
+
target?: string | undefined;
|
|
148
|
+
minify?: boolean | undefined;
|
|
149
|
+
sourcemap?: boolean | undefined;
|
|
150
|
+
splitting?: boolean | undefined;
|
|
151
|
+
outDir?: string | undefined;
|
|
152
|
+
} | undefined;
|
|
153
|
+
experimental?: {
|
|
154
|
+
islands?: boolean | undefined;
|
|
155
|
+
streaming?: boolean | undefined;
|
|
156
|
+
} | undefined;
|
|
157
|
+
plugins?: (string | z.objectInputType<{
|
|
158
|
+
name: z.ZodString;
|
|
159
|
+
}, z.ZodTypeAny, "passthrough">)[] | undefined;
|
|
160
|
+
appDir?: string | undefined;
|
|
161
|
+
publicDir?: string | undefined;
|
|
162
|
+
styles?: string[] | undefined;
|
|
163
|
+
favicon?: string | null | undefined;
|
|
164
|
+
}>;
|
|
165
|
+
type VelixConfig = z.infer<typeof VelixConfigSchema>;
|
|
166
|
+
declare const defaultConfig: VelixConfig;
|
|
167
|
+
/**
|
|
168
|
+
* Helper function to define configuration with full type support.
|
|
169
|
+
* Use this in your velix.config.ts file.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* import { defineConfig } from "velix";
|
|
174
|
+
*
|
|
175
|
+
* export default defineConfig({
|
|
176
|
+
* app: { name: "My App" },
|
|
177
|
+
* server: { port: 3000 },
|
|
178
|
+
* seo: { sitemap: true }
|
|
179
|
+
* });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare function defineConfig(config: Partial<VelixConfig>): Partial<VelixConfig>;
|
|
183
|
+
/**
|
|
184
|
+
* Loads and validates configuration from velix.config.ts
|
|
185
|
+
*/
|
|
186
|
+
declare function loadConfig(projectRoot: string): Promise<VelixConfig>;
|
|
187
|
+
/**
|
|
188
|
+
* Resolves all paths in config relative to project root
|
|
189
|
+
*/
|
|
190
|
+
declare function resolvePaths(config: VelixConfig, projectRoot: string): VelixConfig & {
|
|
191
|
+
resolvedAppDir: string;
|
|
192
|
+
resolvedPublicDir: string;
|
|
193
|
+
resolvedOutDir: string;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Velix v5 Middleware System
|
|
198
|
+
* Request processing pipeline with composable middleware
|
|
199
|
+
*/
|
|
200
|
+
interface MiddlewareRequest {
|
|
201
|
+
url: string;
|
|
202
|
+
method: string;
|
|
203
|
+
headers: Record<string, string | string[] | undefined>;
|
|
204
|
+
cookies: Record<string, string>;
|
|
205
|
+
params: Record<string, string>;
|
|
206
|
+
query: Record<string, string>;
|
|
207
|
+
body?: unknown;
|
|
208
|
+
raw: http.IncomingMessage;
|
|
209
|
+
}
|
|
210
|
+
interface MiddlewareResponse {
|
|
211
|
+
status: (code: number) => MiddlewareResponse;
|
|
212
|
+
header: (name: string, value: string) => MiddlewareResponse;
|
|
213
|
+
json: (data: unknown) => void;
|
|
214
|
+
redirect: (url: string, status?: number) => void;
|
|
215
|
+
rewrite: (url: string) => void;
|
|
216
|
+
next: () => Promise<void>;
|
|
217
|
+
_statusCode: number;
|
|
218
|
+
_headers: Record<string, string>;
|
|
219
|
+
_redirectUrl: string | null;
|
|
220
|
+
_rewriteUrl: string | null;
|
|
221
|
+
_ended: boolean;
|
|
222
|
+
}
|
|
223
|
+
type MiddlewareFunction = (req: MiddlewareRequest, res: MiddlewareResponse, next: () => Promise<void>) => void | Promise<void>;
|
|
224
|
+
type MiddlewareResult = {
|
|
225
|
+
continue: boolean;
|
|
226
|
+
rewritten: boolean;
|
|
227
|
+
};
|
|
228
|
+
declare const middlewares: {
|
|
229
|
+
cors(options?: {
|
|
230
|
+
origin?: string | string[];
|
|
231
|
+
methods?: string[];
|
|
232
|
+
headers?: string[];
|
|
233
|
+
credentials?: boolean;
|
|
234
|
+
maxAge?: number;
|
|
235
|
+
}): MiddlewareFunction;
|
|
236
|
+
rateLimit(options?: {
|
|
237
|
+
windowMs?: number;
|
|
238
|
+
max?: number;
|
|
239
|
+
message?: string;
|
|
240
|
+
}): MiddlewareFunction;
|
|
241
|
+
security(): MiddlewareFunction;
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* Loads proxy middleware from the project root (proxy.ts or proxy.js)
|
|
245
|
+
*/
|
|
246
|
+
declare function loadMiddleware(projectRoot: string): Promise<MiddlewareFunction[]>;
|
|
247
|
+
/**
|
|
248
|
+
* Runs middleware chain for a request
|
|
249
|
+
*/
|
|
250
|
+
declare function runMiddleware(req: http.IncomingMessage, res: http.ServerResponse, fns: MiddlewareFunction[]): Promise<MiddlewareResult>;
|
|
251
|
+
/**
|
|
252
|
+
* Compose multiple middleware into one
|
|
253
|
+
*/
|
|
254
|
+
declare function composeMiddleware(...fns: MiddlewareFunction[]): MiddlewareFunction;
|
|
255
|
+
|
|
256
|
+
type ReactNode = unknown;
|
|
257
|
+
type ComponentType<P = {}> = unknown;
|
|
258
|
+
type RouteType$1 = 'page' | 'api' | 'layout' | 'loading' | 'error' | 'not-found';
|
|
259
|
+
interface Route {
|
|
260
|
+
type: RouteType$1;
|
|
261
|
+
path: string;
|
|
262
|
+
filePath: string;
|
|
263
|
+
pattern: RegExp;
|
|
264
|
+
segments: string[];
|
|
265
|
+
layout?: string | null;
|
|
266
|
+
loading?: string | null;
|
|
267
|
+
error?: string | null;
|
|
268
|
+
notFound?: string | null;
|
|
269
|
+
template?: string | null;
|
|
270
|
+
middleware?: string | null;
|
|
271
|
+
isServerComponent?: boolean;
|
|
272
|
+
isClientComponent?: boolean;
|
|
273
|
+
isIsland?: boolean;
|
|
274
|
+
params?: Record<string, string>;
|
|
275
|
+
}
|
|
276
|
+
interface RouteTree {
|
|
277
|
+
pages: Route[];
|
|
278
|
+
api: Route[];
|
|
279
|
+
layouts: Map<string, string>;
|
|
280
|
+
tree: RouteTreeNode;
|
|
281
|
+
appRoutes: Route[];
|
|
282
|
+
rootLayout?: string;
|
|
283
|
+
}
|
|
284
|
+
interface RouteTreeNode {
|
|
285
|
+
children: Record<string, RouteTreeNode>;
|
|
286
|
+
routes: Route[];
|
|
287
|
+
}
|
|
288
|
+
interface RouteMatch {
|
|
289
|
+
route: Route;
|
|
290
|
+
params: Record<string, string>;
|
|
291
|
+
}
|
|
292
|
+
type Request = IncomingMessage & {
|
|
293
|
+
params?: Record<string, string>;
|
|
294
|
+
query?: Record<string, string>;
|
|
295
|
+
body?: unknown;
|
|
296
|
+
json?: () => Promise<unknown>;
|
|
297
|
+
};
|
|
298
|
+
type Response = ServerResponse & {
|
|
299
|
+
json?: (data: unknown) => void;
|
|
300
|
+
send?: (data: string) => void;
|
|
301
|
+
status?: (code: number) => Response;
|
|
302
|
+
};
|
|
303
|
+
type NextFunction = () => void | Promise<void>;
|
|
304
|
+
type Middleware = (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
|
|
305
|
+
type ApiHandler = (req: Request, res: Response) => void | Promise<void>;
|
|
306
|
+
|
|
307
|
+
type ActionState<T> = T | Promise<T>;
|
|
308
|
+
type ServerAction<State, Payload = FormData> = (prevState: Awaited<State>, payload: Payload) => State | Promise<State>;
|
|
309
|
+
interface TypedActionResult<T> {
|
|
310
|
+
success: boolean;
|
|
311
|
+
data?: T;
|
|
312
|
+
error?: string;
|
|
313
|
+
errors?: Record<string, string[]>;
|
|
314
|
+
redirect?: string;
|
|
315
|
+
}
|
|
316
|
+
type InferParams<Path extends string> = Path extends `${infer _Start}/[...${infer Param}]/${infer Rest}` ? {
|
|
317
|
+
[K in Param]: string;
|
|
318
|
+
} & InferParams<`/${Rest}`> : Path extends `${infer _Start}/[[...${infer Param}]]/${infer Rest}` ? {
|
|
319
|
+
[K in Param]?: string;
|
|
320
|
+
} & InferParams<`/${Rest}`> : Path extends `${infer _Start}/[${infer Param}]/${infer Rest}` ? {
|
|
321
|
+
[K in Param]: string;
|
|
322
|
+
} & InferParams<`/${Rest}`> : Path extends `${infer _Start}/[...${infer Param}]` ? {
|
|
323
|
+
[K in Param]: string;
|
|
324
|
+
} : Path extends `${infer _Start}/[[...${infer Param}]]` ? {
|
|
325
|
+
[K in Param]?: string;
|
|
326
|
+
} : Path extends `${infer _Start}/[${infer Param}]` ? {
|
|
327
|
+
[K in Param]: string;
|
|
328
|
+
} : Record<string, string>;
|
|
329
|
+
interface PageProps<TPath extends string = string> {
|
|
330
|
+
params: InferParams<TPath>;
|
|
331
|
+
searchParams?: Record<string, string>;
|
|
332
|
+
}
|
|
333
|
+
interface LayoutProps<TPath extends string = string> {
|
|
334
|
+
children: ReactNode;
|
|
335
|
+
params: InferParams<TPath>;
|
|
336
|
+
}
|
|
337
|
+
interface ErrorProps {
|
|
338
|
+
error: Error;
|
|
339
|
+
reset: () => void;
|
|
340
|
+
}
|
|
341
|
+
interface LoadingProps {
|
|
342
|
+
}
|
|
343
|
+
interface NotFoundProps {
|
|
344
|
+
}
|
|
345
|
+
type PageComponent<TPath extends string = string> = ComponentType<PageProps<TPath>>;
|
|
346
|
+
type LayoutComponent<TPath extends string = string> = ComponentType<LayoutProps<TPath>>;
|
|
347
|
+
type ErrorComponent = ComponentType<ErrorProps>;
|
|
348
|
+
type LoadingComponent = ComponentType<LoadingProps>;
|
|
349
|
+
type NotFoundComponent = ComponentType<NotFoundProps>;
|
|
350
|
+
interface IslandConfig {
|
|
351
|
+
name: string;
|
|
352
|
+
component: ComponentType<unknown>;
|
|
353
|
+
props?: Record<string, unknown>;
|
|
354
|
+
hydrate?: 'load' | 'idle' | 'visible' | 'media' | 'interaction';
|
|
355
|
+
media?: string;
|
|
356
|
+
}
|
|
357
|
+
interface IslandManifest {
|
|
358
|
+
islands: Map<string, IslandConfig>;
|
|
359
|
+
}
|
|
360
|
+
interface BuildOptions {
|
|
361
|
+
outDir?: string;
|
|
362
|
+
minify?: boolean;
|
|
363
|
+
sourcemap?: boolean;
|
|
364
|
+
target?: string;
|
|
365
|
+
}
|
|
366
|
+
interface BuildResult {
|
|
367
|
+
success: boolean;
|
|
368
|
+
errors?: string[];
|
|
369
|
+
warnings?: string[];
|
|
370
|
+
duration?: number;
|
|
371
|
+
}
|
|
372
|
+
interface StaticPath {
|
|
373
|
+
params: Record<string, string>;
|
|
374
|
+
}
|
|
375
|
+
interface StaticProps {
|
|
376
|
+
props: Record<string, unknown>;
|
|
377
|
+
revalidate?: number | false;
|
|
378
|
+
notFound?: boolean;
|
|
379
|
+
redirect?: {
|
|
380
|
+
destination: string;
|
|
381
|
+
permanent?: boolean;
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
interface VelixPlugin {
|
|
385
|
+
name: string;
|
|
386
|
+
setup?: (config: VelixConfig) => void | Promise<void>;
|
|
387
|
+
transform?: (code: string, id: string) => string | null | Promise<string | null>;
|
|
388
|
+
buildStart?: () => void | Promise<void>;
|
|
389
|
+
buildEnd?: () => void | Promise<void>;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
declare const RouteType: {
|
|
393
|
+
readonly PAGE: "page";
|
|
394
|
+
readonly API: "api";
|
|
395
|
+
readonly LAYOUT: "layout";
|
|
396
|
+
readonly LOADING: "loading";
|
|
397
|
+
readonly ERROR: "error";
|
|
398
|
+
readonly NOT_FOUND: "not-found";
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Builds the complete route tree from the app/ directory
|
|
402
|
+
*/
|
|
403
|
+
declare function buildRouteTree(appDir: string): {
|
|
404
|
+
pages: Route[];
|
|
405
|
+
api: Route[];
|
|
406
|
+
layouts: Map<string, string>;
|
|
407
|
+
tree: RouteTreeNode;
|
|
408
|
+
appRoutes: Route[];
|
|
409
|
+
rootLayout?: string;
|
|
410
|
+
};
|
|
411
|
+
/**
|
|
412
|
+
* Matches URL path against routes
|
|
413
|
+
*/
|
|
414
|
+
declare function matchRoute(urlPath: string, routes: Route[]): {
|
|
415
|
+
params: Record<string, string>;
|
|
416
|
+
type: RouteType$1;
|
|
417
|
+
path: string;
|
|
418
|
+
filePath: string;
|
|
419
|
+
pattern: RegExp;
|
|
420
|
+
segments: string[];
|
|
421
|
+
layout?: string | null;
|
|
422
|
+
loading?: string | null;
|
|
423
|
+
error?: string | null;
|
|
424
|
+
notFound?: string | null;
|
|
425
|
+
template?: string | null;
|
|
426
|
+
middleware?: string | null;
|
|
427
|
+
isServerComponent?: boolean;
|
|
428
|
+
isClientComponent?: boolean;
|
|
429
|
+
isIsland?: boolean;
|
|
430
|
+
} | null;
|
|
431
|
+
/**
|
|
432
|
+
* Finds all layouts that apply to a route
|
|
433
|
+
*/
|
|
434
|
+
declare function findRouteLayouts(route: Route, layoutsMap: Map<string, string>): Array<{
|
|
435
|
+
name: string;
|
|
436
|
+
filePath: string | undefined;
|
|
437
|
+
}>;
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Velix v5 Logger
|
|
441
|
+
* Minimalist, professional output inspired by modern CLIs
|
|
442
|
+
*/
|
|
443
|
+
declare const logger: {
|
|
444
|
+
logo(): void;
|
|
445
|
+
serverStart(config: {
|
|
446
|
+
port: number | string;
|
|
447
|
+
host: string;
|
|
448
|
+
mode: string;
|
|
449
|
+
pagesDir?: string;
|
|
450
|
+
}, startTime?: number): void;
|
|
451
|
+
request(method: string, path: string, status: number, time: number, extra?: {
|
|
452
|
+
type?: string;
|
|
453
|
+
}): void;
|
|
454
|
+
info(msg: string): void;
|
|
455
|
+
success(msg: string): void;
|
|
456
|
+
warn(msg: string): void;
|
|
457
|
+
error(msg: string, err?: Error | null): void;
|
|
458
|
+
compile(file: string, time: number): void;
|
|
459
|
+
hmr(file: string): void;
|
|
460
|
+
plugin(name: string): void;
|
|
461
|
+
route(path: string, type: string): void;
|
|
462
|
+
divider(): void;
|
|
463
|
+
blank(): void;
|
|
464
|
+
portInUse(port: number | string): void;
|
|
465
|
+
build(stats: {
|
|
466
|
+
time: number;
|
|
467
|
+
}): void;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Velix v5 Metadata & SEO System
|
|
472
|
+
*
|
|
473
|
+
* First-class SEO with automatic:
|
|
474
|
+
* - Meta tags, Open Graph, Twitter Cards
|
|
475
|
+
* - Canonical URLs, robots, sitemaps
|
|
476
|
+
* - JSON-LD structured data
|
|
477
|
+
* - Viewport, theme color, icons
|
|
478
|
+
*/
|
|
479
|
+
interface Metadata {
|
|
480
|
+
title?: string | {
|
|
481
|
+
default: string;
|
|
482
|
+
template?: string;
|
|
483
|
+
absolute?: string;
|
|
484
|
+
};
|
|
485
|
+
description?: string;
|
|
486
|
+
keywords?: string | string[];
|
|
487
|
+
authors?: Author | Author[];
|
|
488
|
+
creator?: string;
|
|
489
|
+
publisher?: string;
|
|
490
|
+
robots?: Robots | string;
|
|
491
|
+
icons?: Icons;
|
|
492
|
+
manifest?: string;
|
|
493
|
+
openGraph?: OpenGraph;
|
|
494
|
+
twitter?: Twitter;
|
|
495
|
+
verification?: Verification;
|
|
496
|
+
alternates?: Alternates;
|
|
497
|
+
viewport?: Viewport | string;
|
|
498
|
+
themeColor?: ThemeColor | ThemeColor[];
|
|
499
|
+
colorScheme?: 'normal' | 'light' | 'dark' | 'light dark' | 'dark light';
|
|
500
|
+
formatDetection?: FormatDetection;
|
|
501
|
+
metadataBase?: URL | string;
|
|
502
|
+
generator?: string;
|
|
503
|
+
applicationName?: string;
|
|
504
|
+
referrer?: string;
|
|
505
|
+
other?: Record<string, string | string[]>;
|
|
506
|
+
}
|
|
507
|
+
interface Author {
|
|
508
|
+
name?: string;
|
|
509
|
+
url?: string;
|
|
510
|
+
}
|
|
511
|
+
interface Robots {
|
|
512
|
+
index?: boolean;
|
|
513
|
+
follow?: boolean;
|
|
514
|
+
noarchive?: boolean;
|
|
515
|
+
nosnippet?: boolean;
|
|
516
|
+
noimageindex?: boolean;
|
|
517
|
+
nocache?: boolean;
|
|
518
|
+
googleBot?: Robots | string;
|
|
519
|
+
}
|
|
520
|
+
interface Icons {
|
|
521
|
+
icon?: IconDescriptor | IconDescriptor[];
|
|
522
|
+
shortcut?: IconDescriptor | IconDescriptor[];
|
|
523
|
+
apple?: IconDescriptor | IconDescriptor[];
|
|
524
|
+
other?: IconDescriptor[];
|
|
525
|
+
}
|
|
526
|
+
interface IconDescriptor {
|
|
527
|
+
url: string;
|
|
528
|
+
type?: string;
|
|
529
|
+
sizes?: string;
|
|
530
|
+
color?: string;
|
|
531
|
+
rel?: string;
|
|
532
|
+
media?: string;
|
|
533
|
+
}
|
|
534
|
+
interface OpenGraph {
|
|
535
|
+
type?: string;
|
|
536
|
+
url?: string;
|
|
537
|
+
title?: string;
|
|
538
|
+
description?: string;
|
|
539
|
+
siteName?: string;
|
|
540
|
+
locale?: string;
|
|
541
|
+
images?: OGImage | OGImage[];
|
|
542
|
+
videos?: OGVideo | OGVideo[];
|
|
543
|
+
determiner?: string;
|
|
544
|
+
publishedTime?: string;
|
|
545
|
+
modifiedTime?: string;
|
|
546
|
+
expirationTime?: string;
|
|
547
|
+
authors?: string | string[];
|
|
548
|
+
section?: string;
|
|
549
|
+
tags?: string[];
|
|
550
|
+
}
|
|
551
|
+
interface OGImage {
|
|
552
|
+
url: string;
|
|
553
|
+
secureUrl?: string;
|
|
554
|
+
type?: string;
|
|
555
|
+
width?: number;
|
|
556
|
+
height?: number;
|
|
557
|
+
alt?: string;
|
|
558
|
+
}
|
|
559
|
+
interface OGVideo {
|
|
560
|
+
url: string;
|
|
561
|
+
secureUrl?: string;
|
|
562
|
+
type?: string;
|
|
563
|
+
width?: number;
|
|
564
|
+
height?: number;
|
|
565
|
+
}
|
|
566
|
+
interface Twitter {
|
|
567
|
+
card?: 'summary' | 'summary_large_image' | 'app' | 'player';
|
|
568
|
+
site?: string;
|
|
569
|
+
siteId?: string;
|
|
570
|
+
creator?: string;
|
|
571
|
+
creatorId?: string;
|
|
572
|
+
title?: string;
|
|
573
|
+
description?: string;
|
|
574
|
+
images?: string | TwitterImage | (string | TwitterImage)[];
|
|
575
|
+
}
|
|
576
|
+
interface TwitterImage {
|
|
577
|
+
url: string;
|
|
578
|
+
alt?: string;
|
|
579
|
+
}
|
|
580
|
+
interface Verification {
|
|
581
|
+
google?: string | string[];
|
|
582
|
+
yahoo?: string | string[];
|
|
583
|
+
yandex?: string | string[];
|
|
584
|
+
other?: Record<string, string | string[]>;
|
|
585
|
+
}
|
|
586
|
+
interface Alternates {
|
|
587
|
+
canonical?: string;
|
|
588
|
+
languages?: Record<string, string>;
|
|
589
|
+
media?: Record<string, string>;
|
|
590
|
+
}
|
|
591
|
+
interface Viewport {
|
|
592
|
+
width?: number | 'device-width';
|
|
593
|
+
height?: number | 'device-height';
|
|
594
|
+
initialScale?: number;
|
|
595
|
+
minimumScale?: number;
|
|
596
|
+
maximumScale?: number;
|
|
597
|
+
userScalable?: boolean;
|
|
598
|
+
viewportFit?: 'auto' | 'cover' | 'contain';
|
|
599
|
+
}
|
|
600
|
+
interface ThemeColor {
|
|
601
|
+
color: string;
|
|
602
|
+
media?: string;
|
|
603
|
+
}
|
|
604
|
+
interface FormatDetection {
|
|
605
|
+
telephone?: boolean;
|
|
606
|
+
date?: boolean;
|
|
607
|
+
address?: boolean;
|
|
608
|
+
email?: boolean;
|
|
609
|
+
}
|
|
610
|
+
declare function generateMetadataTags(metadata: Metadata, baseUrl?: string): string;
|
|
611
|
+
declare function mergeMetadata(parent: Metadata, child: Metadata): Metadata;
|
|
612
|
+
declare function generateJsonLd(data: Record<string, unknown>): string;
|
|
613
|
+
declare const jsonLd: {
|
|
614
|
+
website: (c: {
|
|
615
|
+
name: string;
|
|
616
|
+
url: string;
|
|
617
|
+
description?: string;
|
|
618
|
+
}) => {
|
|
619
|
+
'@context': string;
|
|
620
|
+
'@type': string;
|
|
621
|
+
name: string;
|
|
622
|
+
url: string;
|
|
623
|
+
description: string | undefined;
|
|
624
|
+
};
|
|
625
|
+
article: (c: {
|
|
626
|
+
headline: string;
|
|
627
|
+
description?: string;
|
|
628
|
+
image?: string | string[];
|
|
629
|
+
datePublished: string;
|
|
630
|
+
dateModified?: string;
|
|
631
|
+
author: {
|
|
632
|
+
name: string;
|
|
633
|
+
url?: string;
|
|
634
|
+
} | {
|
|
635
|
+
name: string;
|
|
636
|
+
url?: string;
|
|
637
|
+
}[];
|
|
638
|
+
}) => {
|
|
639
|
+
'@context': string;
|
|
640
|
+
'@type': string;
|
|
641
|
+
headline: string;
|
|
642
|
+
description: string | undefined;
|
|
643
|
+
image: string | string[] | undefined;
|
|
644
|
+
datePublished: string;
|
|
645
|
+
dateModified: string;
|
|
646
|
+
author: {
|
|
647
|
+
name: string;
|
|
648
|
+
url?: string;
|
|
649
|
+
'@type': string;
|
|
650
|
+
}[] | {
|
|
651
|
+
name: string;
|
|
652
|
+
url?: string;
|
|
653
|
+
'@type': string;
|
|
654
|
+
};
|
|
655
|
+
};
|
|
656
|
+
organization: (c: {
|
|
657
|
+
name: string;
|
|
658
|
+
url: string;
|
|
659
|
+
logo?: string;
|
|
660
|
+
sameAs?: string[];
|
|
661
|
+
}) => {
|
|
662
|
+
'@context': string;
|
|
663
|
+
'@type': string;
|
|
664
|
+
name: string;
|
|
665
|
+
url: string;
|
|
666
|
+
logo: string | undefined;
|
|
667
|
+
sameAs: string[] | undefined;
|
|
668
|
+
};
|
|
669
|
+
breadcrumb: (items: {
|
|
670
|
+
name: string;
|
|
671
|
+
url: string;
|
|
672
|
+
}[]) => {
|
|
673
|
+
'@context': string;
|
|
674
|
+
'@type': string;
|
|
675
|
+
itemListElement: {
|
|
676
|
+
'@type': string;
|
|
677
|
+
position: number;
|
|
678
|
+
name: string;
|
|
679
|
+
item: string;
|
|
680
|
+
}[];
|
|
681
|
+
};
|
|
682
|
+
};
|
|
683
|
+
/**
|
|
684
|
+
* Generate sitemap.xml content from routes
|
|
685
|
+
*/
|
|
686
|
+
declare function generateSitemap(routes: Array<{
|
|
687
|
+
type: string;
|
|
688
|
+
path: string;
|
|
689
|
+
}>, baseUrl: string): string;
|
|
690
|
+
/**
|
|
691
|
+
* Generate robots.txt content
|
|
692
|
+
*/
|
|
693
|
+
declare function generateRobotsTxt(baseUrl: string, options?: {
|
|
694
|
+
disallow?: string[];
|
|
695
|
+
allow?: string[];
|
|
696
|
+
}): string;
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Velix v5 Plugin System
|
|
700
|
+
* Extensible hook-based plugin architecture
|
|
701
|
+
*/
|
|
702
|
+
declare const PluginHooks: {
|
|
703
|
+
readonly CONFIG: "config";
|
|
704
|
+
readonly SERVER_START: "server:start";
|
|
705
|
+
readonly REQUEST: "request";
|
|
706
|
+
readonly RESPONSE: "response";
|
|
707
|
+
readonly ROUTES_LOADED: "routes:loaded";
|
|
708
|
+
readonly BEFORE_RENDER: "render:before";
|
|
709
|
+
readonly AFTER_RENDER: "render:after";
|
|
710
|
+
readonly BUILD_START: "build:start";
|
|
711
|
+
readonly BUILD_END: "build:end";
|
|
712
|
+
};
|
|
713
|
+
type PluginHook = typeof PluginHooks[keyof typeof PluginHooks];
|
|
714
|
+
interface PluginHookArgs {
|
|
715
|
+
[PluginHooks.CONFIG]: [config: VelixConfig];
|
|
716
|
+
[PluginHooks.SERVER_START]: [context: {
|
|
717
|
+
config: VelixConfig;
|
|
718
|
+
isDev: boolean;
|
|
719
|
+
projectRoot: string;
|
|
720
|
+
}, isDev: boolean];
|
|
721
|
+
[PluginHooks.REQUEST]: [req: http.IncomingMessage, res: http.ServerResponse];
|
|
722
|
+
[PluginHooks.RESPONSE]: [req: http.IncomingMessage, res: http.ServerResponse, duration: number];
|
|
723
|
+
[PluginHooks.ROUTES_LOADED]: [routes: RouteTree];
|
|
724
|
+
[PluginHooks.BEFORE_RENDER]: [html: string, context: {
|
|
725
|
+
route: Route;
|
|
726
|
+
config: VelixConfig;
|
|
727
|
+
isDev: boolean;
|
|
728
|
+
}];
|
|
729
|
+
[PluginHooks.AFTER_RENDER]: [html: string, context: {
|
|
730
|
+
route: Route;
|
|
731
|
+
config: VelixConfig;
|
|
732
|
+
isDev: boolean;
|
|
733
|
+
}];
|
|
734
|
+
[PluginHooks.BUILD_START]: [];
|
|
735
|
+
[PluginHooks.BUILD_END]: [stats: {
|
|
736
|
+
time: number;
|
|
737
|
+
}];
|
|
738
|
+
}
|
|
739
|
+
interface VelixPluginDefinition {
|
|
740
|
+
name: string;
|
|
741
|
+
version?: string;
|
|
742
|
+
setup?: (config: VelixConfig) => void | Promise<void>;
|
|
743
|
+
hooks?: {
|
|
744
|
+
[K in PluginHook]?: (...args: PluginHookArgs[K]) => unknown;
|
|
745
|
+
};
|
|
746
|
+
[key: string]: unknown;
|
|
747
|
+
}
|
|
748
|
+
declare class PluginManager {
|
|
749
|
+
private plugins;
|
|
750
|
+
private hooks;
|
|
751
|
+
/**
|
|
752
|
+
* Register a plugin
|
|
753
|
+
*/
|
|
754
|
+
register(plugin: VelixPluginDefinition): void;
|
|
755
|
+
/**
|
|
756
|
+
* Run a hook with arguments
|
|
757
|
+
*/
|
|
758
|
+
runHook<K extends PluginHook>(hookName: K, ...args: PluginHookArgs[K]): Promise<void>;
|
|
759
|
+
/**
|
|
760
|
+
* Run a waterfall hook — each handler transforms the first argument
|
|
761
|
+
*/
|
|
762
|
+
runWaterfallHook<K extends PluginHook>(hookName: K, value: PluginHookArgs[K][0], ...args: PluginHookArgs[K] extends [unknown, ...infer Rest] ? Rest : []): Promise<PluginHookArgs[K][0]>;
|
|
763
|
+
/**
|
|
764
|
+
* Get all registered plugins
|
|
765
|
+
*/
|
|
766
|
+
getPlugins(): VelixPluginDefinition[];
|
|
767
|
+
/**
|
|
768
|
+
* Check if a plugin is registered
|
|
769
|
+
*/
|
|
770
|
+
hasPlugin(name: string): boolean;
|
|
771
|
+
}
|
|
772
|
+
declare const pluginManager: PluginManager;
|
|
773
|
+
/**
|
|
774
|
+
* Load plugins from project configuration
|
|
775
|
+
*/
|
|
776
|
+
declare function loadPlugins(projectRoot: string, config: {
|
|
777
|
+
plugins?: unknown[];
|
|
778
|
+
}): Promise<void>;
|
|
779
|
+
/**
|
|
780
|
+
* Helper to define a Velix plugin with type safety.
|
|
781
|
+
*
|
|
782
|
+
* @example
|
|
783
|
+
* ```ts
|
|
784
|
+
* export default definePlugin({
|
|
785
|
+
* name: 'my-plugin',
|
|
786
|
+
* hooks: {
|
|
787
|
+
* 'server:start': (server) => {
|
|
788
|
+
* console.log('Server started!');
|
|
789
|
+
* }
|
|
790
|
+
* }
|
|
791
|
+
* });
|
|
792
|
+
* ```
|
|
793
|
+
*/
|
|
794
|
+
declare function definePlugin(definition: VelixPluginDefinition): VelixPluginDefinition;
|
|
795
|
+
declare const builtinPlugins: {
|
|
796
|
+
/**
|
|
797
|
+
* Security headers plugin
|
|
798
|
+
*/
|
|
799
|
+
security: VelixPluginDefinition;
|
|
800
|
+
/**
|
|
801
|
+
* Request logging plugin
|
|
802
|
+
*/
|
|
803
|
+
logger: VelixPluginDefinition;
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
interface TailwindPluginOptions {
|
|
807
|
+
input?: string;
|
|
808
|
+
output?: string;
|
|
809
|
+
config?: string;
|
|
810
|
+
minify?: boolean;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Velix AI Plugin - Type Definitions
|
|
815
|
+
* @module velix-plugin-ai/types
|
|
816
|
+
*/
|
|
817
|
+
/**
|
|
818
|
+
* Supported AI providers
|
|
819
|
+
*/
|
|
820
|
+
type AIProviderType = 'openai' | 'ollama' | 'anthropic';
|
|
821
|
+
/**
|
|
822
|
+
* AI input configuration
|
|
823
|
+
*/
|
|
824
|
+
interface AIInput {
|
|
825
|
+
/** The prompt or message to send to the AI */
|
|
826
|
+
prompt: string;
|
|
827
|
+
/** System message for context */
|
|
828
|
+
system?: string;
|
|
829
|
+
/** Model to use (provider-specific) */
|
|
830
|
+
model?: string;
|
|
831
|
+
/** Temperature for randomness (0-1) */
|
|
832
|
+
temperature?: number;
|
|
833
|
+
/** Maximum tokens to generate */
|
|
834
|
+
maxTokens?: number;
|
|
835
|
+
/** Stop sequences */
|
|
836
|
+
stop?: string[];
|
|
837
|
+
/** Additional provider-specific options */
|
|
838
|
+
options?: Record<string, unknown>;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Chat message
|
|
842
|
+
*/
|
|
843
|
+
interface ChatMessage {
|
|
844
|
+
role: 'system' | 'user' | 'assistant';
|
|
845
|
+
content: string;
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Chat input configuration
|
|
849
|
+
*/
|
|
850
|
+
interface ChatInput {
|
|
851
|
+
/** Array of chat messages */
|
|
852
|
+
messages: ChatMessage[];
|
|
853
|
+
/** Model to use */
|
|
854
|
+
model?: string;
|
|
855
|
+
/** Temperature for randomness (0-1) */
|
|
856
|
+
temperature?: number;
|
|
857
|
+
/** Maximum tokens to generate */
|
|
858
|
+
maxTokens?: number;
|
|
859
|
+
/** Stop sequences */
|
|
860
|
+
stop?: string[];
|
|
861
|
+
/** Additional provider-specific options */
|
|
862
|
+
options?: Record<string, unknown>;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* AI response
|
|
866
|
+
*/
|
|
867
|
+
interface AIResponse {
|
|
868
|
+
/** Generated text */
|
|
869
|
+
text: string;
|
|
870
|
+
/** Provider that generated the response */
|
|
871
|
+
provider: AIProviderType;
|
|
872
|
+
/** Model used */
|
|
873
|
+
model: string;
|
|
874
|
+
/** Token usage information */
|
|
875
|
+
usage?: {
|
|
876
|
+
promptTokens: number;
|
|
877
|
+
completionTokens: number;
|
|
878
|
+
totalTokens: number;
|
|
879
|
+
};
|
|
880
|
+
/** Raw provider response */
|
|
881
|
+
raw?: unknown;
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Stream chunk
|
|
885
|
+
*/
|
|
886
|
+
interface AIStreamChunk {
|
|
887
|
+
/** Chunk of generated text */
|
|
888
|
+
text: string;
|
|
889
|
+
/** Whether this is the final chunk */
|
|
890
|
+
done: boolean;
|
|
891
|
+
/** Provider that generated the chunk */
|
|
892
|
+
provider?: AIProviderType;
|
|
893
|
+
/** Model used */
|
|
894
|
+
model?: string;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Embedding input
|
|
898
|
+
*/
|
|
899
|
+
interface EmbedInput {
|
|
900
|
+
/** Text to embed */
|
|
901
|
+
text: string;
|
|
902
|
+
/** Model to use for embeddings */
|
|
903
|
+
model?: string;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Embedding response
|
|
907
|
+
*/
|
|
908
|
+
interface EmbedResponse {
|
|
909
|
+
/** Embedding vector */
|
|
910
|
+
embedding: number[];
|
|
911
|
+
/** Provider that generated the embedding */
|
|
912
|
+
provider: AIProviderType;
|
|
913
|
+
/** Model used */
|
|
914
|
+
model: string;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* AI Provider interface
|
|
918
|
+
*/
|
|
919
|
+
interface AIProvider {
|
|
920
|
+
/** Provider name */
|
|
921
|
+
name: AIProviderType;
|
|
922
|
+
/** Generate text from a prompt */
|
|
923
|
+
generate(input: AIInput): Promise<AIResponse>;
|
|
924
|
+
/** Chat with messages */
|
|
925
|
+
chat(input: ChatInput): Promise<AIResponse>;
|
|
926
|
+
/** Stream text generation */
|
|
927
|
+
stream(input: AIInput): AsyncIterable<AIStreamChunk>;
|
|
928
|
+
/** Generate embeddings */
|
|
929
|
+
embed(input: EmbedInput): Promise<EmbedResponse>;
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* AI Plugin configuration
|
|
933
|
+
*/
|
|
934
|
+
interface AIPluginConfig {
|
|
935
|
+
/** Provider to use */
|
|
936
|
+
provider: AIProviderType;
|
|
937
|
+
/** API key (for cloud providers) */
|
|
938
|
+
apiKey?: string;
|
|
939
|
+
/** Base URL (for custom endpoints) */
|
|
940
|
+
baseUrl?: string;
|
|
941
|
+
/** Default model */
|
|
942
|
+
defaultModel?: string;
|
|
943
|
+
/** Default temperature */
|
|
944
|
+
defaultTemperature?: number;
|
|
945
|
+
/** Retry configuration */
|
|
946
|
+
retry?: {
|
|
947
|
+
maxRetries: number;
|
|
948
|
+
retryDelay: number;
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* AI Client interface
|
|
953
|
+
*/
|
|
954
|
+
interface AIClient {
|
|
955
|
+
/** Generate text from a prompt */
|
|
956
|
+
generate(input: AIInput): Promise<AIResponse>;
|
|
957
|
+
/** Chat with messages */
|
|
958
|
+
chat(input: ChatInput): Promise<AIResponse>;
|
|
959
|
+
/** Stream text generation */
|
|
960
|
+
stream(input: AIInput): AsyncIterable<AIStreamChunk>;
|
|
961
|
+
/** Generate embeddings */
|
|
962
|
+
embed(input: EmbedInput): Promise<EmbedResponse>;
|
|
963
|
+
/** Get current provider */
|
|
964
|
+
getProvider(): AIProvider;
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Action AI configuration
|
|
968
|
+
*/
|
|
969
|
+
interface ActionAIConfig<TInput = unknown> {
|
|
970
|
+
/** Input schema */
|
|
971
|
+
input: TInput;
|
|
972
|
+
/** Prompt builder function */
|
|
973
|
+
prompt: (input: TInput) => string;
|
|
974
|
+
/** System message */
|
|
975
|
+
system?: string;
|
|
976
|
+
/** Model to use */
|
|
977
|
+
model?: string;
|
|
978
|
+
/** Temperature */
|
|
979
|
+
temperature?: number;
|
|
980
|
+
/** Post-processing function */
|
|
981
|
+
transform?: (response: string) => unknown;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Velix AI Plugin - Utilities
|
|
986
|
+
* @module velix-plugin-ai/utils
|
|
987
|
+
*/
|
|
988
|
+
/**
|
|
989
|
+
* Retry a function with exponential backoff
|
|
990
|
+
*/
|
|
991
|
+
declare function retry<T>(fn: () => Promise<T>, options?: {
|
|
992
|
+
maxRetries: number;
|
|
993
|
+
retryDelay: number;
|
|
994
|
+
}): Promise<T>;
|
|
995
|
+
/**
|
|
996
|
+
* Safe JSON parsing with fallback
|
|
997
|
+
*/
|
|
998
|
+
declare function safeJsonParse<T = unknown>(text: string, fallback?: T): T | null;
|
|
999
|
+
/**
|
|
1000
|
+
* Build a prompt from a template
|
|
1001
|
+
*/
|
|
1002
|
+
declare function buildPrompt(template: string, variables: Record<string, unknown>): string;
|
|
1003
|
+
/**
|
|
1004
|
+
* Validate API key
|
|
1005
|
+
*/
|
|
1006
|
+
declare function validateApiKey(apiKey: string | undefined, provider: string): void;
|
|
1007
|
+
/**
|
|
1008
|
+
* Validate input
|
|
1009
|
+
*/
|
|
1010
|
+
declare function validateInput(input: Record<string, unknown>, requiredFields: string[]): void;
|
|
1011
|
+
/**
|
|
1012
|
+
* Create a streaming text decoder
|
|
1013
|
+
*/
|
|
1014
|
+
declare function createStreamDecoder(): (chunk: Uint8Array) => string;
|
|
1015
|
+
/**
|
|
1016
|
+
* Parse SSE (Server-Sent Events) data
|
|
1017
|
+
*/
|
|
1018
|
+
declare function parseSSE(line: string): unknown;
|
|
1019
|
+
/**
|
|
1020
|
+
* Sanitize input text
|
|
1021
|
+
*/
|
|
1022
|
+
declare function sanitizeInput(text: string): string;
|
|
1023
|
+
/**
|
|
1024
|
+
* Count tokens (rough estimation)
|
|
1025
|
+
*/
|
|
1026
|
+
declare function estimateTokens(text: string): number;
|
|
1027
|
+
/**
|
|
1028
|
+
* Truncate text to max tokens
|
|
1029
|
+
*/
|
|
1030
|
+
declare function truncateToTokens(text: string, maxTokens: number): string;
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Velix AI Plugin - OpenAI Provider
|
|
1034
|
+
* @module velix-plugin-ai/providers/openai
|
|
1035
|
+
*/
|
|
1036
|
+
|
|
1037
|
+
interface OpenAIConfig {
|
|
1038
|
+
apiKey: string;
|
|
1039
|
+
baseUrl?: string;
|
|
1040
|
+
defaultModel?: string;
|
|
1041
|
+
organization?: string;
|
|
1042
|
+
retry?: {
|
|
1043
|
+
maxRetries: number;
|
|
1044
|
+
retryDelay: number;
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
declare class OpenAIProvider implements AIProvider {
|
|
1048
|
+
name: "openai";
|
|
1049
|
+
private apiKey;
|
|
1050
|
+
private baseUrl;
|
|
1051
|
+
private defaultModel;
|
|
1052
|
+
private organization?;
|
|
1053
|
+
private retryConfig;
|
|
1054
|
+
constructor(config: OpenAIConfig);
|
|
1055
|
+
generate(input: AIInput): Promise<AIResponse>;
|
|
1056
|
+
chat(input: ChatInput): Promise<AIResponse>;
|
|
1057
|
+
stream(input: AIInput): AsyncIterable<AIStreamChunk>;
|
|
1058
|
+
embed(input: EmbedInput): Promise<EmbedResponse>;
|
|
1059
|
+
private getHeaders;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* Velix AI Plugin - Ollama Provider
|
|
1064
|
+
* @module velix-plugin-ai/providers/ollama
|
|
1065
|
+
*/
|
|
1066
|
+
|
|
1067
|
+
interface OllamaConfig {
|
|
1068
|
+
baseUrl?: string;
|
|
1069
|
+
defaultModel?: string;
|
|
1070
|
+
retry?: {
|
|
1071
|
+
maxRetries: number;
|
|
1072
|
+
retryDelay: number;
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
declare class OllamaProvider implements AIProvider {
|
|
1076
|
+
name: "ollama";
|
|
1077
|
+
private baseUrl;
|
|
1078
|
+
private defaultModel;
|
|
1079
|
+
private retryConfig;
|
|
1080
|
+
constructor(config?: OllamaConfig);
|
|
1081
|
+
generate(input: AIInput): Promise<AIResponse>;
|
|
1082
|
+
chat(input: ChatInput): Promise<AIResponse>;
|
|
1083
|
+
stream(input: AIInput): AsyncIterable<AIStreamChunk>;
|
|
1084
|
+
embed(input: EmbedInput): Promise<EmbedResponse>;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* Velix AI Plugin - AI Client
|
|
1089
|
+
* @module velix-plugin-ai/client
|
|
1090
|
+
*/
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Create an AI client
|
|
1094
|
+
*/
|
|
1095
|
+
declare function createAIClient(config: AIPluginConfig): AIClient;
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Velix AI Plugin v1
|
|
1099
|
+
* @module velix-plugin-ai
|
|
1100
|
+
*/
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* Get AI client in server actions
|
|
1104
|
+
*/
|
|
1105
|
+
declare function useAI(): AIClient;
|
|
1106
|
+
/**
|
|
1107
|
+
* Create an AI-powered server action
|
|
1108
|
+
*
|
|
1109
|
+
* @example
|
|
1110
|
+
* ```ts
|
|
1111
|
+
* export const summarize = createAIAction({
|
|
1112
|
+
* input: { text: 'string' },
|
|
1113
|
+
* prompt: ({ text }) => `Summarize this text: ${text}`,
|
|
1114
|
+
* system: 'You are a helpful assistant that summarizes text concisely.'
|
|
1115
|
+
* });
|
|
1116
|
+
* ```
|
|
1117
|
+
*/
|
|
1118
|
+
declare function createAIAction<TInput = unknown, TOutput = string>(config: {
|
|
1119
|
+
input: TInput;
|
|
1120
|
+
prompt: (input: TInput) => string;
|
|
1121
|
+
system?: string;
|
|
1122
|
+
model?: string;
|
|
1123
|
+
temperature?: number;
|
|
1124
|
+
transform?: (response: string) => TOutput;
|
|
1125
|
+
}): (input: TInput) => Promise<TOutput>;
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
* Velix v5 Utility Functions
|
|
1129
|
+
*/
|
|
1130
|
+
/**
|
|
1131
|
+
* Generates a unique hash for cache busting
|
|
1132
|
+
*/
|
|
1133
|
+
declare function generateHash(content: string): string;
|
|
1134
|
+
/**
|
|
1135
|
+
* Escapes HTML special characters
|
|
1136
|
+
*/
|
|
1137
|
+
declare function escapeHtml(str: string): string;
|
|
1138
|
+
/**
|
|
1139
|
+
* Recursively finds all files matching a pattern
|
|
1140
|
+
*/
|
|
1141
|
+
declare function findFiles(dir: string, pattern: RegExp, files?: string[]): string[];
|
|
1142
|
+
/**
|
|
1143
|
+
* Ensures a directory exists
|
|
1144
|
+
*/
|
|
1145
|
+
declare function ensureDir(dir: string): void;
|
|
1146
|
+
/**
|
|
1147
|
+
* Cleans a directory
|
|
1148
|
+
*/
|
|
1149
|
+
declare function cleanDir(dir: string): void;
|
|
1150
|
+
/**
|
|
1151
|
+
* Copies a directory recursively
|
|
1152
|
+
*/
|
|
1153
|
+
declare function copyDir(src: string, dest: string): void;
|
|
1154
|
+
/**
|
|
1155
|
+
* Debounce function for file watching
|
|
1156
|
+
*/
|
|
1157
|
+
declare function debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
1158
|
+
/**
|
|
1159
|
+
* Formats bytes to human-readable string
|
|
1160
|
+
*/
|
|
1161
|
+
declare function formatBytes(bytes: number): string;
|
|
1162
|
+
/**
|
|
1163
|
+
* Formats milliseconds to human-readable string
|
|
1164
|
+
*/
|
|
1165
|
+
declare function formatTime(ms: number): string;
|
|
1166
|
+
/**
|
|
1167
|
+
* Creates a deferred promise
|
|
1168
|
+
*/
|
|
1169
|
+
declare function createDeferred<T>(): {
|
|
1170
|
+
promise: Promise<T>;
|
|
1171
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
1172
|
+
reject: (reason?: unknown) => void;
|
|
1173
|
+
};
|
|
1174
|
+
/**
|
|
1175
|
+
* Sleep utility
|
|
1176
|
+
*/
|
|
1177
|
+
declare function sleep(ms: number): Promise<void>;
|
|
1178
|
+
/**
|
|
1179
|
+
* Check if a file is a server component (has 'use server' directive)
|
|
1180
|
+
*/
|
|
1181
|
+
declare function isServerComponent(filePath: string): boolean;
|
|
1182
|
+
/**
|
|
1183
|
+
* Check if a file is a client component (has 'use client' directive)
|
|
1184
|
+
*/
|
|
1185
|
+
declare function isClientComponent(filePath: string): boolean;
|
|
1186
|
+
/**
|
|
1187
|
+
* Check if a component is an island (has 'use island' directive)
|
|
1188
|
+
*/
|
|
1189
|
+
declare function isIsland(filePath: string): boolean;
|
|
1190
|
+
|
|
1191
|
+
/**
|
|
1192
|
+
* Velix v5 — Advanced Cache (VelixCache)
|
|
1193
|
+
*
|
|
1194
|
+
* Production-grade caching with:
|
|
1195
|
+
* - LRU eviction (configurable maxSize)
|
|
1196
|
+
* - TTL-based expiration
|
|
1197
|
+
* - Stale-while-revalidate (SWR) window
|
|
1198
|
+
* - Tag-based invalidation
|
|
1199
|
+
* - Type-safe generics
|
|
1200
|
+
*/
|
|
1201
|
+
type RevalidationType = 'path' | 'tag' | 'layout';
|
|
1202
|
+
interface CacheOptions {
|
|
1203
|
+
/** Time-to-live in milliseconds */
|
|
1204
|
+
ttl?: number;
|
|
1205
|
+
/** Stale-while-revalidate window in milliseconds (after TTL expires) */
|
|
1206
|
+
swr?: number;
|
|
1207
|
+
/** Tags for group invalidation */
|
|
1208
|
+
tags?: string[];
|
|
1209
|
+
}
|
|
1210
|
+
interface VelixCacheConfig {
|
|
1211
|
+
/** Maximum number of entries (default: 1000) */
|
|
1212
|
+
maxSize?: number;
|
|
1213
|
+
/** Default TTL in ms (default: 60_000 — 1 minute) */
|
|
1214
|
+
defaultTtl?: number;
|
|
1215
|
+
/** Default SWR window in ms (default: 10_000 — 10 seconds) */
|
|
1216
|
+
defaultSwr?: number;
|
|
1217
|
+
}
|
|
1218
|
+
declare class VelixCache {
|
|
1219
|
+
private readonly maxSize;
|
|
1220
|
+
private readonly defaultTtl;
|
|
1221
|
+
private readonly defaultSwr;
|
|
1222
|
+
private readonly store;
|
|
1223
|
+
private readonly tagIndex;
|
|
1224
|
+
private readonly head;
|
|
1225
|
+
private readonly tail;
|
|
1226
|
+
constructor(config?: VelixCacheConfig);
|
|
1227
|
+
/** Current number of entries */
|
|
1228
|
+
get size(): number;
|
|
1229
|
+
/**
|
|
1230
|
+
* Store a value with optional TTL, SWR, and tags.
|
|
1231
|
+
*/
|
|
1232
|
+
set<T>(key: string, value: T, options?: CacheOptions): void;
|
|
1233
|
+
/**
|
|
1234
|
+
* Get a cached value. Returns `null` if not found or expired beyond SWR window.
|
|
1235
|
+
*
|
|
1236
|
+
* @returns `{ value, stale }` — `stale` is true when the entry is past TTL but within SWR window.
|
|
1237
|
+
*/
|
|
1238
|
+
get<T>(key: string): {
|
|
1239
|
+
value: T;
|
|
1240
|
+
stale: boolean;
|
|
1241
|
+
} | null;
|
|
1242
|
+
/**
|
|
1243
|
+
* Simple get that returns only the value (ignoring staleness).
|
|
1244
|
+
* Returns `null` if not found or expired.
|
|
1245
|
+
*/
|
|
1246
|
+
getValue<T>(key: string): T | null;
|
|
1247
|
+
/** Check whether a key exists and is not expired */
|
|
1248
|
+
has(key: string): boolean;
|
|
1249
|
+
/** Remove a specific key */
|
|
1250
|
+
delete(key: string): boolean;
|
|
1251
|
+
/** Invalidate a specific path/key */
|
|
1252
|
+
revalidatePath(path: string): void;
|
|
1253
|
+
/** Invalidate all entries associated with a tag */
|
|
1254
|
+
revalidateTag(tag: string): void;
|
|
1255
|
+
/** Clear all entries */
|
|
1256
|
+
invalidateAll(): void;
|
|
1257
|
+
/** Get cache stats for debugging/monitoring */
|
|
1258
|
+
stats(): {
|
|
1259
|
+
size: number;
|
|
1260
|
+
maxSize: number;
|
|
1261
|
+
tags: number;
|
|
1262
|
+
};
|
|
1263
|
+
private createSentinel;
|
|
1264
|
+
private addToHead;
|
|
1265
|
+
private removeFromList;
|
|
1266
|
+
private moveToHead;
|
|
1267
|
+
private evictLRU;
|
|
1268
|
+
private removeEntry;
|
|
1269
|
+
}
|
|
1270
|
+
declare const cacheManager: VelixCache;
|
|
1271
|
+
/**
|
|
1272
|
+
* Revalidate a specific path
|
|
1273
|
+
* @example
|
|
1274
|
+
* ```ts
|
|
1275
|
+
* import { revalidatePath } from 'velix/actions';
|
|
1276
|
+
*
|
|
1277
|
+
* await revalidatePath('/blog');
|
|
1278
|
+
* await revalidatePath('/blog/[slug]', 'layout');
|
|
1279
|
+
* ```
|
|
1280
|
+
*/
|
|
1281
|
+
declare function revalidatePath(path: string, _type?: RevalidationType): void;
|
|
1282
|
+
/**
|
|
1283
|
+
* Revalidate all paths with a specific cache tag
|
|
1284
|
+
* @example
|
|
1285
|
+
* ```ts
|
|
1286
|
+
* import { revalidateTag } from 'velix/actions';
|
|
1287
|
+
*
|
|
1288
|
+
* await revalidateTag('blog-posts');
|
|
1289
|
+
* ```
|
|
1290
|
+
*/
|
|
1291
|
+
declare function revalidateTag(tag: string): void;
|
|
1292
|
+
/**
|
|
1293
|
+
* Unstable cache wrapper (experimental)
|
|
1294
|
+
*/
|
|
1295
|
+
declare function unstable_cache<T>(fn: () => Promise<T>, keys: string[], options?: {
|
|
1296
|
+
tags?: string[];
|
|
1297
|
+
revalidate?: number;
|
|
1298
|
+
}): () => Promise<T>;
|
|
1299
|
+
|
|
1300
|
+
export { type AIClient, type AIInput, type AIPluginConfig, type AIProvider, type AIProviderType, type AIResponse, type AIStreamChunk, type ActionAIConfig, type ActionState, type Alternates, type ApiHandler, type Author, type BuildOptions, type BuildResult, type CacheOptions, type ChatInput, type ChatMessage, type EmbedInput, type EmbedResponse, type ErrorComponent, type ErrorProps, type FormatDetection, type IconDescriptor, type Icons, type IslandConfig, type IslandManifest, type LayoutComponent, type LayoutProps, type LoadingComponent, type LoadingProps, type Metadata, type Middleware, type MiddlewareFunction, type MiddlewareRequest, type MiddlewareResponse, type MiddlewareResult, type NextFunction, type NotFoundComponent, type NotFoundProps, type OGImage, type OGVideo, OllamaProvider, OpenAIProvider, type OpenGraph, type PageComponent, type PageProps, type PluginHook, type PluginHookArgs, PluginHooks, PluginManager, type RevalidationType, type Robots, type Route, type RouteMatch, type RouteTree, RouteType, type ServerAction, type StaticPath, type StaticProps, type TailwindPluginOptions, type ThemeColor, type Twitter, type TwitterImage, type TypedActionResult, VelixCache, type VelixConfig, VelixConfigSchema, type VelixPlugin, type VelixPluginDefinition, type Verification, type Viewport, buildPrompt, buildRouteTree, builtinPlugins, cacheManager, cleanDir, composeMiddleware, copyDir, createAIAction, createAIClient, createDeferred, createStreamDecoder, debounce, defaultConfig, defineConfig, definePlugin, ensureDir, escapeHtml, estimateTokens, findFiles, findRouteLayouts, formatBytes, formatTime, generateHash, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, isClientComponent, isIsland, isServerComponent, jsonLd, loadConfig, loadMiddleware, loadPlugins, logger, matchRoute, mergeMetadata, middlewares, parseSSE, pluginManager, resolvePaths, retry, revalidatePath, revalidateTag, runMiddleware, safeJsonParse, sanitizeInput, sleep, truncateToTokens, unstable_cache, useAI, validateApiKey, validateInput };
|