Prisma prisma.yml 变量机制完全指南:env、self 与 opt 三种变量源详解
【免费下载链接】prisma1💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1
本文是 Prisma 服务定义文件
prisma.yml配置参考的一部分,系统讲解如何在prisma.yml中使用变量(Variables)动态替换配置值。你将掌握${env:...}、${self:...}、${opt:...}三种变量源的语法与适用场景,理解 CLI 加载环境变量的顺序与优先级,以及默认值的写法,并了解这些机制在prisma-yml包中的底层实现。读完后,你可以写出用环境变量管理密钥、用 self 引用复用配置、用 CLI 选项动态传参的高可复用prisma.yml。
本指南对应的原始文档位于 docs/1.2/04-Reference/02-Service-Configuration/02-prisma.yml/03-Using-Variables.md,变量解析的实际实现可参考 cli/packages/prisma-yml/src/Variables.ts。
变量机制概述:为什么需要变量
prisma.yml是 Prisma 服务的核心配置文件,其中包含服务名、stage、cluster、secret、datamodel 路径以及 subscriptions 等多项配置。在真实项目中,这些值往往需要随环境(开发、测试、生产)而变化,例如:
secret是服务级的 API 密钥,绝不能明文提交到代码仓库;stage、cluster在不同环境下指向不同的部署目标;- 订阅 webhook 的 URL 与请求头在不同环境各有不同。
变量(Variables)机制允许你在prisma.yml中用占位符动态替换这些配置值,把环境相关的差异从配置文件中抽离出去。
从源码看,变量解析发生在 Prisma CLI 读取并校验配置文件的阶段:yaml.ts中的readDefinition会先用js-yaml将文件解析为 JSON 对象,再实例化Variables并调用populateJson完成占位符替换,最后才用 JSON Schema 校验填充后的结果(见 cli/packages/prisma-yml/src/yaml.ts#L21-L58)。也就是说,变量替换发生在 Schema 校验之前,因此变量可以被用在prisma.yml的任意属性值中,包括secret、stage、cluster、subscriptions.*.webhook.url等。
变量语法基础
要在prisma.yml中使用变量,把值用${}括号包裹。括号内依次包含两部分,用冒号分隔:
- 变量源(variable source):指出这个值从哪里来;
- 变量名(variable name):在对应来源中查找的具体名字。
# prisma.yml yamlKeyXYZ: ${src:myVariable} # 变量源:变量名 otherYamlKey: ${src:myVariable, defaultValue} # 提供默认值作为第二个参数src可以是以下三种变量源之一:
- 环境变量(Environment variable):来自进程环境或
.env文件; - 自引用(Self-reference):引用同一
prisma.yml内其他属性的值; - 命令行选项(CLI option):来自执行
prisma命令时传入的选项。
注意:变量只能用于属性的值(values),不能用于属性的键(keys)。这一点在实现上也成立:
Variables.populateObject只对字符串类型的值做替换(typeof property === 'string'时调用populateProperty),并不会改写 YAML 的键名(见 cli/packages/prisma-yml/src/Variables.ts#L67-L76)。
底层实现中,Variables类用一组正则表达式识别不同的变量源(见 cli/packages/prisma-yml/src/Variables.ts#L11-L20):
| 正则 | 匹配的变量源 |
|---|---|
/^env:/g | 环境变量 |
/^self:/g | 自引用 |
/^opt:/g | CLI 选项 |
/,/g | 默认值(覆盖语法) |
环境变量:env:
使用环境变量时,括号内的值由两部分组成:
- 前缀
env: - 环境变量的名称
下面的示例中,example服务的stage、cluster、secret三个属性全部来自环境变量:
service: example stage: ${env:PRISMA_STAGE} cluster: ${env:PRISMA_CLUSTER} secret: ${env:PRISMA_SECRET} datamodel: database/datamodel.graphql使用环境变量的典型收益是:secret等敏感信息不再硬编码进prisma.yml,可以从外部环境注入。
环境变量的加载顺序
CLI 会从3 个位置加载环境变量,按如下顺序:
- 本地环境(local environment):当前 shell 进程中已有的环境变量;
--dotenv参数指定的文件:如果传入了--dotenv参数,则加载该文件中的变量;- 省略
--dotenv参数时:默认加载prisma.yml所在目录下的.env文件。
这一点在源码中得到印证:PrismaDefinitionClass.load调用dotenv.config({ path: envPath })加载.env文件,其中envPath来自命令行的--env-file参数(不同版本 CLI 中该参数名为--dotenv或--env-file),未指定时则使用process.env中的本地环境变量作为兜底(见 cli/packages/prisma-yml/src/PrismaDefinition.ts#L49-L84)。
以prisma deploy命令为例,其--env-file选项的官方描述就是 “Path to .env file to inject env vars”,并提供了-e短选项(见 cli/packages/prisma-cli-core/src/commands/deploy/deploy.ts#L58-L61):
prisma deploy --env-file ./.env从测试用例可以确认两种注入方式的行为:既有直接设置process.env.MY_TEST_SECRET的“本地环境变量”用例,也有在prisma.yml同目录创建.env文件(内容形如MY_DOT_ENV_SECRET=this-is-very-secret,and-comma,seperated)后由 CLI 自动读取的用例(见 cli/packages/prisma-yml/src/PrismaDefinition.test.ts#L80-L146)。注意该测试中.env的取值包含逗号,说明带逗号的取值仍可作为单个环境变量值被正确注入。
自引用:self:
你可以递归地引用同一prisma.yml文件内其他属性的值。使用自引用时,括号内的值由两部分组成:
- 前缀
self: - (可选)被引用属性的路径(path)
如果不指定路径,变量的值将是整个 YAML 文件对象。
下面这个示例中,createCRMEntry订阅复用了sendWelcomeEmail订阅的 query、webhook URL 与 headers:
subscriptions: sendWelcomeEmail: query: database/subscriptions/createUserSubscription.graphql webhook: url: ${self.custom.severlessEndpoint}/sendWelcomeEmail headers: ${self.custom.headers} createCRMEntry: query: ${self:functions.subscriptions.sendWelcomeEmail.query} webhook: url: ${self.custom.severlessEndpoint}/createCRMEntry headers: ${self.custom.headers} custom: serverlessEndpoint: 'https://bcdeaxokbj.execute-api.eu-west-1.amazonaws.com/dev' headers: Authorization: Bearer wohngaeveishuomeiphohph1lsself 引用的实现细节
自引用不仅能引用普通字符串,还能:
- 引用对象并整体注入:
${self.custom.headers}会把custom.headers这个对象(如Authorization头)整体作为值填入。底层实现中,如果取到的值是对象,populateProperty会递归调用populateObject继续解析其中的嵌套变量(见 cli/packages/prisma-yml/src/Variables.ts#L96-L104); - 与其他文本拼接:如
url: ${self.custom.severlessEndpoint}/sendWelcomeEmail,替换是“就地”完成的——非字符串值(数字等)会被转成字符串拼入原值(见 cli/packages/prisma-yml/src/Variables.ts#L132-L158); - 支持多层路径:路径按
.分隔逐级向下查找,getDeepValue会沿属性链递归取值,若取到的值本身仍是${...}占位符,还会继续解析(见 cli/packages/prisma-yml/src/Variables.ts#L223-L249)。
需要留意的是:文档示例中custom.severlessEndpoint(拼写如此)是文档原文,实际使用时请按你自己的属性名书写,例如custom.serverlessEndpoint。此外,prisma.yml的custom段在变量填充完成后会被删除(if (populatedJson.custom) { delete populatedJson.custom },见 cli/packages/prisma-yml/src/yaml.ts#L38-L40),它只作为变量引用的中间存储区使用,不会作为最终配置提交给服务端。
关于 “self 引用的路径起点” 补充说明
文档示例中createCRMEntry.query写的是${self:functions.subscriptions.sendWelcomeEmail.query},即以functions.为前缀;而同文件内实际配置段名为subscriptions(无functions前缀)。这属于文档示例与示例 YAML 结构不完全一致的情况。按实现逻辑(getValueFromSelf以self:之后的部分按.分割逐级查找,见 cli/packages/prisma-yml/src/Variables.ts#L223-L227),若要引用subscriptions.sendWelcomeEmail.query,应写作${self:subscriptions.sendWelcomeEmail.query}。因此在实际使用时,务必让self:后的路径与你prisma.yml中的真实属性结构保持一致,否则取值会变成undefined。
CLI 选项:opt:
你可以引用执行prisma命令时传入的 CLI 选项。使用 CLI 选项时,括号内的值由两部分组成:
- 前缀
opt: - CLI 选项的名称
例如:
service: example stage: ${opt:stage}对应在命令行中传入:
prisma deploy --stage dev此时prisma.yml中的stage会被替换为dev。CLI 选项的来源是命令解析后的flags对象——Variables构造时接收的options参数即来自命令的 args/flags,getValueFromOptions用opt:后跟的名字直接在选项中取值(见 cli/packages/prisma-yml/src/Variables.ts#L214-L221)。
默认值(覆盖语法)
你可以在变量后追加一个逗号和默认值,当变量在对应来源中找不到值时,使用默认值兜底:
# 当 env:MY_VARIABLE 不存在时,fallbackValue 会被使用 otherYamlKey: ${env:MY_VARIABLE, fallbackValue}其实现对应overwrite方法:把括号内以逗号分隔的多段值依次从各自的变量源取值,返回第一个“非空”的值(finalValue !== null、typeof finalValue !== 'undefined'且不是空对象),见 cli/packages/prisma-yml/src/Variables.ts#L161-L178。这实际上是一种“多个候选值按优先级取首个可用者”的机制,可用于实现“环境变量优先、本地默认值兜底”的配置策略。
变量未找到时的行为
如果某个变量在对应来源中找不到有效值(结果为null、undefined或空对象),CLI 不会直接静默失败,而是输出一条警告,形如:
A valid environment variable to satisfy the declaration 'env:PRISMA_SECRET' could not be found.warnIfNotFound会根据变量源类型(环境变量 / 选项 / 自引用)生成对应的警告文案(见 cli/packages/prisma-yml/src/Variables.ts#L251-L273)。因此在部署前应检查这些警告,避免配置值意外缺失。
变量解析全流程:从 prisma.yml 到最终配置
把上面的机制串起来,一次完整的变量解析流程如下(对应 cli/packages/prisma-yml/src/yaml.ts 与 cli/packages/prisma-yml/src/Variables.ts):
- CLI 读取
prisma.yml文本,用js-yaml解析为 JSON 对象; - 构造
Variables实例,传入文件路径、CLI 选项、输出对象与环境变量; populateJson深度遍历所有属性值,识别${...}占位符;- 按变量源分派解析:
env:→ 环境变量 /.env文件;self:→ 同文件属性路径;opt:→ CLI 选项;含逗号 → 默认值覆盖逻辑; - 解析后的值递归回填(自引用值可能嵌套其他变量);
- 删除仅用于存放引用值的
custom段; - 对填充后的完整配置执行 JSON Schema 校验,通过后进入后续命令流程。
最佳实践小结
- 敏感信息(
secret)一律用${env:...},配合.env文件或--env-file注入,避免明文入库; - 环境相关配置(
stage、cluster、endpoint)用${env:...}或${opt:...}区分开发/测试/生产环境; - 需要复用的配置(如 webhook 地址、请求头)用
${self:...}在文件内引用一次、多处使用,保持单一事实来源; - 使用
${src:name, defaultValue}提供兜底值,防止环境变量缺失时配置整体失效; - 牢记变量只能出现在属性值中,且
self:路径必须与prisma.yml真实结构一致; - 变量替换在 Schema 校验之前完成,因此使用变量不会绕过
prisma.yml的格式校验,非法填充结果依然会被拦截。
通过这三种变量源与默认值机制,prisma.yml得以从“静态配置文件”升级为“随环境与命令动态变化的声明式配置”,这也是 Prisma 多环境部署工作流的基础设施之一。
【免费下载链接】prisma1💾 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL & MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考