weifuwu 0.30.0 → 0.30.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/README.md +115 -203
- package/dist/core/router.d.ts +21 -58
- package/dist/core/serve.d.ts +0 -4
- package/dist/core/ws.d.ts +28 -0
- package/dist/index.d.ts +2 -24
- package/dist/index.js +396 -1880
- package/dist/queue/index.d.ts +10 -0
- package/dist/queue/types.d.ts +5 -9
- package/package.json +4 -5
- package/dist/ai/provider.d.ts +0 -45
- package/dist/ai/stream.d.ts +0 -13
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -178
- package/dist/core/cookie.d.ts +0 -36
- package/dist/core/env.d.ts +0 -69
- package/dist/core/html.d.ts +0 -34
- package/dist/core/sse.d.ts +0 -47
- package/dist/middleware/csrf.d.ts +0 -31
- package/dist/middleware/flash.d.ts +0 -44
- package/dist/middleware/health.d.ts +0 -24
- package/dist/middleware/i18n.d.ts +0 -39
- package/dist/middleware/request-id.d.ts +0 -40
- package/dist/middleware/theme.d.ts +0 -31
- package/dist/middleware/validate.d.ts +0 -32
- package/dist/react/index.js +0 -2573
- package/dist/test/test-utils.d.ts +0 -193
package/dist/queue/index.d.ts
CHANGED
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis-backed job queue with cron scheduling.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* const q = queue({ url: process.env.REDIS_URL })
|
|
6
|
+
* q.process('email', async (job) => { await send(job.data) })
|
|
7
|
+
* await q.add('email', { to: '...' })
|
|
8
|
+
* q.cron('cleanup', '0 3 * * *', async () => { ... })
|
|
9
|
+
* await q.run()
|
|
10
|
+
*/
|
|
1
11
|
import type { Queue, QueueOptions } from './types.ts';
|
|
2
12
|
export declare function queue(opts?: QueueOptions): Queue;
|
package/dist/queue/types.d.ts
CHANGED
|
@@ -13,16 +13,14 @@ export interface QueueJob<T = unknown> {
|
|
|
13
13
|
schedule?: string;
|
|
14
14
|
}
|
|
15
15
|
export interface QueueOptions {
|
|
16
|
-
/**
|
|
17
|
-
store?: 'memory' | 'pg' | 'redis';
|
|
16
|
+
/** Redis client instance (auto-created if not provided). */
|
|
18
17
|
redis?: Redis;
|
|
18
|
+
/** Redis URL (default: REDIS_URL env or redis://localhost:6379). */
|
|
19
19
|
url?: string;
|
|
20
|
+
/** Key prefix (default: 'queue'). */
|
|
20
21
|
prefix?: string;
|
|
22
|
+
/** Poll interval in ms (default: 200). */
|
|
21
23
|
pollInterval?: number;
|
|
22
|
-
/** PostgreSQL client (required when store: 'pg'). */
|
|
23
|
-
pg?: {
|
|
24
|
-
sql: import('../types.ts').SqlClient;
|
|
25
|
-
};
|
|
26
24
|
}
|
|
27
25
|
export interface QueueInjected {
|
|
28
26
|
queue: Queue;
|
|
@@ -32,7 +30,7 @@ export interface QueueJobWithError<T = unknown> extends QueueJob<T> {
|
|
|
32
30
|
failedAt: number;
|
|
33
31
|
}
|
|
34
32
|
export interface Queue extends Middleware<Context, Context & QueueInjected>, Closeable {
|
|
35
|
-
/** Register a cron job.
|
|
33
|
+
/** Register a cron job. */
|
|
36
34
|
cron(pattern: string, handler: () => void | Promise<void>): {
|
|
37
35
|
stop: () => void;
|
|
38
36
|
};
|
|
@@ -55,7 +53,5 @@ export interface Queue extends Middleware<Context, Context & QueueInjected>, Clo
|
|
|
55
53
|
retryFailed(jobId: string): Promise<boolean>;
|
|
56
54
|
retryAllFailed(type?: string): Promise<number>;
|
|
57
55
|
dashboard(): import('../core/router.ts').Router;
|
|
58
|
-
/** Create the jobs table (PG mode only; safe to call multiple times). */
|
|
59
|
-
migrate?(): Promise<void>;
|
|
60
56
|
close(): Promise<void>;
|
|
61
57
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "weifuwu",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.30.
|
|
4
|
+
"version": "0.30.2",
|
|
5
5
|
"description": "Web-standard HTTP microframework for Node.js — (req, ctx) => Response",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"build": "node scripts/build.mjs",
|
|
18
18
|
"prepublishOnly": "npm run build && tsc --emitDeclarationOnly --outdir dist",
|
|
19
19
|
"typecheck": "tsc --noEmit",
|
|
20
|
-
"
|
|
21
|
-
"test
|
|
20
|
+
"pretest": "docker compose up -d --wait 2>/dev/null; sleep 1",
|
|
21
|
+
"test": "node --env-file=.env --test 'src/test/**/*.test.ts'",
|
|
22
22
|
"release": "node scripts/release.mjs",
|
|
23
23
|
"release:dry": "node scripts/release.mjs --dry-run"
|
|
24
24
|
},
|
|
@@ -27,8 +27,7 @@
|
|
|
27
27
|
"graphql": "^16",
|
|
28
28
|
"ioredis": "^5.11.0",
|
|
29
29
|
"postgres": "^3.4.9",
|
|
30
|
-
"ws": "^8"
|
|
31
|
-
"zod": "^4.4.3"
|
|
30
|
+
"ws": "^8"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
33
|
"@types/node": "^25",
|
package/dist/ai/provider.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { Context, Middleware } from '../types.ts';
|
|
2
|
-
import { generateText as aiGenerateText, streamText as aiStreamText, type LanguageModel, type EmbeddingModel } from 'ai';
|
|
3
|
-
declare module '../types.ts' {
|
|
4
|
-
interface Context {
|
|
5
|
-
ai: AIProvider;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export interface AIProviderInjected {
|
|
9
|
-
ai: AIProvider;
|
|
10
|
-
}
|
|
11
|
-
export interface AIProviderOptions {
|
|
12
|
-
/** API base URL (default: OPENAI_BASE_URL env or http://localhost:11434/v1). */
|
|
13
|
-
baseURL?: string;
|
|
14
|
-
/** API key (default: OPENAI_API_KEY env or 'ollama'). */
|
|
15
|
-
apiKey?: string;
|
|
16
|
-
/** Chat model name (default: OPENAI_MODEL env or 'qwen3:0.6b'). */
|
|
17
|
-
model?: string;
|
|
18
|
-
/** Embedding model name (default: OPENAI_EMBEDDING_MODEL env or 'qwen3-embedding:0.6b'). */
|
|
19
|
-
embeddingModel?: string;
|
|
20
|
-
/** Vector dimension (default: EMBEDDING_DIMENSION env or 1024). */
|
|
21
|
-
embeddingDimension?: number;
|
|
22
|
-
}
|
|
23
|
-
export interface AIProvider {
|
|
24
|
-
/** Get the language model. Caches by default; pass a name to override. */
|
|
25
|
-
model(name?: string): LanguageModel;
|
|
26
|
-
/** Get the embedding model. Caches by default; pass a name to override. */
|
|
27
|
-
embeddingModel(name?: string): EmbeddingModel;
|
|
28
|
-
/** Embed a single text string into a vector. */
|
|
29
|
-
embed(text: string): Promise<number[]>;
|
|
30
|
-
/** Embed multiple text strings in batch. */
|
|
31
|
-
embedMany(texts: string[]): Promise<number[][]>;
|
|
32
|
-
/** The configured vector dimension. */
|
|
33
|
-
readonly dimension: number;
|
|
34
|
-
/**
|
|
35
|
-
* Generate text using the configured model.
|
|
36
|
-
* All options are passed through to the AI SDK's `generateText`, with `model` auto-injected.
|
|
37
|
-
*/
|
|
38
|
-
generateText(params: Omit<Parameters<typeof aiGenerateText>[0], 'model'>): ReturnType<typeof aiGenerateText>;
|
|
39
|
-
/**
|
|
40
|
-
* Stream text using the configured model.
|
|
41
|
-
* All options are passed through to the AI SDK's `streamText`, with `model` auto-injected.
|
|
42
|
-
*/
|
|
43
|
-
streamText(params: Omit<Parameters<typeof aiStreamText>[0], 'model'>): ReturnType<typeof aiStreamText>;
|
|
44
|
-
}
|
|
45
|
-
export declare function aiProvider(options?: AIProviderOptions): Middleware<Context, Context & AIProviderInjected> & AIProvider;
|
package/dist/ai/stream.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Context } from '../types.ts';
|
|
2
|
-
import { Router } from '../core/router.ts';
|
|
3
|
-
import type { AIProvider } from './provider.ts';
|
|
4
|
-
export type AIHandler = (req: Request, ctx: Context) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
5
|
-
export declare const _ai: Record<string, any>;
|
|
6
|
-
/**
|
|
7
|
-
* Create a streaming AI endpoint.
|
|
8
|
-
*
|
|
9
|
-
* @param handler - Returns options for `streamText` or `streamObject` (if `schema` is present).
|
|
10
|
-
* @param provider - Optional AI provider. If provided and the handler does not return a `model`,
|
|
11
|
-
* `provider.model()` is used as the default.
|
|
12
|
-
*/
|
|
13
|
-
export declare function aiStream(handler: AIHandler, provider?: AIProvider): Promise<Router>;
|
package/dist/cli.d.ts
DELETED
package/dist/cli.js
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// cli.ts
|
|
4
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
5
|
-
import { existsSync } from "node:fs";
|
|
6
|
-
import { execSync } from "node:child_process";
|
|
7
|
-
import { join, dirname, resolve } from "node:path";
|
|
8
|
-
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { parseArgs } from "node:util";
|
|
10
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
var __dirname = dirname(__filename);
|
|
12
|
-
var pkgRoot = existsSync(join(__dirname, "package.json")) ? __dirname : resolve(__dirname, "..");
|
|
13
|
-
async function readPkg() {
|
|
14
|
-
return JSON.parse(
|
|
15
|
-
await import("node:fs/promises").then(
|
|
16
|
-
(fs) => fs.readFile(join(pkgRoot, "package.json"), "utf-8")
|
|
17
|
-
)
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
async function cmdVersion() {
|
|
21
|
-
const pkg = await readPkg();
|
|
22
|
-
console.log(pkg.version);
|
|
23
|
-
}
|
|
24
|
-
async function cmdInit(name, opts) {
|
|
25
|
-
const targetDir = resolve(process.cwd(), name);
|
|
26
|
-
if (existsSync(targetDir)) {
|
|
27
|
-
console.error(`Directory ${name} already exists.`);
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
const pkg = await readPkg();
|
|
31
|
-
const typesNodeVersion = pkg.devDependencies?.["@types/node"] || "^22";
|
|
32
|
-
if (opts.ssr) {
|
|
33
|
-
await generateReactSsr(targetDir, name, pkg.version, typesNodeVersion, opts.skipInstall);
|
|
34
|
-
} else {
|
|
35
|
-
await generateMinimal(targetDir, name, pkg.version, typesNodeVersion, opts.skipInstall);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
async function generateMinimal(targetDir, name, version, typesNodeVersion, skipInstall) {
|
|
39
|
-
await mkdir(targetDir, { recursive: true });
|
|
40
|
-
await writeFile(
|
|
41
|
-
join(targetDir, "app.ts"),
|
|
42
|
-
[
|
|
43
|
-
`import { Router } from 'weifuwu'`,
|
|
44
|
-
``,
|
|
45
|
-
`export const app = new Router()`,
|
|
46
|
-
``,
|
|
47
|
-
`app.get('/', () => new Response('Hello from ${name}!'))`,
|
|
48
|
-
`app.get('/api/ping', () => Response.json({ pong: true, time: new Date().toISOString() }))`,
|
|
49
|
-
``
|
|
50
|
-
].join("\n")
|
|
51
|
-
);
|
|
52
|
-
await writeFile(
|
|
53
|
-
join(targetDir, "index.ts"),
|
|
54
|
-
[
|
|
55
|
-
`import { loadEnv, serve } from 'weifuwu'`,
|
|
56
|
-
`import { app } from './app.ts'`,
|
|
57
|
-
``,
|
|
58
|
-
`loadEnv()`,
|
|
59
|
-
`const port = Number(process.env.PORT) || 3000`,
|
|
60
|
-
`serve(app.handler(), { port })`,
|
|
61
|
-
``
|
|
62
|
-
].join("\n")
|
|
63
|
-
);
|
|
64
|
-
await writePackageJson(targetDir, name, version, typesNodeVersion, {});
|
|
65
|
-
await writeCommonFiles(targetDir);
|
|
66
|
-
await finishInit(targetDir, skipInstall);
|
|
67
|
-
}
|
|
68
|
-
async function generateReactSsr(targetDir, name, version, typesNodeVersion, skipInstall) {
|
|
69
|
-
const templateDir = join(pkgRoot, "cli", "template", "react");
|
|
70
|
-
await copyRecursive(templateDir, targetDir);
|
|
71
|
-
await writePackageJson(targetDir, name, version, typesNodeVersion, {
|
|
72
|
-
dependencies: {
|
|
73
|
-
react: "^19",
|
|
74
|
-
"react-dom": "^19",
|
|
75
|
-
"@tailwindcss/postcss": "^4",
|
|
76
|
-
tailwindcss: "^4",
|
|
77
|
-
postcss: "^8"
|
|
78
|
-
},
|
|
79
|
-
devDependencies: {
|
|
80
|
-
"@types/react": "^19",
|
|
81
|
-
"@types/react-dom": "^19",
|
|
82
|
-
esbuild: "^0.28"
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
await writeFile(join(targetDir, ".gitignore"), "node_modules\n.env\n.weifuwu\n");
|
|
86
|
-
await finishInit(targetDir, skipInstall);
|
|
87
|
-
}
|
|
88
|
-
async function copyRecursive(src, dest) {
|
|
89
|
-
const { readdir, stat, copyFile } = await import("node:fs/promises");
|
|
90
|
-
const entries = await readdir(src, { withFileTypes: true });
|
|
91
|
-
for (const entry of entries) {
|
|
92
|
-
const srcPath = join(src, entry.name);
|
|
93
|
-
const destPath = join(dest, entry.name);
|
|
94
|
-
if (entry.isDirectory()) {
|
|
95
|
-
await mkdir(destPath, { recursive: true });
|
|
96
|
-
await copyRecursive(srcPath, destPath);
|
|
97
|
-
} else if (entry.isFile()) {
|
|
98
|
-
await copyFile(srcPath, destPath);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
async function writePackageJson(targetDir, name, version, typesNodeVersion, extra) {
|
|
103
|
-
const pkg = {
|
|
104
|
-
name,
|
|
105
|
-
type: "module",
|
|
106
|
-
scripts: {
|
|
107
|
-
dev: "node --watch index.ts",
|
|
108
|
-
start: "node index.ts"
|
|
109
|
-
},
|
|
110
|
-
dependencies: {
|
|
111
|
-
weifuwu: "^" + version
|
|
112
|
-
},
|
|
113
|
-
devDependencies: {
|
|
114
|
-
"@types/node": typesNodeVersion
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
if (extra) {
|
|
118
|
-
if (extra.dependencies) {
|
|
119
|
-
Object.assign(pkg.dependencies, extra.dependencies);
|
|
120
|
-
}
|
|
121
|
-
if (extra.devDependencies) {
|
|
122
|
-
Object.assign(pkg.devDependencies, extra.devDependencies);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
await writeFile(join(targetDir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
126
|
-
}
|
|
127
|
-
async function writeCommonFiles(targetDir) {
|
|
128
|
-
await writeFile(join(targetDir, ".gitignore"), "node_modules\n.env\n.weifuwu\n");
|
|
129
|
-
await writeFile(join(targetDir, ".env"), "PORT=3000\n");
|
|
130
|
-
}
|
|
131
|
-
async function finishInit(targetDir, skipInstall) {
|
|
132
|
-
if (!skipInstall) {
|
|
133
|
-
console.log("\nInstalling dependencies...");
|
|
134
|
-
execSync("npm install", { cwd: targetDir, stdio: "inherit" });
|
|
135
|
-
}
|
|
136
|
-
console.log(`
|
|
137
|
-
\u2705 Created ${targetDir.split("/").pop()}/`);
|
|
138
|
-
console.log(` cd ${targetDir.split("/").pop()}`);
|
|
139
|
-
if (skipInstall) console.log(` npm install`);
|
|
140
|
-
console.log(` npm run dev`);
|
|
141
|
-
}
|
|
142
|
-
var cmd = process.argv[2];
|
|
143
|
-
var HELP = `
|
|
144
|
-
weifuwu \u2014 Web-standard HTTP microframework for Node.js
|
|
145
|
-
|
|
146
|
-
Usage:
|
|
147
|
-
npx weifuwu init <name> Create a new API project
|
|
148
|
-
npx weifuwu init <name> --ssr Create a React SSR project
|
|
149
|
-
npx weifuwu init <name> --skip-install Skip npm install
|
|
150
|
-
npx weifuwu version Print version
|
|
151
|
-
`;
|
|
152
|
-
if (cmd === "version" || cmd === "-v" || cmd === "--version") {
|
|
153
|
-
cmdVersion().catch(console.error);
|
|
154
|
-
} else if (cmd === "init") {
|
|
155
|
-
const { values, positionals } = parseArgs({
|
|
156
|
-
args: process.argv.slice(3),
|
|
157
|
-
options: {
|
|
158
|
-
"skip-install": { type: "boolean" },
|
|
159
|
-
"ssr": { type: "boolean" },
|
|
160
|
-
"react": { type: "boolean" }
|
|
161
|
-
},
|
|
162
|
-
strict: false,
|
|
163
|
-
allowPositionals: true
|
|
164
|
-
});
|
|
165
|
-
const name = positionals[0];
|
|
166
|
-
if (!name) {
|
|
167
|
-
console.error("Usage: npx weifuwu init <name> [--ssr] [--skip-install]");
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
cmdInit(name, {
|
|
171
|
-
skipInstall: !!values["skip-install"],
|
|
172
|
-
ssr: !!(values["ssr"] || values["react"])
|
|
173
|
-
}).catch(
|
|
174
|
-
console.error
|
|
175
|
-
);
|
|
176
|
-
} else {
|
|
177
|
-
console.log(HELP);
|
|
178
|
-
}
|
package/dist/core/cookie.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/** Options for setting a cookie. All fields map to standard Set-Cookie attributes. */
|
|
2
|
-
export interface CookieOptions {
|
|
3
|
-
domain?: string;
|
|
4
|
-
path?: string;
|
|
5
|
-
maxAge?: number;
|
|
6
|
-
expires?: Date;
|
|
7
|
-
httpOnly?: boolean;
|
|
8
|
-
secure?: boolean;
|
|
9
|
-
sameSite?: 'strict' | 'lax' | 'none';
|
|
10
|
-
}
|
|
11
|
-
/** Parse cookies from a Request's `Cookie` header.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* const cookies = getCookies(req)
|
|
16
|
-
* console.log(cookies.session_id) // value or undefined
|
|
17
|
-
* ``` */
|
|
18
|
-
export declare function getCookies(req: Request): Record<string, string>;
|
|
19
|
-
/** Set a cookie on a Response.
|
|
20
|
-
*
|
|
21
|
-
* Appends a `Set-Cookie` header to the existing response headers.
|
|
22
|
-
* Returns a new Response with the added header.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```ts
|
|
26
|
-
* const res = new Response('ok')
|
|
27
|
-
* return setCookie(res, 'session', token, { httpOnly: true, path: '/' })
|
|
28
|
-
* ``` */
|
|
29
|
-
export declare function setCookie(res: Response, name: string, value: string, options?: CookieOptions): Response;
|
|
30
|
-
/** Delete a cookie by setting `Max-Age=0`.
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```ts
|
|
34
|
-
* return deleteCookie(res, 'session')
|
|
35
|
-
* ``` */
|
|
36
|
-
export declare function deleteCookie(res: Response, name: string, options?: Omit<CookieOptions, 'maxAge'>): Response;
|
package/dist/core/env.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { Context, Middleware } from '../types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* Get all public environment variables (those prefixed with `WEIFUWU_PUBLIC_`),
|
|
4
|
-
* with the prefix stripped.
|
|
5
|
-
*
|
|
6
|
-
* ```ts
|
|
7
|
-
* const pub = getPublicEnv()
|
|
8
|
-
* // WEIFUWU_PUBLIC_API_URL=http://api.example.com → { API_URL: 'http://api.example.com' }
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
export declare function getPublicEnv(): Record<string, string>;
|
|
12
|
-
declare module '../types.ts' {
|
|
13
|
-
interface Context {
|
|
14
|
-
env?: Record<string, string>;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Whether this code is running from the compiled `dist/index.js` bundle.
|
|
19
|
-
* `false` when running TypeScript source directly (dev workflow in weifuwu repo).
|
|
20
|
-
*
|
|
21
|
-
* Used by modules that need to resolve package-internal files differently
|
|
22
|
-
* depending on whether they are compiled (published npm package) or raw TS.
|
|
23
|
-
*/
|
|
24
|
-
export declare function isBundled(): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Whether `NODE_ENV` is explicitly set to `'development'`.
|
|
27
|
-
*
|
|
28
|
-
* Used for dev-only features: HMR, livereload, React `createRoot` (not hydrate).
|
|
29
|
-
* **Not** the opposite of {@link isProd} — when `NODE_ENV` is unset, both return `false`.
|
|
30
|
-
*/
|
|
31
|
-
export declare function isDev(): boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Whether `NODE_ENV` is explicitly set to `'production'`.
|
|
34
|
-
*
|
|
35
|
-
* Used for production-only behavior: plain-text 404, suppressed warnings, minified output.
|
|
36
|
-
*/
|
|
37
|
-
export declare function isProd(): boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Load environment variables from a `.env` file into `process.env`.
|
|
40
|
-
*
|
|
41
|
-
* Does **not** override existing `process.env` values.
|
|
42
|
-
* Supports quoted values and inline comments.
|
|
43
|
-
*
|
|
44
|
-
* @param path - Path to `.env` file (default: `'.env'` relative to cwd).
|
|
45
|
-
*
|
|
46
|
-
* ```ts
|
|
47
|
-
* import { loadEnv } from 'weifuwu'
|
|
48
|
-
* loadEnv()
|
|
49
|
-
* console.log(process.env.PORT)
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
export declare function loadEnv(path?: string): void;
|
|
53
|
-
/**
|
|
54
|
-
* Public env middleware.
|
|
55
|
-
*
|
|
56
|
-
* Injects `ctx.env` with all environment variables prefixed with `WEIFUWU_PUBLIC_`,
|
|
57
|
-
* with the prefix stripped. Safe to expose to the client.
|
|
58
|
-
*
|
|
59
|
-
* ```ts
|
|
60
|
-
* import { env } from 'weifuwu'
|
|
61
|
-
* app.use(env())
|
|
62
|
-
*
|
|
63
|
-
* // .env: WEIFUWU_PUBLIC_API_URL=https://api.example.com
|
|
64
|
-
* // ctx: ctx.env.API_URL === 'https://api.example.com'
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
|
-
export declare function env(): Middleware<Context, Context & {
|
|
68
|
-
env: Record<string, string>;
|
|
69
|
-
}>;
|
package/dist/core/html.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Safe HTML rendering via tagged template literals.
|
|
3
|
-
*
|
|
4
|
-
* Auto-escapes interpolated values to prevent XSS.
|
|
5
|
-
* Use `raw()` for trusted HTML that should not be escaped.
|
|
6
|
-
*
|
|
7
|
-
* ```ts
|
|
8
|
-
* import { html, raw } from '@weifuwujs/core'
|
|
9
|
-
*
|
|
10
|
-
* html`<h1>${title}</h1>` // auto-escaped
|
|
11
|
-
* html`<div>${raw(trustedHtml)}</div>` // unescaped
|
|
12
|
-
* html`<ul>${items.map(i => html`<li>${i}</li>`)}</ul>` // arrays
|
|
13
|
-
* html`${isAdmin && html`<button>Admin</button>`}` // conditionals
|
|
14
|
-
* html`<div>${html`<span>nested</span>`}</div>` // nested (safe)
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
interface RawHtml {
|
|
18
|
-
_raw: string;
|
|
19
|
-
}
|
|
20
|
-
export type HtmlValue = string | number | boolean | null | undefined | HtmlValue[] | RawHtml;
|
|
21
|
-
/**
|
|
22
|
-
* Tagged template literal for safe HTML.
|
|
23
|
-
*
|
|
24
|
-
* Interpolated values are auto-escaped. Use {@link raw} to bypass escaping
|
|
25
|
-
* for trusted HTML. Nested `html` calls are safe (not double-escaped).
|
|
26
|
-
*/
|
|
27
|
-
export declare function html(strings: TemplateStringsArray, ...values: HtmlValue[]): string;
|
|
28
|
-
/**
|
|
29
|
-
* Bypass HTML escaping for trusted content.
|
|
30
|
-
*
|
|
31
|
-
* Can be used standalone or inside {@link html} tagged templates.
|
|
32
|
-
*/
|
|
33
|
-
export declare function raw(content: string): HtmlValue;
|
|
34
|
-
export {};
|
package/dist/core/sse.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Format an SSE message string with a named event type.
|
|
3
|
-
*
|
|
4
|
-
* ```ts
|
|
5
|
-
* formatSSE('ping', { ts: Date.now() })
|
|
6
|
-
* // "event: ping\ndata: {"ts":...}\n\n"
|
|
7
|
-
* ```
|
|
8
|
-
*/
|
|
9
|
-
export declare function formatSSE(event: string, data: unknown): string;
|
|
10
|
-
/**
|
|
11
|
-
* Format an SSE message string with only a data line (no event type).
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* formatSSEData({ message: 'hello' })
|
|
15
|
-
* // "data: {"message":"hello"}\n\n"
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
export declare function formatSSEData(data: unknown): string;
|
|
19
|
-
/** An SSE event to be sent via {@link createSSEStream}. */
|
|
20
|
-
export interface SSEEvent {
|
|
21
|
-
/** Event type (maps to `event:` field). */
|
|
22
|
-
event: string;
|
|
23
|
-
/** Event payload (serialized as JSON in `data:` field). */
|
|
24
|
-
data: unknown;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Create a Server-Sent Events (SSE) `Response` from an async iterable.
|
|
28
|
-
*
|
|
29
|
-
* Each item in the iterable is serialized as an SSE message:
|
|
30
|
-
* - If the item has a `.type` property → `event: {type}` + `data: {item}`
|
|
31
|
-
* - Otherwise → `data: {item}`
|
|
32
|
-
*
|
|
33
|
-
* Errors are sent as `event: error` messages. `AbortError` is silently ignored.
|
|
34
|
-
*
|
|
35
|
-
* ```ts
|
|
36
|
-
* app.get('/events', () => {
|
|
37
|
-
* async function* generate() {
|
|
38
|
-
* yield { type: 'ping', data: { ts: Date.now() } }
|
|
39
|
-
* }
|
|
40
|
-
* return createSSEStream(generate())
|
|
41
|
-
* })
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export declare function createSSEStream(iterable: AsyncIterable<any>, opts?: {
|
|
45
|
-
headers?: Record<string, string>;
|
|
46
|
-
status?: number;
|
|
47
|
-
}): Response;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Context, Middleware } from '../types.ts';
|
|
2
|
-
declare module '../types.ts' {
|
|
3
|
-
interface Context {
|
|
4
|
-
csrf: CsrfInjected;
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
export interface CsrfInjected {
|
|
8
|
-
token: string;
|
|
9
|
-
}
|
|
10
|
-
/** CSRF protection module — a {@link Middleware} that injects `ctx.csrf`. */
|
|
11
|
-
export type CsrfModule = Middleware<Context, Context & CsrfInjected>;
|
|
12
|
-
export interface CsrfOptions {
|
|
13
|
-
/** Cookie name for CSRF token (default: `'_csrf'`). */
|
|
14
|
-
cookie?: string;
|
|
15
|
-
/** Request header name for CSRF token (default: `'x-csrf-token'`). */
|
|
16
|
-
header?: string;
|
|
17
|
-
/** Form body key for CSRF token (default: `'_csrf'`). */
|
|
18
|
-
key?: string;
|
|
19
|
-
/** HTTP methods to exclude from CSRF protection (default: `['GET', 'HEAD', 'OPTIONS']`). */
|
|
20
|
-
excludeMethods?: string[];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* CSRF protection middleware.
|
|
24
|
-
*
|
|
25
|
-
* On excluded methods (GET, HEAD, OPTIONS), generates a token and stores it
|
|
26
|
-
* in a cookie. On other methods, validates the token from header or body
|
|
27
|
-
* against the cookie.
|
|
28
|
-
*
|
|
29
|
-
* Injects `ctx.csrf.token` for use in forms.
|
|
30
|
-
*/
|
|
31
|
-
export declare function csrf(options?: CsrfOptions): Middleware<Context, Context & CsrfInjected>;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Context, Middleware } from '../types.ts';
|
|
2
|
-
declare module '../types.ts' {
|
|
3
|
-
interface Context {
|
|
4
|
-
flash: FlashInjected;
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
/** Flash message module — a {@link Middleware} that injects `ctx.flash`. */
|
|
8
|
-
export type FlashModule = Middleware<Context, Context & FlashInjected>;
|
|
9
|
-
/** Options for {@link flash}. */
|
|
10
|
-
export interface FlashOptions {
|
|
11
|
-
/**
|
|
12
|
-
* Cookie name to store the flash message.
|
|
13
|
-
* @default 'flash'
|
|
14
|
-
*/
|
|
15
|
-
name?: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Flash message object injected into `ctx.flash`.
|
|
19
|
-
*/
|
|
20
|
-
export interface FlashInjected {
|
|
21
|
-
/**
|
|
22
|
-
* The flash value read from the incoming cookie.
|
|
23
|
-
* `undefined` if no flash cookie is present.
|
|
24
|
-
* Automatically cleared after the response is sent.
|
|
25
|
-
*/
|
|
26
|
-
value: unknown;
|
|
27
|
-
/**
|
|
28
|
-
* Set a flash message and return a 302 redirect response.
|
|
29
|
-
*
|
|
30
|
-
* @param data - Any JSON-serializable value to store as the flash message.
|
|
31
|
-
* @param location - Redirect location (defaults to the `Referer` header).
|
|
32
|
-
* @returns A 302 Response with a `Set-Cookie` header.
|
|
33
|
-
*/
|
|
34
|
-
set: (data: unknown, location?: string) => Response;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Flash message middleware — injects `ctx.flash`.
|
|
38
|
-
*
|
|
39
|
-
* @param options - Cookie name configuration.
|
|
40
|
-
* @returns Middleware that injects `ctx.flash` (`FlashInjected`).
|
|
41
|
-
*/
|
|
42
|
-
export declare function flash(options?: FlashOptions): Middleware<Context, Context & {
|
|
43
|
-
flash: FlashInjected;
|
|
44
|
-
}>;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Router } from '../core/router.ts';
|
|
2
|
-
/** Options for {@link health}. */
|
|
3
|
-
export interface HealthOptions {
|
|
4
|
-
/** Health check endpoint path (default: `'/__health'`). */
|
|
5
|
-
path?: string;
|
|
6
|
-
/** Async function that throws if the service is unhealthy. Called on each request. */
|
|
7
|
-
check?: () => Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Health check endpoint.
|
|
11
|
-
*
|
|
12
|
-
* Returns 200 with `'OK'` if the check passes, 503 if it fails.
|
|
13
|
-
*
|
|
14
|
-
* ```ts
|
|
15
|
-
* import { health } from 'weifuwu'
|
|
16
|
-
*
|
|
17
|
-
* app.use(health({
|
|
18
|
-
* check: async () => {
|
|
19
|
-
* await db.query('SELECT 1')
|
|
20
|
-
* },
|
|
21
|
-
* }))
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export declare function health(options?: HealthOptions): Router;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Router } from '../core/router.ts';
|
|
2
|
-
import type { Context, Middleware } from '../types.ts';
|
|
3
|
-
declare module '../types.ts' {
|
|
4
|
-
interface Context {
|
|
5
|
-
i18n: I18nInjected;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
export interface I18nInjected {
|
|
9
|
-
locale: string;
|
|
10
|
-
messages?: Record<string, unknown>;
|
|
11
|
-
t: (key: string, params?: Record<string, string>, fallback?: string) => string;
|
|
12
|
-
set?: (value: string, loc?: string) => Response;
|
|
13
|
-
}
|
|
14
|
-
export interface I18nOptions {
|
|
15
|
-
/** Default locale (default: 'en'). */
|
|
16
|
-
default?: string;
|
|
17
|
-
/** Directory containing `{locale}.json` translation files. */
|
|
18
|
-
dir?: string;
|
|
19
|
-
/** Inline translation messages keyed by locale. */
|
|
20
|
-
messages?: Record<string, Record<string, unknown>>;
|
|
21
|
-
/** Cookie name for locale (default: 'locale'). Set empty to disable. */
|
|
22
|
-
cookie?: string;
|
|
23
|
-
/** Whether to detect locale from Accept-Language header (default: true). */
|
|
24
|
-
fromAcceptLanguage?: boolean;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* i18n module. Returns a Router with an attached `.middleware()` method.
|
|
28
|
-
*
|
|
29
|
-
* ```ts
|
|
30
|
-
* const l = i18n({ dir: './locales' })
|
|
31
|
-
* app.use(l.middleware()) // → ctx.i18n = { locale, t, set }
|
|
32
|
-
* app.mount('/', l) // → GET /__lang/:locale (switch route)
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export interface I18nModule extends Router {
|
|
36
|
-
/** Middleware that injects `ctx.i18n = { locale, t, set }`. */
|
|
37
|
-
middleware: () => Middleware<Context, Context & I18nInjected>;
|
|
38
|
-
}
|
|
39
|
-
export declare function i18n(options?: I18nOptions): I18nModule;
|