@env-spec
我们正在积极寻找关于@env-spec的反馈. 请分享你的想法和想法 RFC (RFC ) (法语)。 。 。 .
@env- spec 是一个简单的DSL/语言,可以扩展普通多腾v语法,允许您:
- 使用结构化元数据添加
@decorator样式注释类似于 联合来文文件 - 通过函数调用将设置值的语法正规化
以下是一个简短的例子:
# Stripe secret api key
# @required @sensitive @type=string(startsWith="sk_")
# @docs(https://docs.stripe.com/keys)
STRIPE_SECRET_KEY=fetchSecret("stripe/secret-key")
图书馆可以利用这种结构化数据提供:
- 额外的验证,强制,类型安全 您的env vars
- 处理过程中的额外护卫铁路
@sensitive数据 - 没有附加应用程序代码或配置文件的更灵活的加载逻辑
如何使用计划数据?
这种计划信息在团队成员和机器之间共享时最有价值——所以它打算用于一个致力于git的文件中.
在大多数情况下,这将意味着建立一个 .env.schema,致力于源控制,其中包含所有计划信息以及可能的一些默认值.
这和拥有一个 .env.example file - 它只是更有用,并且实际上将它融入了env加载过程.
然后您可以使用设置值的附加文件 - 当然,它们可以添加附加项目或现有项目的压倒性 .
您是否想要使用单个 git- ignored .env 文档,或应用环境专用文件的级联(例如, .env, (中文(简体) ), .env.local, (中文(简体) ), .env.test等)由你决定.
然而,使用函数的新能力要求安全地解密数据,或者从外部来源装入值,意味着你可能会被诱惑使用承诺 .env 文档更多.
一个已启用的env spec工具将适当加载所有 env 文件, 合并了 schema 和 值, 以及从 shell/ process 读取的额外值 . 然后将采用可转换/填充值的图案,例如从外部来源解密或取出,以及实施强制和验证.
QQ 在一个非常简单的工程中,您也可以想象使用一个既包含计划又包含值的单个已承诺的.env文件,并利用函数调用来安全地加载敏感信息.
向后兼容
这个设计大多是向后兼容传统的.env文件,然而没有标准.env spec,各种工具的规则和特征略有不同,因此我们作出一些决定来尝试使事物标准化. 如果用户想要选择与其它工具相匹配的特定行为,工具可以支持额外的相容性标记.
扩展特性集指一个已启用的env spec spec parser将成功解析其他工具可能不会解析的env文件.
这是什么 这个 包裹?
此软件包定义了用于解析的解析器和相关工具 @env- spec 启用了 .env 文件.
它并没有提供任何经过这个解析步骤的东西——比如实际加载环境变量.
在 .env 文件中实际使用的工具,请查看 https://varlock.com (中文(简体) )
语言语法参考
这是关于env-spec语言本身细节的参考. 这里我们不假设特定装饰者的含义,或函数调用.
评论
Env- spec( 如 dotenv) 中的评论起始于 a #. 评论可以自行进行,也可以在某行行后进行.
# this is a commentKEY=val # so is this# but this is invalid
我们赋予这些评论更多的意义,让它们包含: @decorators 并把它们附在具体配置物品上.
Comment
常规评论是一个不从 @
- 铅白空间是可选的 --
#these, (中文(简体) ),# are, (中文(简体) ),# all valid - 里面的装饰被忽略了..
# this @decorator is ignored
DecoratorComment
装饰者评论是一个以 @ 并包含装饰器
- 它可能包含一个或多个装饰器 --
# @type=integer, (中文(简体) ),# @sensitive @required - 在装饰者之后可能还会有额外的经常性评论 --
# @sensitive=false # key is published in final build
Divider
分隔符是作为分隔符的注释,如水平行
- 以
---或者说===被视为一个分隔符 --# ---, (中文(简体) ),# === - A 类 单人 领导空白是可选的 --
# ---, (中文(简体) ),#--- - 之后的任何事情都被忽视和有效 --
# --- some info, (中文(简体) ),# ------------
CommentBlock
评论块是一组连续的评论,不附在特定配置项上.
- 注释块以空行结束, a
Divider,或文件的结尾. - 两者
DecoratorComments 和RegularComments 可能为相通
DocumentHeader
如果有的话 CommentBlock 结尾为 Divider 作为文件的第一个要素,它将被视为标题.
- 此信头中的装饰器可用于配置所有包含的元素, 或者装入过程本身
装饰者
A 类 Decorator 用于在注释中附加特定配置项目或整个文档和加载过程的结构化数据.
- 每个装饰器都有一个名称和可选值 --
@name=value - 只使用名称等于设置值为真 --
@required===@required=true - 将使用通用的值处理规则解析装饰值(见下文)
有效的装饰示例 :
# @willBeTrue @willBeFalse=false @explicitTrue=true @undef=undefined
# @int=123 @float=123.456 @willBeString=123.456.789
# @quoted="with spaces" @trueString="true"
# @singleQuote='hi' @backTickQuote=`hi`
# @withNewline="new\nline"`
# @funcCallNoArgs=func() @dec=funcCallArray(val1, "val2") @dec=funcCallObj(k1=v1, k2="v2")
无效的装饰示例 :
# @
# @int=
# @spaceNeedsQuotes=spaces without quotes
# @noNewLines="new
# laksdjf"
配置项目
配置项定义了单个的env vars. 每个都有一个密钥,一个可选值,以及可选的附加注释.
- 键必须从[a-ZA-Z ]开始,然后是任何[a-ZA-Z0-9 ] -- -- ++
SOME_ITEM时BAD-KEY时2BAD_KEY - 不允许设置任何值, 将被视为
undefined- 说吧UNDEF_VAR= - 允许空字符串..
EMPTY_STRING_VAR="" - 单行值可能以引号包裹,也可能不是,并将遵循共同的值处理规则(见下文)
- 多行值可能包含在其中之一
( " | """ | ``` ) - 只有评论 直接 在该项目之前
- 不过a
Divider将会将上述注释分解为CommentBlock与项目无关 - 可在项目后另出评论
ITEM1=foo # post comment - 后评论可以包含装饰器
ITEM1=foo # @required
行终
文件可能使用 \n 或者说 \r\n 线尾。 两者受到相同的对待,因此所分析的数值无论哪种方式都是相同的. 节点和语法错误位置( offset, line, 栏) 总是指您通过的内容, 包括任何 \r 字符键.
共同价值管理规则
对于配置项目值、装饰器值和函数调用参数内的值,对数值作类似的解释。 数值可能用引号包裹,也可能没有,但处理方式略有不同.
- 值可能永远不会包含实际的新行,但可能包含字符串
\n - 如果数值不包含空格, 则不必用引号来包裹
- 未引用的值也可能不包含其他字符,视上下文而定:
ConfigItem值可能不包含[ #]Decorator值可能不包含[ #]FunctionCall参数可能不包含[ ,)]
- 未引用的值将强制
true, (中文(简体) ),false, (中文(简体) ),undefined- 说吧@foo=false - 未引用的值会强制数字值 --
@int=123 @float=123.456 - 否则未引用的值将被视为字符串
- 引文中的值为 永远 作为字符串处理 --
@d1="with spaces" @trueString="true", (中文(简体) ),@numStr="123" - 所有引用样式
[`'"]没事了..@dq="c" @bt=`b` @sq='a' - 与包装引用样式相匹配的已逃出引号是OK --
@ok="escaped\"quote" - 在被引用的数值中,字符串
\n将转换为实际新线
函数调用
如果一个值没有被引文所包裹, 并且看起来像一个函数调用 - 例如 varlock(ASDF123...) - 我们会把它解释为一个 FunctionCall。这与配置项目值和装饰值都相关.
- 函数名称必须从字母开始,然后可以包含字母、数字和下划线
/[a-ZA-Z][a-ZA-Z0-9_]*/ - 函数参数总是被解释为数组或对象
- 无法通过参数、单个值或多个值
- 或您可能通过密钥值对, 参数将被解释为对象
- 每个值将使用共同的值处理规则进行解释(见上文)
实例:
# @noArgs=fn()
# @oneArg=fn(asdf) @oneArgQuoted=fn("with quotes")
# @multipleArgs=fn(one, "two", three, 123.456)
# @objArgs=fn(key1=v1, key2="v2", key3=true)
与多滕v/多滕v-扩展/多滕vx的显著差异
- 我们不支持 筑巢 默认扩展( ex :
VAR=${FOO:-${BAR}}- 相反,你可以使用
fallback直接函数VAR=fallback(ref(FOO), ref(BAR))
- 相反,你可以使用
- 我们不支持 未回避 执行扩展范围内的引用( ex:
VAR="$(echo "foo")"(中文(简体) )- 我们支持后置引用, 逃脱引用, 或者你可以使用
exec直接函数VAR=exec(echo "foo")
- 我们支持后置引用, 逃脱引用, 或者你可以使用
$(...)扩展支持嵌入括号并引用)(单位:千美元)$(jq -r '.address|join(".")')(中文(简体) )
本地 dev 和测试工作流程
bun run dev- 建造和观看一切bun run test构建全部, 运行测试, 并监视更改以重新运行bun run test:ci只要建立和运行测试一次
如果您需要通过额外的旗帜进行vitest( 例如运行特定的测试/ 文件)
运行 bun run dev:grammar 在一个终端和 bunx vitest ... 在另一个
设置 PEGGY_TRACE=1 将允许在 已构建的语法文件。 。 。 .