news 2026/9/13 3:52:53

Wasp kitchen-sink 示例应用全解析:Wasp CLI 开发测试平台与全特性展示场

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Wasp kitchen-sink 示例应用全解析:Wasp CLI 开发测试平台与全特性展示场

Wasp kitchen-sink 示例应用全解析:Wasp CLI 开发测试平台与全特性展示场

【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp

导读

examples/kitchen-sink是 Wasp 仓库中一个"样样俱全"的示例应用:它既是 Wasp 团队为 contributors 准备的低成本开发测试平台,也是向开发者集中展示 Wasp 全栈框架各项能力的演示工程。本文将带你梳理这个应用的定位、初始化流程、环境变量管理、开发/运行/测试全链路,并深入到其 TypeScript 配置与源码实现中,逐一解读认证、查询/动作、后台任务、CRUD、自定义 API、数据库种子、WebSocket 等特性在真实工程里是如何声明的。读完你既能快速把它跑起来,也能把它当作 Wasp 官方功能的"活字典"按图索骥。

kitchen-sink 的设计目标:既是测试床,也是特性清单

从 README.md 开篇可以明确看到,这个应用承担两大使命:

  1. 首要目的:让 Wasp 贡献者轻松地测试开发版本的 Wasp CLI。Wasp 的 CLI(Haskell 实现,位于 waspc/ 目录)在迭代过程中需要不断验证wasp startwasp db migrate-devwasp build等命令的可用性,kitchen-sink 就是那个随时可以拿来"跑一遍"的靶场。
  2. 次要目的:尽可能多地演示 Wasp 特性。README 特别说明:并非所有特性都能同时共存(例如emailusernameAndPassword两种认证方式互斥),但在约束范围内应尽可能覆盖。

此外,它是 Waspe2e 应用测试的主战场——任何新增或修改的特性,都应尽量在这个应用里补充对应的端到端测试。这一点在 e2e-tests/tests/ 目录的 19 个 spec 文件中得到印证(auth.spec.tscrud.spec.tsjobswebsocket.spec.ts等),我们将在后文详述。

项目结构:一个用 TypeScript 声明一切的应用

kitchen-sink 采用 Wasp 较新的 TypeScript 定义方式:核心配置集中在 main.wasp.ts,业务代码按特性(feature)分目录组织在 src/features/ 下,每个特性通过独立的*.wasp.ts文件导出自己的声明片段,再由main.wasp.ts汇总。

// main.wasp.ts(节选) import { app, page, route } from "@wasp.sh/spec"; // ... export default app({ name: "KitchenSink", wasp: { version: "0.26.0" }, title: "Wasp Kitchen Sink", webSocket, auth: authConfig, server: { setupFn: serverSetup, middlewareConfigFn: serverMiddlewareFn, envValidationSchema: serverEnvValidationSchema, }, client: { rootComponent: App, setupFn: clientSetup, envValidationSchema: clientEnvValidationSchema, }, db, emailSender: { provider: "SMTP", defaultFrom: { email: "kitchen-sink@wasp.sh" } }, spec: [ /* route、page、authSpec、operationsSpec、jobsSpec、apisSpec、crudSpec ... */ ], });

从这段声明可以看到一个完整的 Wasp 应用骨架:应用级配置(name/wasp版本/head标签)、服务端与客户端的setupFn、中间件配置函数、环境变量校验 schema、数据库配置、SMTP 邮件发送器,以及按特性拆分的路由与能力清单spec

按特性组织的 src 目录

src/features/ ├── apis/ 自定义 HTTP API 与命名空间 ├── auth/ 多 Provider 认证(Google/GitHub/Discord/Slack/Microsoft/Email) ├── chat/ WebSocket 实时通信 ├── crud/ CRUD 操作与覆盖函数 ├── db/ Prisma 设置与数据库种子 ├── jobs/ PgBoss 后台任务与定时任务 ├── lazy-loading/ 懒加载路由演示 ├── operations/ Query/Action 与序列化演示 ├── prerender/ 静态预渲染演示 └── streaming/ Server-Sent Events 流式响应

这种"一个特性一个目录 + 一个*.wasp.ts声明文件"的组织方式,本身就是对 Wasp"以声明式代码驱动全栈能力"理念的最佳示范。

