@ dbx 工具/ 核心
使用共享节点和 Bun 帮助器进行分层配置, 二进制安装 , 进程执行、锁定和项目发现。 浏览器安全公用设施 @dbx-tools/ 共享核心。 。 。 .
快开始
通过共享环境和项目文件规则解决范围设定:
import { configUtils } from "@dbx-tools/core";
const publicDomain = configUtils.string(undefined, "PUBLIC_DOMAIN", {
prefix: "TUNNEL",
});
使用此软件包用于:
- 以一致的 stdio 处理同步和同步进程执行 .
- 中止对长期运行的子进程的信号支持 .
- 为命令字符串切换类似 shell 的小参数, 必须成为 argv 数组.
- 从软件包管理文件、git元数据中发现的工作空间/项目根 当前的工作目录.
- 与本地文件系统同步的 Databricks 捆绑 App- 资源流 逆向和CLI解析配置.
- 安全文件系统 Stat、主机路径封存和项目命名帮助者 CLIs和projen合成器.
- 从进程内嵌分层配置, 环境特有
.env文档和 数据砖捆绑的 Appconfig.env。 。 。 . - YAML/JSON品牌文字发现并加载共享Zod验证.
- 同上,有zip/tar提取和原子安装的可执行下载.
- 带有一个可移植的 Stale- recelling 锁目录的跨进程文件锁 bun和Node共享的协议.
- 在主线和工人线上相互排斥.
- npm 来自内存的依赖分辨率
package.json反对: 已配置注册 .
安装二进制
import { join } from "node:path";
import { bin } from "@dbx-tools/core";
const executable = await bin.ensure("tool", releaseUrl, {
autoUnpackage: true,
minVersion: "1.2",
selector: ({ source }) => join(source, "tool"),
});
bin.ensure() 安装到 $HOME/.<name>/bin/<name> 返回其属性 root, (中文(简体) ),
binDir执行文件 path。通过 destination 提供准确路径
对于不同的布局。 已存在的可执行文件返回, 所以
uRL 解析器仅在需要安装时才调用。 同时
调用者使用带有检查锁-检查加载序列的文件锁,防止
跨进程和工人线程的重复下载.
锁定后,一个函数 URL 接收 { tempDir } 所以本地安装器可以
在目录下写 直接的HTTP下载是默认选择的. A 类 file:// URL为
复制时不取取或解开。 Zip, tar, tar.gz, 和 tgz 档案可以
自动解开。 单文件归档不需要选择器,而
选择器可以从更大的归档中选择二进制 。 选中的文件是
已正常化为模式 0755 并且必须报告一个可接受的版本,然后才能
解剖学已经进入原地 最终重命名路径运行相同的验证
在返回之前再次出现.
每位候选人都参加 --version 在它被接受之前。 设定
versionArgument 提出不同的论点 minVersion 需要部分
或完整的数值底,例如 1, (中文(简体) ), 1.2,或 1.3.5默认解析器
先搜索 stdout,再搜索 stderr. 它接受一到三个数字成分
带有常见 npm/ Python 后缀, 如 1.2.3-rc.1, (中文(简体) ), 1.2.3rc1,或
1.2.3.patchdev具有更多组成部分的候选人排名第一,然后是最高的
数字候选人获胜。 供应 versionParser({ stdout, stderr }) 用于另一个
输出格式.
成功安装 URL 和 目的地 路径 .
证书、查询参数和碎片从URL中删除。 设定
LOG_LEVEL=debug 追踪访问检查,版本决定,锁定,下载,
归档提取和选择.
装入品牌上下文
import { brandFiles } from "@dbx-tools/core";
const context = await brandFiles.loadBrandContext();
loadBrandContext() 搜索已知 npm/ git 项目根
branding/brand.yaml, (中文(简体) ), .yml,或 .json,然后是等同的根级
文档。 缺少的文件返回完整的 dbx-tool 默认上下文 。 错误
文件失败验证 。 使用 loadBrandContextFile(path) 用于明确文件,以及
resolveBrandAssetPath(path, asset) 用于相对资产参考.
解析配置
import { configUtils } from "@dbx-tools/core";
const publicDomain = configUtils.string(undefined, "PUBLIC_DOMAIN", {
prefix: "TUNNEL",
});
const timeoutMs = configUtils.positiveInt(undefined, "TIMEOUT_MS", 30_000, {
prefix: "SEARCH",
});
解脱是懒惰的 总是跟随 data,进程内, .env数据砖
捆绑配置,然后 app.yaml 编号 : app.yml 内置值。 默认
DBX_TOOLS 范围和可选能力前缀生成诸如
DBX_TOOLS_TUNNEL_PUBLIC_DOMAIN,则
TUNNEL_PUBLIC_DOMAIN,则 PUBLIC_DOMAIN。 。 。 . .env.production 财务报告和审定财务报表 .env.prod
检查之前 .env 何时 NODE_ENV=production2. 开发用途
.env.development 财务报告和审定财务报表 .env.dev。 。 。 .
通过一个配置地图或一系列地图 data。第一个匹配值
默认在环境查找前获胜。 当习惯 sources 命令省略
config,通过的数据仍然被读取,并最后附上。 这让一个打电话的人
首先在不意外丢弃其倒置配置的情况下 :
const endpoint = config.resolveValue("lakebaseEndpoint", {
data: { LAKEBASE_ENDPOINT: flags.endpoint },
sources: ["env", "dotenv", "bundle", "app"],
});
resolveValue() 尝试精确、大写和符号化的上下文表格
environmentKeys() 在应用正常范围和前缀扩展之前.
套装搜索运行 databricks bundle validate --output json 之前才开始
来源丢失。 它读取了单 App 的字面值 config.env,接受
从失败的验证中可以使用部分 JSON, 并尊重正在运行的 Databricks
简介。 已解析的多腾v记录被文件路径缓存. 解析后捆绑输出为
由捆绑路径加配置缓存 。 App YAML 搜索仅在捆绑完成的情况下运行
不解析密钥并读取 env[].value 条目。 套装 value_from 应用程序
也门 valueFrom 引用
sql_warehouse, (中文(简体) ), genie_space,或 postgres 资源.
配置文件发现和解析结果为每个源密钥的单试:
找到路径, 缺少文件, 空记录, 无效记录,以及 undefined
结果全部缓存。 根捆绑 variables 不是一个配置源 。 他们是
输入输入到捆绑的目标、资源和路径中,
因此读取一个进程设置会解析部署的 App 从未看到的名称 .
引用变量来自 config.env 把它变成一个.
Bundle 搜索不与 AppKit 安装或执行上下文相配合 。 若为
本地开发时丢失先前的源, 配置的工作目录
包含捆绑,并启用捆绑读取,验证运行。 一直这样
启动前调用器, 如 @dbx-tools/appkit 相同的自动配置
作为CLI和普通节点消费者的决定性路径.
部署的 Apps 跳过 Dotenv, 捆绑, 以及 app YAML 后检查
environmentUtils.isDatabricksAppEnv() 从 @dbx-tools/shared-core 承认
需要的 App 名称、 HTTP( S) 主机和有效端口, 或 Apps 容器来源
树。 设定 DBX_TOOLS_DATABRICKS_APP_ENV=true 或者说 false 迫使这个结果.
未识别值将自动检测到位.
DBX_TOOLS_CONFIG_DOTENV, (中文(简体) ), DBX_TOOLS_CONFIG_BUNDLE,以及
DBX_TOOLS_CONFIG_APP 独立地强迫文件来源打开或关闭。 A 类
识别布尔语优先于 App
运行时间检测,所以 true 可以在 App 中启用本地源 false
可在本地发展期间加以抑制。 缺失或未识别值保留
默认: 在 App 外读取文件并跳过其中 。 Bundle 读取
也默认当 NODE_ENV=production设置
DBX_TOOLS_CONFIG_BUNDLE=true 选择进行捆绑验证.
使用 config.string(), (中文(简体) ), boolean(), (中文(简体) ), positiveNumber(), (中文(简体) ), positiveInt(), (中文(简体) ),
port(),以及 list() 用于规范输入选项和基于文本的配置
通过一条规则. config.port() 从1到65535年只接受TCP端口.
config.ENV_ONLY 禁用文件倒计时以读取确切的环境 .
config.flattenBundleEnv(), (中文(简体) ), flattenAppEnv(),以及 getBundlePath() 揭露
对已解析配置数据的呼叫者, 解析逻辑相同 .
发现捆绑的 App 资源
import { bundle } from "@dbx-tools/core";
for await (const resource of bundle.appResources(projectRoot, cwd)) {
consume(resource);
}
appResources() 返回一个同步生成器。 它检查捆绑的文件在
可选工作目录的先行链,然后穿越工程
与节点为同步本地文件系统 API 的边界。 每一个都能产生 resources.apps 条目从
databricks bundle validate --output json因此,包括目标、变量,
和相对源路径由 Databricks CLI 解决. 没有
需求 app.yml 或者说 app.yaml。每个资源包括应用程序 config 编辑
完成解析后捆绑 data。 。 。 .
仍然返回部分 App 资源的验证失败
bundleFailure 对这些资源。 没有 App 资源输出失败的捆绑
没什么 缺少、无效或过时的项目路径也无济于事.
失败的 CLI 输出在生成器被消耗时抛出 .
运行命令
import { exec } from "@dbx-tools/core";
const result = await exec.spawn("git", ["status", "--short"], {
stdout: "capture",
stderr: "capture",
});
if (result.exitCode !== 0) {
throw new Error(result.stderr);
}
exec.spawn() 支持继承、管道化、被忽略、捕获和线回调
斯特迪奥。 它接受字符串 stdin并中止信号,使其对CLI和
监视任务。 回来的活生生的孩子也要等待 并暴露出一个记忆
shutdown() 要求操作系统终止其进程的方法
等8秒 武力杀死幸存者 还有4秒的民意调查.
呼叫者可能会超越这些超时,但不是平台信号政策。 家长
除非
forwardTerminationSignals: false 已经设定。 订阅
exec.onParentTerminationSignal 而不是添加另一个 process 听着.
额外收听者会改变这个陷阱是否在孩子出生后重新发出信号
离开.
当一个可执行文件丢失时, spawn() 财务报告和审定财务报表 spawnSync() 返回时
exec.COMMAND_NOT_FOUND_EXIT_CODE (单位:千美元)127除非 check: true 已经设定。 与
check: true他们像其他非零出口一样投出.
偏爱 spawn() 临时 child_process 当命令输出需要时调用
被捕获,逐行流出,或连续地从更高一级中止
用于工具.
同步运行
const rev = exec
.spawnSync("git", ["rev-parse", "HEAD"], {
stdout: "capture",
})
.stdout.trim();
使用 spawnSync() 在 prijen 合成或配置 中发现 async
控制流不可用。 同步的孩子留在父母身边
进程组,所以终端信号可以到达两个进程。 JavaScript 信号陷阱
无法运行, 当父程序被屏蔽时 spawnSync()。 。 。 .
拆分类似 shell 的命令
const argv = exec.shlex('pnpm exec prettier --write "README.md"');
shlex() 是命令字符串需要成为 argv 数组的小型解析器.
尽可能优先使用明确的 argv 阵列 .
串行工作
import { processLock } from "@dbx-tools/core";
await processLock.withProcessLock(["cache", name], async () => {
if (!(await exists(name))) await build(name);
});
withProcessLock() 运行回调,同时按住命名的锁,释放它
当召回器落定时。 共享密钥的呼叫者被序列化 。 区分密钥
同时运行。 键是任何具有稳定身份的值,例如字符串,
a 一个 ["invoice", id] tuple,或者一个配置对象. object.toStableKey
所以结构很重要: ["invoice", 7] 财务报告和审定财务报表 "invoice_7" 为:
不同的锁.
当涉及工人线程时,用它代替模块级的承诺链. 承诺链只会串起它赖以生存的线条 所以一个工人池就开一个 每行调用。 这里的协调员是共享的,所以钥匙承认一个 整个过程的调用.
工人在施工时选择:
import { Worker } from "node:worker_threads";
new Worker(url, processLock.processLockWorkerOptions({ workerData: { tenant } }));
这保存了你自己 workerData 财务报告和审定财务报表 transferList,让工人
模块初始化时锁定。 对于你没有建造的工人,打电话
attachProcessLock(worker) 并有工作者 await processLockAttached()
先说 港口通过信息抵达,因此无法尽早提供.
一条线在扣锁时会退出 释放它 所以坠机的工人不能 永远拿着钥匙 锁只保留到回调运行时,以及 一个闲置的锁从不阻止进程退出.
锁瞄准镜是一个过程的线程. withProcessLock 没有共享
以秒计 node 引用或其他复制品。 当关键部分
跨越部署, 使用 @dbx-工具/邮递是因为 withAdvisoryLock, (中文(简体) ),
它把仲裁者放在PostgreSQL中,每个复制品都能看到它.
将各个进程的工作序列化
import { fileLock } from "@dbx-tools/core";
await fileLock.withFileLock(["cache", name], async () => {
if (!(await exists(name))) await build(name);
});
withFileLock() 序列化同一机器或共享文件系统中的进程.
Bun和Node都用过 proper-lockfile 原子锁-指令创建,
心跳, Stale-lock再生, 和所有权安全释放。 打电话的人可以
选择锁定目录, 明确请求 Bun flock 后端, 请检查,
观察选中的后端, 或设置等时超时 。 锁键使用相同的稳定键
作为进程和Postgres咨询锁的结构化身份.
使用 flock 在使用可移植目录的进程之前必须停止
协议开始于同一共享状态。 两项议定书没有
互相协调.
使用 processLock.withProcessLock() 当在一个过程中只有线程竞争时,
fileLock.withFileLock() 当本地进程相竞争时, 和 Postgres 咨询
当多个应用复制品需要一名仲裁人时锁定.
发现项目根
import { projectUtils } from "@dbx-tools/core";
const root = projectUtils.root();
const name = projectUtils.name();
const origins = [...projectUtils.resolveProjectRoots(process.cwd())];
const cwd = projectUtils.resolveWorkingDirectory("");
projectUtils.root() 检查 npm/ pnpm 工作空间根, git 顶级,和 cwd .
projectUtils.name() 偏好软件包元数据,然后是 git 远程名称,然后是目录
基础名称. projectUtils.resolveWorkingDirectory() 将空白、 无效、 省略,
相对和缓存决定的绝对 cwd 值。 项目子进程探测器
共享命令/参数结果缓存,只当解决的路径是活的
进程 cwd. 另一个目录直接运行 。 空命令结果为
缓存也.
解决 npm 依赖性
import { readFile } from "node:fs/promises";
import { json } from "@dbx-tools/shared-core";
import { dependencyResolver } from "@dbx-tools/core";
const manifest = json.parseRecord(await readFile("package.json", "utf8"));
if (!manifest) throw new Error("package.json is not a JSON object");
const missing = await dependencyResolver.missingDependencies(manifest);
const leftpad = await dependencyResolver.resolveVersion({ name: "leftpad", range: "^1.0.0" });
const also = await dependencyResolver.resolveVersion("leftpad@^1.0.0");
const resolved = await dependencyResolver.resolveDependencies({
dependencies: {
leftpad: "^1.0.0",
typescript: { version: "5.8.3" },
},
});
missingDependencies() 逐行列出的登记规格和每个可达到的
包装 dependencies 通过 HTTP 获取地图 . resolveVersion() 接受一个
软件包名称, name@version 编号 : name@range,第二个指定字符串,或
{ name, version?, range? } (单位:千美元)semver 是用于 version) (中文(简体) ). 准确
存在的版本不变,当发布版本时保留范围
满足它.
resolveDependencies() 复制记录和无法使用的标记
包,或者他们的父母,直到该图表完成。 没有安装器
援引。 依赖性地图可能使用原始字符串或相同的结构对象.
每个返回的地图条目是 { name, version, range? }输入对象为
不变。 工作空间,目录,文件,和"git"的描述器被单独放出. 使用
当一个镜像或延迟代理 404s 已经公开 npm 的版本时 .
模块
exec- 合成/合成过程产卵、 stdio 处理、中断接线和切克.bin- 可执行下载,本地file://复制, 可选存档 提取、选择和原子安装。 URL 闪克接收{ tempDir }安装锁后.bundle- 同步流化 CLI 解析 Databricks 捆绑 App 资源.project- cwd正常化、根部发现、项目命名、基特远程 解析和纪念 npm 注册分辨率(env, npmrc, bunfig, pnpm yaml, 然后公开npm.dependencyResolver- HTTP 包 缺少图行走,单包 版本分辨率,可解析{ name, version, range? }地图来自 a 解析package.json。 。 。 .registryUrl默认为projectUtils.npmRegistry()。 。 。 .file- 使用调用者定义的源密钥来解析记录的缓存.brand- YAML/JSON发现、分析、验证和资产路径解析.config- 范围环境,dotenv, 和验证的Databricks捆绑的检查, 包括运行时间检测和打出强制帮助.fileLock- Bun和Node共用的便携式跨进程锁目录, 明确flock选项.processLock- 在主线及其工人之间相互排斥, 与工人接线(processLockWorkerOptions, (中文(简体) ),attachProcessLock, (中文(简体) ),processLockAttached) (中文(简体) ).