@ elumixor/ devkit
烤面包的Dev管弦乐手 一个配置列出平台 Mac shell,一个iPhone应用软件,一个手表应用软件——和三个命令做别人做过的三件事 他们:
devkit dev # run every platform side by side
devkit build # build every platform, in parallel
devkit deploy # ship every platform, in dependency order
每个都有一个平台: devkit dev:iphone, (中文(简体) ), devkit build:mac, (中文(简体) ), devkit deploy:web。 。 。 .
对于一个完成它们的外壳来说 位置也是 devkit build mac iwatch。 。 。 .
安装
bun add -d @elumixor/devkit
devkit update 移动全局 devkit 在一个项目内部运行,它依赖于最新的
已出版的版本(--dry 显示将发生什么变化.
配置
添加一个 devkit 块到根 package.json. 分三个阶段,每个阶段为平台名称图到一个
台阶,一个站台 意思是所有三个:
{
"scripts": {
"dev": "devkit dev",
"build": "devkit build",
"deploy": "devkit deploy"
},
"devkit": {
"generate": { "command": "bunx nitro-client", "cwd": "apps/backend" },
"dev": {
"web": {
"processes": {
"backend": { "filter": "@app/backend", "port": 3100 },
"frontend": { "port": 8081, "open": true }
}
},
"mac": { "command": "bunx tauri dev", "cwd": "apps/frontend", "needs": ["web"] }
},
"build": {
"web": { "type": "web", "options": { "apiPrefixes": ["api"] } },
"mac": { "type": "tauri-macos" }
},
"deploy": {
"mac": { "type": "tauri-macos" },
"web": { "type": "vercel", "needs": ["mac"] }
}
}
}
needs 就是这个命令足够了 命名一个平台也会运行它依赖的平台——
devkit dev:mac 启动网络堆栈 Mac 窗口点, devkit deploy:web 构建
安装站台先把手伸出来. 无步骤 needs 立刻开始.
generate 运行一次之前的构建或部署图, 领先一切平行运行。 这个
用于每个平台的编译读取的源 —— 从路由生成的 API 客户端
在另一所建筑读取时,不得由一所建筑书写。 它设置 SKIP_CLIENT_GEN=1 联 合 国
脚步它运行之前.
德维
devkit dev 释放港口,并肩运行一切。 一个平台是一个进程或一个
processes 地图——网络平台是客户端和API,两者都不值得命名为
自己来的.
在终端上,它画出一个板:每个进程的 URL 和状态(启动,准备在 1.2s 中,崩溃) 被固定 在顶端,下面的合并日志.
devkit dev · budget logs in .devkit/dev
● 1 web:backend http://localhost:3107 ready in 2.4s
● 2 web:frontend http://localhost:8087 ready in 2.1s
── all ─────────────────────────────────────────────────────────────────────────────
web:frontend │ VITE v8.3.0 ready in 1055 ms
web:backend │ [nitro] ✔ Nitro Server built in 521ms
1-2 focus a all o open r restart c clear jk ud gg G scroll v select y copy e errors q quit
日志卷轴喜欢 less数字 : j编号 :k 或以一行为箭头, u编号 :d 由半个屏幕, PgUp/ PgDn 由 a
屏幕, gg 到顶部 G 继续追踪. v (或 V)在底部开始一行选择
行; 用相同的键移动它 y 复制到剪贴板上, y 仅复制屏幕上的内容.
拖动鼠标也会选择,在指针位于日志上下时自行滚动,
和发行时的拷贝; 轮轴卷轴。 Hold option(macOS) 或 Shift 供终端自己选择 .
一个有堆叠的打印错误折叠成一行红色摘要(其信件,加数据库) detail
当有一个。 点击 [copy] 复制整个错误,或 [▸ N lines] 按钮以扩展;
e 扩展或折叠每个错误.
崩溃的过程留在棋盘上,直到您重新启动它 r其余的继续跑 任何地方
其他(代理人的外壳、CI、管子或 --plain它会打印前缀行:先打印URL,
之后为 a devkit 每一个准备就绪、崩溃和退出,以及一个 all ready: 列出每个 URL 的行.
无论哪种方式,每个进程的全部输出都在 .devkit/dev/<name>.log与 --open,每个 open
进程 URL 一旦其端口答案打开.
| 字段 | 含义 |
|---|---|
processes | 此平台下的几个进程, 按名键 |
filter | 明确 bun --filter <target> (进程密钥的默认值) |
cwd | 运行 bun run --cwd <cwd> <script> 改为 --filter |
script | 在工作空间运行的脚本( 默认) dev(中文(简体) ) |
command | 原始 shell 命令, 覆盖以上( 例如 ). vite dev(中文(简体) ) |
type | a 内置dev目标——见下文 |
port | 开始释放,显示在板上, 并授意告诉何时准备好 |
needs | 必须运行的平台 |
color | 标签颜色; 选择其它颜色 |
open | 与 --open时打开此进程的 URL |
内设目标
capacitor-ios 对运行中的dev服务器运行模拟器上的iPhone应用. 网页视图
在网络上装入页面,而不是从捆绑中装入页面,所以每个网页编辑都是实时的
维特有 原生编辑仍然需要编译——这就是 watch 这是为.
"iphone": {
"type": "capacitor-ios",
"needs": ["web"],
"options": {
"project": "apps/frontend/ios/App/App.xcodeproj",
"scheme": "App",
"bundleId": "com.example.app",
"device": "iPhone 17 Pro",
"port": 8081,
"watch": ["apps/frontend/ios/App/App"]
}
}
xcode-sim 建立任何苹果计划,并在一个模拟器上发布,而不打开Xcode. A 类
watch app 没有自己的登录 所以 previewEnv 是什么让它运行在一个模拟器 没有
配对电话; --real 离开它未定 和真正的API谈话.
"iwatch": {
"type": "xcode-sim",
"options": {
"project": "apps/frontend/ios/App/App.xcodeproj",
"scheme": "BalanceWatch",
"sdk": "watchsimulator",
"bundleId": "com.example.app.watchkitapp",
"device": "Apple Watch Series 11 (46mm)",
"previewEnv": "APP_WATCH_PREVIEW",
"watch": ["apps/frontend/ios/App/WatchApp"]
}
}
--device,或 DEVKIT_SIM_DEVICE,覆盖已配置的模拟器——每个人的列表
已安装的系统不同。 保存被监视的源重建并重新启动; 斯威夫特没有热重装,所以
这就是"活"在本土的意思.
建设和部署
双方画出同一块板子:每站台一行一行,有回旋器,运行时间有多长
它打印的最后一行。 全部输出到 .devkit/<phase>/<platform>.log,尾部则
末端打印出任何失败的平台——发行版打印出上万行,以及
连结他们都是无法读取的。 管道输出( CI, 日志文件) 获得前缀流线
换句话说.
devkit build # every platform
devkit build:iphone # one platform, plus whatever it needs
devkit deploy --dry # print the plan
devkit deploy --verbose # stream every line instead of the live board
| 字段 | 含义 |
|---|---|
command | 执行此步骤的 shell 命令 |
type | 内置目标,由 options |
needs | 必须先完成的平台 |
color | 此平台线条的颜色; 否则会选择一个 |
每个本地外壳都携带自己的网络应用复制品,使用自己的API基址来构建,以及
devkit build 管理彼此相邻的建筑物 BUILD_DIR, (中文(简体) ),
KIT_DIR 财务报告和审定财务报表 VITE_CACHE_DIR 而不是半途而废.
内建目标
web 将客户端的网络应用程序和一个Nitro API 装入一个 Vercel 部署: 该应用程序为
静态文件,API作为它们背后的一个无服务器功能. 相同的来源, 所以网络客户端
调用无 CORS 的 API.
| 选项 | 含义 |
|---|---|
frontendDir | web app dir, 运行时使用 bun run build (默认) apps/frontend(中文(简体) ) |
backendDir | Nitro dir( 默认) apps/backend(中文(简体) ) |
webBuildDir | 网络在其中建地 frontendDir (默认) build(中文(简体) ) |
apiPrefixes | aPI 所拥有路径; 应用 shell 的所有其他路径答案 |
include | 将 dirs 与 web 文件一起运行, 如 { "<source>": "<url path>" } |
tauri-macos 构建 macOS 应用程序, 而不是其他 —— 没有开发者 ID, 没有公证, 没有
安装。 它回答“做Mac shell 仍针对这个前端编译”;运输是部署
同名目标。 选项 : frontendDir, (中文(简体) ), bundles (默认) app, (中文(简体) ), webSuffix。 。 。 .
capacitor-ios 构建网络捆绑,同步到 Xcode 项目并编译 iOS app
对于一个模拟器——整个链条一个"测试Flight"的放出通过,减去签名和
上传. 选项 : frontendDir, (中文(简体) ), iosDir, (中文(简体) ), webSuffix附加时 project, (中文(简体) ), scheme, (中文(简体) ), configuration, (中文(简体) ),
sdk, (中文(简体) ), derivedDataDir。 。 。 .
xcode 为模拟器编译一个方案: 手表应用程序、 部件、 任何携带的本地工具
没有自己的网络捆绑。 选项 : project, (中文(简体) ), scheme, (中文(简体) ), configuration, (中文(简体) ), sdk, (中文(简体) ), derivedDataDir。 。 。 .
模拟器的构建是通过签名来编译的 所以一台从未见过团队的机器 提供配置文件仍然可以告诉你应用程序是否正在编译 .
内设部署目标
vercel 在此构建并上传已完成的输出, 而不是将 Vercel 重播和
等待它再造同样的东西。 选项 : cwd。 。 。 .
aws 是Devkit Cloud:同一个网页构建,服务于我们自己的AWS账户而不是Vercel.
静态文件到 S3, Nitro API 到共享 CloudFront 后面的 Lambda 函数
发行,舞台直播 <project>.devkit.atmagaming.com (或 <project>-dev.… 页:1
development) (中文(简体) ). 见 德维基特云。 。 。 .
tauri-macos 如果此机器有开发者ID, 则构建、 签名和公证 macOS app
证书,分级 DMG 和网络部署的列表,并刷新本地
如果有一个安装。 选项 : frontendDir, (中文(简体) ), stageDir, (中文(简体) ), installIfPresent应用程序存储器
连接 key env var 名称 .
fastlane-ios 以已部署的 API 构建网页捆绑, 同步到 Xcode 项目
然后将存档交给快行道,快行道负责在应用程序、手表应用程序和部件上签字并上传到
试取"Flight". 选项 : frontendDir, (中文(简体) ), iosDir, (中文(简体) ), lane, (中文(简体) ), defaultApiBaseUrl, (中文(简体) ), apiBaseUrlEnv,则
key env var 名称.
德维基特云
我们的Vercel替换:一个部署目标加上少数AWS服务,没有运行 在请求之间。 一个 CloudFront 分布为每个项目服务;一个 CloudFront 函数读取 该主机名的路由记录来自 KeyValueStore , 并将请求发送给工程的 Lambda API 路径的函数 URL, 或者在 S3 中部署的前缀 。 每次部署都是 不可改变的——它自己的S3前缀和Lambda版本——所以回滚是两个写作.
"deploy": {
"web": {
"type": "aws",
"options": {
"project": "kenoverse", // default: the repo name
"apiPrefixes": ["api"],
"routing": "spa", // spa | pages | ssr
"memory": 512, "timeout": 120, // MB, seconds
"crons": [{ "path": "/api/cron/sync", "schedule": "*/5 * * * *" }],
"domains": { "production": ["kenoverse.app"], "development": [] },
"predeploy": "bun run db:migrate"
}
}
}
headers 按路径设置响应信头, 如 vercel.json 使用,并使用一个 vercel.json 块
按原样粘贴( u) :[{ "key", "value" }])或平面图. source 是Vercel的语法 : :name 是一个
部分, :name* 任何深处, ( ) 一个生的Regex。 路由器在出道时加了它们 缓存点击
他们随部署而改变,随部署而退。 适用于2xx和3xx
仅回复(CloudFront在源错误上不运行函数),并最多编译到1 KB.
"headers": [
{ "source": "/bar.js", "headers": { "Access-Control-Allow-Origin": "*", "Cache-Control": "public, max-age=300" } },
{ "source": "/icons/(.*)", "headers": { "Access-Control-Allow-Origin": "*" } }
]
"apiPrefixes": [] 建立静态网站:无硝基建构、无功能、作用、时间表或健康
检查,只有文件。 无前端 build 脚本已按原样分发,所以文件夹中包含
手写文件是 "frontendDir": ".", "webBuildDir": "public"。 。 。 .
A 类 domains 以 *. (说) *.desk.atmagaming.com)只添加通配符别名
分布 : 它下面的每个主机名然后骑一个证书名, 以此保持共享
aCM每证名配额下的证书. 在它覆盖的主机旁边列出它.
DNS不在 Cloudflare 上的域仍然有效: 部署打印证书的验证
CNAME和记录指向发行,等待验证,并为主机服务一次
它的DNS点在那里。 克鲁斯称他们的道路 Authorization: Bearer $CRON_SECRET时
首先部署.
devkit deploy 构建:调和函数、作用、日志组、URL、调度和域;
上传静态文件( 未更改的文件被复制服务器侧); 发布新函数
版本; 运行 predeploy 与舞台的入门; 引用新版本的 /api/health; 仅限
然后移动 live 别名和路由记录。 一次健康检查失败 留下了旧的部署
服务. main 部署 production, (中文(简体) ), develop 部署 development· ; --stage 手取来.
devkit cloud bootstrap # once per account: buckets, edge, roles, budgets ($5 and $20)
devkit cloud init # once per repo: the aws target and .github/workflows/deploy.yml
devkit cloud env push # the root .env into the stage (SSM Parameter Store)
devkit cloud status # what is live, with calls, errors and p95 for the last 24 h
devkit cloud logs --follow # CloudWatch logs for the stage
devkit cloud deploys <project> # the last ten deploys
devkit cloud rollback <project> # back to the previous deploy, in seconds
devkit cloud infra apply # Terraform in infra/, mapped outputs into each stage's env
devkit cloud domains add <project> <host> # cert, alias, Cloudflare DNS, route; later deploys keep it
devkit cloud destroy <project> --stage development
数据库和任何其它 平台不能让自己停留在Terraform中。 点 每个阶段输出的模块和名称:
"terraform": {
"dir": "infra",
"env": {
"production": { "DATABASE_URL": "production_database_url" },
"development": { "DATABASE_URL": "develop_database_url" }
}
}
devkit cloud infra plan 显示变化, apply 将它们复制到SSM中,
sync 只有副本。 接下来的部署会读取它们 就像其它的外壳; CI不需要Terraform
证书。 函数本身必须调用的资源( 队列、 表格) 也需要 permissions。 。 。 .
Env vars 住在 SSM 地点: /dk/<project>/<stage>/<KEY> 并被复制到部署时的函数中,
进入建筑物的环境,所以 VITE_* 值也到达 CI 前端。 在职能方面,
import { waitUntil } from "@elumixor/devkit/runtime" 在回复后继续引用
(代表韦尔塞尔的) waitUntil 当代码仍然运行在那里时),以及
import { put, list, del, head, createUploadUrl } from "@elumixor/devkit/blob" 覆盖我们过去的东西
联 合 国 @vercel/blob: 公共blobs服务于 https://<host>/_blob/<path>。 。 。 .
CI假设 dk-deploy 角色通过 GitHub 的 OIDC 提供者,所以没有 AWS 密钥存储在任何地方.
bootstrap 并写入范围 devkit 从笔记本电脑上部署的 AWS 配置 . examples/hello
练习每个特性和是什么 .github/workflows/deploy-cloud.yml 部署.
电线板和MCP
devkit.atmagaming.com (中文(简体) ) (单位:千美元)发光器/台式计算机, (中文(简体) ),
a SvelteKit app in the speek room's style)显示每个项目和
舞台,什么是活的,最后一天的电话,错误和p95,部署历史和功能
木头。 它本身就是平台上的一个项目;其功能可能读取部署记录,Cloud Watch
指标和指标 dk-* 日志组通过 permissions 选项。 登记是办公桌的办事员
(原始内容存档于2018-10-21) (中文(简体) ). Clark's Frontend API at clirk.desk.atmagaming.com 与devkit.atmagaming.com同地,
因此,会话没有卫星域而结转。 API 接受电子邮件打开的会话
DASHBOARD_EMAILS,或 DASHBOARD_TOKEN 作为脚本的携带者. 只读:部署和回滚
留在CLI和MCP.
devkit mcp 与《示范背景议定书》相同 -- -- cloud_status, (中文(简体) ),
cloud_deploys, (中文(简体) ), cloud_logs, (中文(简体) ), cloud_rollback, (中文(简体) ), cloud_env (只有钥匙), cloud_domains, (中文(简体) ),
cloud_domain_add 财务报告和审定财务报表 cloud_domain_remove 这样啊
特工可以检查和撤销部署。 登记一次:
claude mcp add --scope user devkit-cloud -- devkit mcp
permissions 编辑 aws 目标附件 IAM Allow 函数对应用的作用的语句
读取其它 AWS 资源; 其他所有东西都保留默认角色(它自己的日志和blob)
只有前缀).
版本数
devkit version 读取一个版本,并把它写入其他文件 宣布一个,所以
App Store,安装器和设置底部的数字无法相去甚远.
"devkit": {
"version": {
"source": "apps/frontend/src-tauri/tauri.conf.json",
"packages": ["package.json", "apps/frontend/package.json"],
"cargo": ["apps/frontend/src-tauri/Cargo.toml"],
"xcodeProjects": ["apps/frontend/ios/App/App.xcodeproj/project.pbxproj"],
"marketingVersionPlists": ["apps/frontend/ios/App/App/Info.plist"],
"plists": ["apps/frontend/ios/App/WatchApp/Info.plist"]
}
}
Xcode 项目中的目标读取 $(MARKETING_VERSION) 从项目,所以他们的列表是
而不是一个数字 plists 用于用剧本连接的目标,没有
这样的设置和携带数字本身.
devkit release <prefix> 标记当前任务 <prefix>-v<timestamp> 并按下标签
如何释放线人.
装一台机器
Repo通常在运行前需要几个被取出的文件—— .env, (中文(简体) ), infra/terraform.tfvars ——这些都无法从宿主那里取回. Vercel, 单是存储 Terraform 管理的变量只写, 并把它们从 vercel env pull 作为 空字符串看起来像它的工作, 悄悄地留给你一个 .env 满是空白.
所以devkit在私密的Repo中同步它们本身,加密. 在新机器上,整个设置是:
gh auth login
devkit clone elumixor/puretype # clone, decrypt secrets, install, terraform init
clone 第一次要求你的秘密密码句,然后缓存它——那台机器不会再问你了.
宣布要同步和运行什么:
"devkit": {
"setup": {
"secrets": [".env", "infra/terraform.tfvars"],
"env": [{ "file": ".env", "example": ".env.example" }],
"terraform": "infra",
"steps": ["bun --filter backend prisma:generate"]
}
}
| 键 | 含义 |
|---|---|
secrets | 要同步、加密、通过 devkit secrets push 编号 : pull |
secretsRepo | 私藏( 默认) elumixor/secrets(中文(简体) ) |
env | 嵌入文件以验证所犯 .example ——缺失 或为空 键失败 |
terraform | 目录到 terraform init如果没有,则跳过 terraform.tfvars |
install | 运行 bun install (默认真实) |
steps | 要运行的 shell 命令, 顺序 |
setup 拒绝以空白值继续。 一个缺失的秘密 读作 "" 不然的话 以后会变成一个无关紧要的虫子.
密码句
每个项目的秘密被装入一个AES-256-GCM捆绑(<project>.enc)在密语repo中,用从单个密码句中通过scrypt得到的密钥加密. 阅读它们不需要其他东西——没有密钥文件,没有密钥链,没有外部的二进制——所以这在任何OS上都有效.
- 第一届
secrets push对于一个项目,要求密码句两次, 捕捉一个你永远无法恢复的打字. - 然后缓存在
~/.config/devkit/passphrase(模式600),所以你每台输入一次. DEVKIT_PASSPHRASE两者都推翻,为CI.- 在GCM的认证标记上,错误的密码句响亮地失败了;它不能默默地产生垃圾.
在密码管理器中保留密码句 . 它是唯一的东西 站在一个新鲜的笔记本电脑 和你的秘密之间, 唯一的东西 如果丢失无法恢复.
更改a .env运行 devkit secrets push,或者下一个机器得到一个 stale 副本.
纸箱
devkit dev [platforms...] [--open] [--dry]——运行dev进程.devkit自己也一样.devkit build [platforms...] [--dry] [--verbose]——建设平台,平行建设.devkit deploy [platforms...] [--dry] [--verbose]——以依附顺序运送平台.devkit clone <owner/repo> [dir]——克隆,解密秘密,运行设置.devkit setup [root] [--dry]验证秘密,安装,terraform init运行阶梯.devkit version——将源版本写入每个声明一个的文件.devkit release <prefix>标记此承诺<prefix>-v<timestamp>并推进它.devkit secrets push|pull [root]同步加密机密.free-port <port>- 杀死在港口上听的任何东西(手在predev) (中文(简体) ).
任何一项 dev, (中文(简体) ), build 财务报告和审定财务报表 deploy 还取一个平台作为后缀—— devkit build:mac - 这是
读起来最好 package.json 剧本.