初始化与依赖安装

首次拿到仓库后,进入 kitchen-sink 目录执行依赖安装:

wasp install

该命令会基于 main.wasp.ts 中的wasp: { version: "0.26.0" }校验 CLI 版本兼容性,并为项目生成.wasp输出目录。项目本身是 npm workspace 结构,package.json 中声明了workspaces: [".wasp/out/*", ".wasp/out/sdk/wasp"],即把 Wasp 生成的前端、后端与 SDK 包作为本地 workspace 链接,保证运行时依赖与生成代码始终一致。

环境变量:从最小启动到团队共享

最小启动:复制示例文件

kitchen-sink 提供了带假值的示例环境变量文件,最小化配置即可启动:

cp .env.server.example .env.server

README 明确说明:这样创建的.env.server中各项变量都是 dummy 值,应用可以正常启动,但并非所有特性都能工作——例如 Google Auth、GitHub Auth 等第三方 Provider 需要真实的 API Key 才能完成 OAuth 流程。配置这些 Provider 的细节可查阅 Wasp 官方文档中对应章节。

团队共享:dotenv-vault

对于 Wasp 团队成员,kitchen-sink 通过 package.json 中的脚本封装了 dotenv-vault(外部工具,此处仅说明命令本身):

# 拉取共享的 .env.server(含真实 API Keys) npm run env:pull # 将本地改动同步回共享配置 npm run env:push

对应的脚本定义为:

"env:pull": "npx dotenv-vault@latest pull development .env.server", "env:push": "npx dotenv-vault@latest push development .env.server"

这套机制解决了"本地开发需要真实密钥、但密钥不应进入 Git"的矛盾,适合团队协作场景。

环境变量的运行时校验

kitchen-sink 还示范了 Wasp 的环境变量校验能力。src/env.ts 使用 Zod 分别定义了服务端与客户端的校验 schema:

import { defineEnvValidationSchema } from "wasp/env"; import * as z from "zod"; export const serverEnvValidationSchema = defineEnvValidationSchema( z.object({ TEST_ENV_VAR: z.string({ error: "TEST_ENV_VAR is required." }), }), ); export const clientEnvValidationSchema = defineEnvValidationSchema( z.object({ REACT_APP_NAME: z.string().default("Kitchen Sink App"), }), );

可以看到:服务端变量TEST_ENV_VAR缺失时会抛出自定义错误信息;客户端变量REACT_APP_NAME则提供了默认值"Kitchen Sink App"。这两个 schema 分别挂在 main.wasp.ts 的server.envValidationSchemaclient.envValidationSchema上,在应用启动阶段即完成校验,属于"配置即验证"的实践。

运行应用:三步启动

kitchen-sink 的运行方式与任何 Wasp 应用完全一致,README 给出了标准流程:

1. 启动数据库(独立终端):

wasp start db

该命令拉起 Postgres 容器。从 schema.prisma 可以看到数据库 provider 固定为postgresqlDATABASE_URL由环境变量注入。

2. 迁移数据库(如需要,另一个终端):

wasp db migrate-dev

kitchen-sink 的迁移记录都在 migrations/ 目录下,涵盖初始表、地址字段、会话、投票、可见性枚举、邮件验证钩子、大写文本任务等多次演进。以 schema.prisma 当前模型为例,核心实体包括:

  • User:除基础字段外,还带有isOnAfterSignupHookCalledisOnAfterLoginHookCalledisOnAfterEmailVerifiedHookCallednumTimesOnAfterEmailVerifiedCalled钩子调用记录字段——它们正是 e2e 测试中验证认证钩子是否被正确触发的依据;
  • Task:含TaskVisibility枚举(PRIVATE/LINK_ONLY/PUBLIC),演示枚举类型在查询与 CRUD 中的应用;
  • TaskVote:多对多关系的投票表;
  • UppercaseTextRequest:配合后台任务演示"提交请求 → 异步处理 → 查询结果"的完整链路。

3. 启动应用(第三个终端):

wasp start

4. 浏览器打开localhost:3000,即可看到应用首页。

使用开发版 Wasp CLI:waspc/run 脚本

