weifuwu 0.23.2 → 0.23.4

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.
Files changed (45) hide show
  1. package/README.md +55 -0
  2. package/cli/template/.weifuwu/ssr/2e3a7e60.js +3 -3
  3. package/dist/analytics.d.ts +20 -0
  4. package/dist/client-locale.d.ts +20 -0
  5. package/dist/client-theme.d.ts +29 -0
  6. package/dist/compress.d.ts +14 -0
  7. package/dist/cors.d.ts +15 -0
  8. package/dist/cron-utils.d.ts +65 -0
  9. package/dist/csrf.d.ts +29 -0
  10. package/dist/env.d.ts +33 -5
  11. package/dist/flash.d.ts +66 -7
  12. package/dist/health.d.ts +18 -0
  13. package/dist/helmet.d.ts +15 -0
  14. package/dist/hub.d.ts +25 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +124 -43
  17. package/dist/mailer.d.ts +30 -0
  18. package/dist/permissions.d.ts +5 -3
  19. package/dist/postgres/schema/columns.d.ts +56 -0
  20. package/dist/postgres/schema/sql.d.ts +15 -0
  21. package/dist/postgres/schema/table.d.ts +54 -1
  22. package/dist/postgres/schema/where.d.ts +14 -0
  23. package/dist/rate-limit.d.ts +25 -3
  24. package/dist/request-id.d.ts +19 -0
  25. package/dist/seo.d.ts +65 -0
  26. package/dist/sse.d.ts +37 -0
  27. package/dist/static.d.ts +16 -0
  28. package/dist/stream.d.ts +15 -0
  29. package/dist/trace.d.ts +41 -5
  30. package/dist/types.d.ts +10 -1
  31. package/dist/upload.d.ts +30 -0
  32. package/dist/use-action.d.ts +28 -0
  33. package/dist/use-agent-stream.d.ts +32 -10
  34. package/dist/use-flash-message.d.ts +16 -0
  35. package/dist/use-websocket.d.ts +25 -0
  36. package/dist/user/client.d.ts +15 -0
  37. package/dist/user/oauth2.d.ts +10 -0
  38. package/dist/user/types.d.ts +58 -4
  39. package/dist/webhook.d.ts +40 -15
  40. package/package.json +5 -3
  41. package/cli/template/.weifuwu/ssr/560568d7.js +0 -14
  42. package/dist/kb.d.ts +0 -70
  43. package/dist/oauth-client.d.ts +0 -41
  44. package/dist/preferences.d.ts +0 -18
  45. package/dist/server.d.ts +0 -1
@@ -1,6 +1,7 @@
1
1
  import type { Middleware, Context } from '../types.ts';
2
2
  import type { Router } from '../router.ts';
3
3
  import type { PostgresClient } from '../postgres/types.ts';