kitchen-sink 的首要定位是测试开发版Wasp CLI,因此 README 特别给出了三种调用方式:

# 从 kitchen-sink 目录内,使用仓库内脚本的相对路径: ../../waspc/run wasp-cli start db # 或为该脚本设置别名后使用绝对路径: wrun wasp-cli start db # 或将开发版 waspc 二进制全局安装后直接调用: wasp-cli start db

这里的 waspc/run 脚本是 Wasp 仓库内为 contributors 准备的开发用包装器,它会构建(或复用已构建的)waspc Haskell 可执行文件并转发后续参数,从而让你总是用最新源码的 CLI 行为来驱动 kitchen-sink,而不是已发布的正式版本。这对贡献者验证 CLI 改动、排查回归至关重要:任何一个startbuilddb子命令的改动,都可以在 kitchen-sink 上立刻得到真实反馈。

全特性深度解读:从声明到实现

kitchen-sink 的价值在于它几乎覆盖了 Wasp 的每一项核心能力。下面逐特性拆解其声明文件与配套实现。

1. 认证:六种 Provider + 完整生命周期钩子

src/features/auth/auth.wasp.ts 是仓库里信息量最大的声明文件之一,展示了 Wasp 认证体系的全貌:

  • 五种 OAuth ProviderslackdiscordgooglegitHubmicrosoft,每个 Provider 都带有configFn(读取对应环境变量、组装 OAuth 配置)与userSignupFields(声明注册时需要收集的额外用户字段,对应实现位于 providers/);
  • 邮箱密码认证email方法配置了fromField、邮件验证(getEmailContentFn+ 客户端验证路由EmailVerificationRoute)和密码重置(getPasswordResetContentFn+PasswordResetRoute);
  • 认证钩子onBeforeSignuponAfterSignuponAfterEmailVerifiedonBeforeLoginonAfterLogin,实现见 hooks.ts。这些钩子会修改 User 实体上那些isOnAfter*HookCalled字段,供 auth-hooks.spec.ts 端到端验证;
  • 自定义注册流程/custom-signup(自定义 Signup 页面 + 自定义 action,见 customSignup.ts)与/manual-signup(手动注册页)两条演示路由,对应 custom-signup.spec.ts 与 manual-signup.spec.ts;
  • 跳转策略onAuthFailedRedirectTo: "/login"onAuthSucceededRedirectTo: "/"

认证相关路由(注册、登录、密码重置、邮件验证、Profile 页)统一由authSpec导出并在main.wasp.ts中注册,其中/profile页使用了{ authRequired: true }保护。

2. Query / Action:类型安全的 RPC 与实体跟踪

src/features/operations/operations.wasp.ts 展示了 Wasp 的 RPC 核心:

query(getTasks, { entities: ["Task"] }), query(getNumTasks, { entities: ["Task"], auth: false }), action(createTask, { entities: ["Task"] }), action(updateTaskIsDone, { entities: ["Task"] }), // ... query(getSerializedObjects),
  • query/actionentities字段声明操作涉及的数据模型,Wasp 据此生成自动缓存失效逻辑——相关的测试见 cacheInvalidation.test.ts;
  • auth: false可标记无需认证的公开查询(如getNumTasks);
  • 页面路由(/tasks/tasks/:id)都带authRequired: true
  • 特别地,getSerializedObjects与 SerializationPage.tsx 用来演示 Wasp 对 Date、特殊对象等复杂类型在客户端/服务端之间的序列化处理,配套 serialization.spec.ts 测试。

3. 后台任务:PgBoss 执行器与 Cron 调度

src/features/jobs/jobs.wasp.ts 覆盖了 Wasp 后台任务的两个核心场景:

job(uppercaseTextJob, { executor: "PgBoss", entities: ["UppercaseTextRequest"], }), job(mySpecialJob, { executor: "PgBoss", performExecutorOptions: { pgBoss: { retryLimit: 1 } }, entities: ["Task"], }), job(mySpecialScheduledJob, { executor: "PgBoss", schedule: { cron: "0 * * * *", args: { foo: "bar" }, executorOptions: { pgBoss: { retryLimit: 2 } }, }, }),
  • 按需任务uppercaseTextJob接收一个UppercaseTextRequest记录,异步完成文本大写转换并回写结果——配套 uppercaseText.ts 与 JobsPage;
  • 任务级重试策略mySpecialJob通过performExecutorOptions.pgBoss.retryLimit设置重试次数;
  • 定时任务mySpecialScheduledJobcron: "0 * * * *"声明每小时执行,并携带静态参数args与调度级重试配置executorOptions

从源码结构看,所有后台任务均指定executor: "PgBoss",这意味着 kitchen-sink 的 job 依赖 Postgres(与 schema.prisma 的UppercaseTextRequestState枚举PENDING/SUCCESS/ERROR共同构成任务状态机),对应 e2e 测试为 async-jobs.spec.ts。

4. CRUD:声明式增删改查 + 覆盖函数 + 部分 CRUD

src/features/crud/crud.wasp.ts 演示了三种 CRUD 用法:

crud("tasks", "Task", { get: {}, getAll: { overrideFn: crudGetAllTasks }, create: { overrideFn: crudCreateTask }, update: {}, delete: {}, }), // 故意只声明 getAll:覆盖"用户未请求的操作不应出现在生成代码中"的情形 crud("taskVotes", "TaskVote", { getAll: {} }),
  • 一个crud声明即可为指定实体生成get/getAll/create/update/delete全套操作;
  • overrideFn允许用自定义函数替换默认实现(例如在创建任务前补充业务逻辑),实现在 crud.ts;
  • taskVotes示例故意只声明getAll,用于验证 Wasp 生成的代码不会包含用户未请求的操作——这是对"最小生成面"的测试用例,属于 contributor 场景下的边界验证。

5. 自定义 API:方法、命名空间与中间件

src/features/apis/apis.wasp.ts 覆盖了自定义 REST API 的声明方式:

api("ALL", "/foo/bar", fooBar, { middlewareConfigFn: fooBarMiddlewareFn, entities: ["Task"], }), apiNamespace("/bar", { middlewareConfigFn: barNamespaceMiddlewareFn }), api("GET", "/bar/baz", barBaz, { auth: false, entities: ["Task"] }), api("POST", "/webhook/callback", webhookCallback, { middlewareConfigFn: webhookCallbackMiddlewareFn, auth: false, }),
  • api声明支持指定 HTTP 方法(ALL/GET/POST)、路径、处理函数与可选配置;
  • apiNamespace可以为路径前缀统一注入中间件/bar下的所有 API 共享barNamespaceMiddlewareFn);
  • auth: false用于公开端点(如 webhook 回调);entities声明同样驱动缓存失效;
  • 中间件实现位于 apis.ts,配套测试 custom-apis.spec.ts。

6. 数据库:种子数据与 Prisma 设置函数

src/features/db/db.wasp.ts 演示了数据层的两个扩展点:

export const db: Db = { seeds: [devSeedSimple, prodSeed], prismaSetupFn: setUpPrisma, };
  • seeds区分开发种子devSeedSimple)与生产种子prodSeed),实现见 seeds.ts;
  • prismaSetupFn允许在 PrismaClient 创建时注入自定义设置(如日志、扩展),实现见 prisma.ts,并有 prisma-setup-fn.spec.ts 做端到端验证。

7. 其他特性:WebSocket、Streaming、预渲染、懒加载

main.wasp.tsspec中还导入了其余特性:

  • WebSocket:来自 chat.wasp.ts,通过webSocket配置与 webSocket.ts 实现实时聊天,测试见 websocket.spec.ts;
  • Streaming(SSE):streaming.wasp.ts 声明流式 API,StreamingTestPage.tsx 展示逐块接收响应,测试见 streaming.spec.ts;
  • 预渲染:prerender.wasp.ts 覆盖静态预渲染、带参数的预渲染实例与 hydration mismatch 场景,对应 prerender.spec.ts;main.wasp.tsroute("HomeRoute", "/", page(HomePage), { prerender: true })即首页预渲染示例;
  • 懒加载:lazyLoading.wasp.ts 演示 Eager/Lazy 两种加载模式,测试见 lazy-loading.spec.ts;
  • RPC 类型安全专项:src/rpcTests/ 通过 TS 与 JS 两套定义(definitions.ts 与 jsDefinitions.js)对比验证 Wasp 生成的 RPC 客户端在两种语言下的类型/行为一致性。