4
+ /** A user record from the database. */
4
5
  export interface UserData {
5
6
  id: number;
6
7
  email: string;
@@ -9,10 +10,14 @@ export interface UserData {
9
10
  created_at: Date;
10
11
  updated_at: Date;
11
12
  }
13
+ /** Result of a successful register or login. */
12
14
  export interface AuthResult {
15
+ /** User data (excluding password hash). */
13
16
  user: Omit<UserData, 'password'>;
17
+ /** Signed JWT token. */
14
18
  token: string;
15
19
  }
20
+ /** An OAuth2 client application registered with the server. */
16
21
  export interface OAuth2Client {
17
22
  id: number;
18
23
  name: string;
@@ -21,12 +26,17 @@ export interface OAuth2Client {
21
26
  redirectUris: string[];
22
27
  scopes: string;
23
28
  }
29
+ /** Enable OAuth2 server mode (authorization code flow). */
24
30
  export interface OAuth2ServerOptions {
25
31
  server: true;
26
32
  }
33
+ /** Configuration for an OAuth login provider (e.g. GitHub, Google). */
27
34
  export interface OAuthProviderConfig {
35
+ /** OAuth app client ID. */
28
36
  clientId: string;
37
+ /** OAuth app client secret. */
29
38
  clientSecret: string;
39
+ /** Scopes to request (default: `'openid profile email'`). */
30
40
  scope?: string;
31
41
  /** Custom auth URL (overrides built-in provider default). */
32
42
  authUrl?: string;
@@ -36,8 +46,8 @@ export interface OAuthProviderConfig {
36
46
  userUrl?: string;
37
47
  /**
38
48
  * Custom user parser.
39
- * Required when any of authUrl/tokenUrl/userUrl is custom.
40
- * Receives the raw response from userUrl + the access token.
49
+ * Required when any of `authUrl`/`tokenUrl`/`userUrl` is custom.
50
+ * Receives the raw response from `userUrl` + the access token.
41
51
  */
42
52
  parseUser?: (data: any, accessToken: string) => {
43
53
  id: string;
@@ -46,43 +56,87 @@ export interface OAuthProviderConfig {
46
56
  avatarUrl?: string;
47
57
  };
48
58
  }
59
+ /** Options for {@link user}. */
49
60
  export interface UserOptions {
61
+ /** PostgreSQL client for user storage. */
50
62
  pg: PostgresClient;
63
+ /** Secret key for JWT signing. */
51
64
  jwtSecret: string;
65
+ /** Custom table name for users (default: `'users'`). */
52
66
  table?: string;
67
+ /** JWT expiration time (default: `'7d'`). */
53
68
  expiresIn?: string | number;
69
+ /** Enable OAuth2 server mode (authorization code flow). */
54
70
  oauth2?: OAuth2ServerOptions;
55
71
  /**
56
72
  * OAuth login providers (login with GitHub/Google).
57
- * Registers GET /auth/:provider and GET /auth/:provider/callback routes.
73
+ * Registers `GET /auth/:provider` and `GET /auth/:provider/callback` routes.
58
74
  */
59
75
  oauthLogin?: {
76
+ /** Map of provider name to config (e.g. `{ github: {...}, google: {...} }`). */
60
77
  providers: Record<string, OAuthProviderConfig>;
61
- /** Where to redirect after successful login (default: '/'). */
78
+ /** Redirect URL after successful login (default: `'/'`). */
62
79
  redirectUrl?: string;
63
80
  };
64
81
  }
82
+ /** The shape of `ctx.user` when the user middleware is active. */
65
83
  export interface UserInjected {
66
84
  user: UserData;
67
85
  }
86
+ /**
87
+ * User module returned by {@link user}. Provides auth routes, middleware, and programmatic API.
88
+ *
89
+ * ```ts
90
+ * const auth = user({ pg, jwtSecret: process.env.JWT_SECRET })
91
+ * app.use(auth.middleware()) // injects ctx.user on every request
92
+ * app.use('/', auth) // mounts routes: /register, /login
93
+ * ```
94
+ */
68
95
  export interface UserModule extends Router {
96
+ /**
97
+ * Strict auth middleware. Reads JWT from `Authorization: Bearer` header.
98
+ * Returns 401 if no valid token is found.
99
+ * Use for routes that require authentication.
100
+ */
69
101
  middleware: () => Middleware<Context, Context & UserInjected>;
102
+ /**
103
+ * Optional auth middleware. Reads JWT from `Authorization` header or `token` cookie.
104
+ * Sets `ctx.user` if a valid token is present, but does **not** block unauthenticated requests.
105
+ * Use as a global middleware when some routes are public and some are protected.
106
+ *
107
+ * ```ts
108
+ * app.use(auth.middlewareOptional({ cookie: 'token' }))
109
+ * app.get('/profile', auth.middleware(), handler) // protected
110
+ * app.get('/', handler) // public
111
+ * ```
112
+ */
113
+ middlewareOptional: (opts?: {
114
+ cookie?: string;
115
+ }) => Middleware;
116
+ /** Create the users table. */
70
117
  migrate: () => Promise<void>;
118
+ /** Register a new user. Returns user data + JWT. */
71
119
  register: (data: {
72
120
  email: string;
73
121
  password: string;
74
122
  name: string;
75
123
  }) => Promise<AuthResult>;
124
+ /** Authenticate by email + password. Returns user data + JWT. */
76
125
  login: (data: {
77
126
  email: string;
78
127
  password: string;
79
128
  }) => Promise<AuthResult>;
129
+ /** Verify a JWT and return the user data (or null if invalid). */
80
130
  verify: (token: string) => Promise<Omit<UserData, 'password'> | null>;
131
+ /** Register a new OAuth2 client application. */
81
132
  registerClient: (data: {
82
133
  name: string;
83
134
  redirectUris: string[];
84
135
  }) => Promise<OAuth2Client>;
136
+ /** Look up an OAuth2 client by clientId. */
85
137
  getClient: (clientId: string) => Promise<OAuth2Client | null>;
138
+ /** Revoke an OAuth2 client. */
86
139
  revokeClient: (clientId: string) => Promise<void>;
140
+ /** Close the underlying DB connection. */
87
141
  close: () => Promise<void>;
88
142
  }
package/dist/webhook.d.ts CHANGED
@@ -1,54 +1,79 @@
1
1
  import type { Context } from './types.ts';
2
2
  import { Router } from './router.ts';
3
+ /** A parsed webhook event delivered to handlers. */
3
4
  export interface WebhookEvent {
4
- /** Raw event name from the provider (e.g. 'checkout.session.completed') */
5
+ /** Raw event name from the provider (e.g. 'checkout.session.completed'). */
5
6
  event: string;
6
- /** Parsed event payload */
7
+ /** Parsed event payload (body after verification). */
7
8
  payload: unknown;
8
- /** Provider name (e.g. 'stripe', 'github') */
9
+ /** Provider name (e.g. 'stripe', 'github'). */
9
10
  provider: string;
10
- /** Unique event ID for replay protection */
11
+ /** Unique event ID for replay protection. */
11
12
  id?: string;
12
13
  }
14
+ /** Handler function for a webhook event. */
13
15
  export interface WebhookHandler {
14
16
  (event: WebhookEvent, ctx: Context): void | Promise<void>;
15
17
  }
18
+ /** Configuration for a built-in platform webhook verifier (Stripe, GitHub, Slack). */
16
19
  export interface PlatformConfig {
17
- /** HMAC-SHA256 secret */
20
+ /** HMAC-SHA256 signing secret. */
18
21
  secret: string;
19
- /** Optional custom event prefix (default: platform name) */
22
+ /** Optional event prefix (default: platform name, e.g. 'stripe'). */
20
23
  prefix?: string;
21
24
  }
25
+ /** Configuration for a custom webhook verifier. */
22
26
  export interface CustomVerifierConfig {
23
- /** Name for this verifier */
27
+ /** Name for this verifier. */
24
28
  name: string;
25
29
  /** Verify function. Return true if signature is valid. */
26
30
  verify: (body: string, headers: Record<string, string>) => boolean | Promise<boolean>;
27
31
  /** Extract event name from body and headers */
28
32
  event: (body: unknown, headers: Record<string, string>) => string;
29
33
  }
34
+ /** Options for {@link webhook}. */
30
35
  export interface WebhookOptions {
31
- /** Stripe webhook config (enables Stripe signature verification) */
36
+ /** Stripe webhook config (enables Stripe signature verification). */
32
37
  stripe?: PlatformConfig;
33
- /** GitHub webhook config */
38
+ /** GitHub webhook config. */
34
39
  github?: PlatformConfig;
35
- /** Slack webhook config */
40
+ /** Slack webhook config. */
36
41
  slack?: PlatformConfig;
37
- /** Custom verifiers */
42
+ /** Custom verifiers. */
38
43
  custom?: CustomVerifierConfig[];
39
- /** Global prefix for all event types (default: none) */
44
+ /** Global prefix for all event types (default: none). */
40
45
  prefix?: string;
41
- /** Path to mount the webhook receiver. Default: '/'. */
46
+ /** Path to mount the webhook receiver. Default: `'/'`. */
42
47
  path?: string;
43
48
  /** Enable replay protection (requires provider to send unique event IDs). Default: true. */
44
49
  replayProtection?: boolean;
45
50
  /** Idempotency key TTL in ms. Default: 3600000 (1 hour). */
46
51
  idempotencyTTL?: number;
47
52
  }
53
+ /** Webhook module instance returned by {@link webhook}. */
48
54
  export interface WebhookModule extends Router {
49
- /** Register an event handler */
55
+ /** Register an event handler. */
50
56
  on(event: string, handler: WebhookHandler): this;
51
- /** Remove an event handler */
57
+ /** Remove an event handler. */
52
58
  off(event: string, handler: WebhookHandler): this;
53
59
  }
60
+ /**
61
+ * Webhook receiver module. Validates signatures and dispatches events.
62
+ *
63
+ * Supports built-in verifiers for Stripe, GitHub, and Slack, plus custom verifiers.
64
+ *
65
+ * ```ts
66
+ * import { webhook } from 'weifuwu'
67
+ *
68
+ * const wh = webhook({
69
+ * stripe: { secret: process.env.STRIPE_WEBHOOK_SECRET },
70
+ * })
71
+ *
72
+ * wh.on('checkout.session.completed', async (event, ctx) => {
73
+ * // event.payload contains the parsed Stripe event
74
+ * })
75
+ *
76
+ * app.use('/', wh)
77
+ * ```
78
+ */
54
79
  export declare function webhook(options?: WebhookOptions): WebhookModule;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weifuwu",
3
- "version": "0.23.2",
3
+ "version": "0.23.4",
4
4
  "description": "Web-standard HTTP framework for Node.js — (req, ctx) => Response",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -22,9 +22,11 @@
22
22
  "scripts": {
23
23
  "dev": "cd cli/template && NODE_ENV=development node --watch index.ts",
24
24
  "start": "cd cli/template && node index.ts",
25
- "build": "esbuild index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --packages=external && esbuild cli.ts --bundle --format=esm --platform=node --outfile=dist/cli.js --packages=external && esbuild react.ts --bundle --format=esm --outfile=dist/react.js --external:react --external:react-dom",
25
+ "build": "esbuild index.ts --bundle --format=esm --platform=node --outfile=dist/index.js --packages=external --define:__WFW_BUNDLED__=true && esbuild cli.ts --bundle --format=esm --platform=node --outfile=dist/cli.js --packages=external && esbuild react.ts --bundle --format=esm --outfile=dist/react.js --external:react --external:react-dom",
26
26
  "prepublishOnly": "npm run build && tsc --emitDeclarationOnly --outdir dist",
27
- "test": "node --test 'test/**/*.test.ts'"
27
+ "test": "node --test 'test/**/*.test.ts'",
28
+ "test:unit": "bash scripts/test-unit.sh",
29
+ "test:ci": "node --test 'test/**/*.test.ts'"
28
30
  },
29
31
  "dependencies": {
30
32
  "@ai-sdk/openai": "^3.0.66",
@@ -1,14 +0,0 @@
1
- // ui/app/layout.tsx
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- function RootLayout({ children }) {
4
- return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
5
- /* @__PURE__ */ jsxs("head", { children: [
6
- /* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
7
- /* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" })
8
- ] }),
9
- /* @__PURE__ */ jsx("body", { children: /* @__PURE__ */ jsx("main", { children }) })
10
- ] });
11
- }
12
- export {
13
- RootLayout as default
14
- };
package/dist/kb.d.ts DELETED
@@ -1,70 +0,0 @@
1
- import type { Sql } from './vendor.ts';
2
- import type { Middleware } from './types.ts';
3
- export interface KBOptions {
4
- /** Postgres SQL client (with pgvector extension enabled). */
5
- sql: Sql<{}>;
6
- /**
7
- * Embedding function.
8
- * Takes a text string, returns a vector of numbers.
9
- * Example: (text) => embed({ model: openai.embedding('text-embedding-3-small'), value: text }).then(r => r.embedding)
10
- */
11
- embedding: (text: string) => Promise<number[]>;
12
- /** Vector dimensions (default: 1536 for text-embedding-3-small). */
13
- dimensions?: number;
14
- /** Table name (default: '_kb_docs'). */
15
- table?: string;
16
- /** Default chunk size in characters (default: 512). */
17
- chunkSize?: number;
18
- /** Default chunk overlap in characters (default: 64). */
19
- chunkOverlap?: number;
20
- /** Default search limit (default: 5). */
21
- searchLimit?: number;
22
- /** Minimum similarity score threshold (0–1, default: 0). Set higher for stricter matches. */
23
- searchThreshold?: number;
24
- }
25
- export interface KBIngestOptions {
26
- title?: string;
27
- metadata?: Record<string, unknown>;
28
- chunkSize?: number;
29
- chunkOverlap?: number;
30
- }
31
- export interface KBSearchResult {
32
- id: number;
33
- key: string;
34
- title: string;
35
- content: string;
36
- score: number;
37
- metadata: Record<string, unknown>;
38
- }
39
- export interface KBSearchOptions {
40
- limit?: number;
41
- /** Minimum cosine similarity score (0–1). Results below this are excluded. */
42
- threshold?: number;
43
- }
44
- export interface KBListEntry {
45
- key: string;
46
- title: string;
47
- chunks: number;
48
- }
49
- export interface KBModule {
50
- /**
51
- * Ingest a document: chunk → embed → store.
52
- * If a document with the same key exists, it is replaced (delete + re-insert).
53
- * Returns the number of chunks created.
54
- */
55
- ingest(key: string, content: string, options?: KBIngestOptions): Promise<number>;
56
- /**
57
- * Search the knowledge base by semantic similarity.
58
- * Query is embedded, then vector similarity search returns top results.
59
- */
60
- search(query: string, searchOptions?: KBSearchOptions): Promise<KBSearchResult[]>;
61
- /** Delete all chunks for a document key. */
62
- delete(key: string): Promise<void>;
63
- /** List all document keys with title and chunk count. */
64
- list(): Promise<KBListEntry[]>;
65
- /** Create the table and HNSW index. Safe to call multiple times. */
66
- migrate(): Promise<void>;
67
- /** Middleware that injects `ctx.kb` with `.search()` method. */
68
- middleware(): Middleware;
69
- }
70
- export declare function knowledgeBase(options: KBOptions): KBModule;
@@ -1,41 +0,0 @@
1
- import type { PostgresClient } from './postgres/types.ts';
2
- import { Router } from './router.ts';
3
- export interface OAuthProviderConfig {
4
- clientId: string;
5
- clientSecret: string;
6
- scope?: string;
7
- /** Custom auth URL (overrides built-in provider default). */
8
- authUrl?: string;
9
- /** Custom token URL (overrides built-in provider default). */
10
- tokenUrl?: string;
11
- /** Custom user info URL (overrides built-in provider default). */
12
- userUrl?: string;
13
- /**
14
- * Custom user parser.
15
- * Required when any of authUrl/tokenUrl/userUrl is custom.
16
- * Receives the raw response from userUrl + the access token.
17
- */
18
- parseUser?: (data: any, accessToken: string) => ProviderUser;
19
- }
20
- export interface OAuthClientOptions {
21
- /** Postgres client (required). */
22
- pg: PostgresClient;
23
- /** JWT secret — must match user() module's jwtSecret. */
24
- jwtSecret: string;
25
- /** JWT expiry (default: '24h'). */
26
- expiresIn?: string | number;
27
- /** Where to redirect after successful login (default: '/'). */
28
- redirectUrl?: string;
29
- /** Provider configurations. */
30
- providers: Record<string, OAuthProviderConfig>;
31
- /** Table name for provider-user links (default: '_auth_providers'). */
32
- table?: string;
33
- }
34
- interface ProviderUser {
35
- id: string;
36
- email: string;
37
- name: string;
38
- avatarUrl?: string;
39
- }
40
- export declare function oauthClient(options: OAuthClientOptions): Router;
41
- export {};
@@ -1,18 +0,0 @@
1
- import type { Context, Middleware } from './types.ts';
2
- export interface PrefOptions {
3
- dir?: string;
4
- locale?: {
5
- default?: string;
6
- cookie?: string;
7
- fromAcceptLanguage?: boolean;
8
- };
9
- theme?: {
10
- default?: string;
11
- cookie?: string;
12
- };
13
- }
14
- export declare function preferences(options: PrefOptions): Middleware<Context, Context & {
15
- prefs: Record<string, string>;
16
- t: NonNullable<Context['t']>;
17
- setPref: NonNullable<Context['setPref']>;
18
- }>;
package/dist/server.d.ts DELETED
@@ -1 +0,0 @@
1
- export {};