端到端测试:Playwright 双视口矩阵

kitchen-sink 的 e2e 测试是 Wasp 验证框架行为的主要手段。测试入口为:

npm run test

该脚本实际执行(见 package.json):

"test": "npm run test:install-deps && DEBUG=pw:webserver playwright test --config e2e-tests/", "test:install-deps": "playwright install --with-deps"

Playwright 配置要点

playwright.config.ts 中值得注意的设计:

  • 两个测试项目chromium(桌面 Chrome)与Mobile Chrome(Pixel 5 视口),覆盖响应式场景;
  • webServer 自动拉起:通过WASP_APP_RUNNER_CLI_CMDWASP_RUN_MODE(默认dev)、WASP_CLI_CMD(默认wasp-cli)三个环境变量拼出启动命令run-wasp-app dev --path-to-app=../ --wasp-cli-cmd=wasp-cli,等待localhost:3001就绪后开始测试,超时 180 秒;reuseExistingServer: !process.env.CI允许本地复用已运行的服务;
  • 部署模式:当WASP_RUN_MODE=deployed时不再自启 webServer,而是测试已部署的实例(PLAYWRIGHT_SERVER_URL指定地址);
  • CI 行为forbidOnlyretries: 2、单 worker、dotreporter 均为 CI 环境专用。

测试覆盖清单

e2e-tests/tests/ 下的 19 个 spec 文件与上文特性一一对应:auth.spec.tsauth-hooks.spec.tscustom-signup.spec.tsmanual-signup.spec.tsuser-api.spec.tsoperations.spec.tsserialization.spec.tsasync-jobs.spec.tscrud.spec.tscustom-apis.spec.tswebsocket.spec.tsstreaming.spec.tsprerender.spec.tslazy-loading.spec.tscatch-all-route.spec.tsprisma-setup-fn.spec.ts等,另有 mailcrab.ts 用于测试邮件类功能(验证邮件、密码重置邮件)。这让 kitchen-sink 成为名副其实的"特性回归测试中心"。

小结:如何用好 kitchen-sink

综合来看,kitchen-sink 的三种典型用法对应三条路径:

  1. 作为普通 Wasp 开发者:复制.env.server.example即可wasp install+wasp start db+wasp db migrate-dev+wasp start全流程跑通,把首页当作特性导航,逐个进入/tasks(Query/Action)、/crud(CRUD)、/jobs(后台任务)、/apis(自定义 API)、/chat(WebSocket)、/serialization(序列化)、预渲染与懒加载页面,感受 Wasp"声明即所得"的开发体验;
  2. 作为 Wasp 贡献者:通过../../waspc/run wasp-cli <子命令>用源码级 CLI 驱动应用,任何 CLI 改动都能立刻在此验证;新增特性时同步补充*.wasp.ts声明、源码实现与 e2e 测试;
  3. 作为测试基础设施npm run test一键跑完双视口 e2e 矩阵,配合env:pull/env:push共享真实密钥的团队工作流,构成 Wasp 仓库内闭环的质量保障体系。

无论从哪个角度切入,examples/kitchen-sink 都是理解 Wasp 框架能力边界与工程实践的最佳入口。

【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 3:46:07

lo 库 Fill 函数深度解析:基于 Go 1.18+ 泛型的切片克隆填充

lo 库 Fill 函数深度解析&#xff1a;基于 Go 1.18 泛型的切片克隆填充 【免费下载链接】lo &#x1f4a5; A Lodash-style Go library based on Go 1.18 Generics (map, filter, contains, find...) 项目地址: https://gitcode.com/GitHub_Trending/lo/lo Fill 是 lo 库…

作者头像 李华
网站建设 2026/9/13 3:45:02

如何为 p5.js 新方法添加参数校验的友好错误消息?

如何为 p5.js 新方法添加参数校验的友好错误消息&#xff1f; 【免费下载链接】p5.js p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core…

作者头像 李华
网站建设 2026/9/13 3:45:00

Web教师成果管理系统开发:Vue+SpringBoot实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华