geospec

中文文档
0.5.1发布于 2026/11/04Apache-2.0TypeScriptES Module构建来源已验证

用于CAD模型的几何规范API: DSL、选择器语言、诊断模式和本机运行器集成

中文使用文档
文档目录5 节
  1. 运行规范
  2. 主题和主持人寿命
  3. 跑步者配置
  4. 检查没有规格的文件
  5. 许可证

geospec

GeoSpec是一个CAD几何测试库,具有一个独立于主机的创作API: loadModel 从 geospec/model 和 expectGeo 从 geospec。

这个包裹是 matcher-API衬底 (Apache-2.0): 创作DSL, 选择器语言,诊断和证据模式,匹配器 注册表和主机集成。它自己不执行任何几何: 每个索赔 由编译后的 geospec-engine 核心是 主机传递给跑者。Tau的桌面/浏览器组成和 geospec CLI 供应那个引擎。创作的测试 不要导入或选择引擎,也不会全局注册一个引擎。

以下是 *.geospec.ts 模块,用于CLI或Tau test_model:

import { describe, expectGeo, it } from 'geospec';
import { loadModel } from 'geospec/model';

const code = `
  import { makeBaseBox } from 'replicad';
  export default function main() {
    return makeBaseBox(40, 20, 8);
  }
`;

describe('bracket', () => {
  it('has expected measurements', async () => {
    const model = await loadModel({
      code: { 'main.ts': code },
      file: 'main.ts',
      format: 'glb',
    });

    expectGeo(model).toHaveBoundingBox({ size: { x: 40, y: 20, z: 8 }, tolerance: 0.1 });
    expectGeo(model).toHaveSurfaceArea({ value: 2560, tolerance: 10 });
    expectGeo(model).toHaveVolume({ value: 6400, tolerance: 10 });
  });
});

运行规范

主题和主持人寿命

等待 loadModel,然后进行同步 expectGeo 断言。它的 GeoSpecSubject 是不透明的:不读取网格字段,伪造主题哈希,还是 在其所属的加载器/运行被处置后重用一个主体。主机保留 源和参数的同一性和具有几何允许、重用和释放性。

独立主机和Vitest主机通过以下方式提供托管加载程序 createModelLoader 与现有主机集成; geospec/vitest 提供框架 适配器。轻快地的 describe/it 来自Vitest,而助手进口 从 geospec 以上都属于GeoSpec的VM运行器。普通的断言仍然存在 expectGeo;可选的Vitest expect 扩展有自己的异步 结算合同。看到 主机绑定文档。

Python使用 load_model/expect_geo 从 geospec,车轮的pytest 插件范围或独立 GeoSpecEngine 上下文。τ test_model 发现 TypeScript/JavaScript测试,而不是Python文件。

阅读 runStatus,完整的核算,发现和源谱系状态时 解释跑步。不支持、不确定、跳过和未运行的要求 不是通行证。紧凑的 test_model 输出可以省略细节; 其保留 fullResult 保留完整的结果。一个空的失败列表本身并不是 确认和过滤的需求仍然在演示的范围之外。

跑步者配置

这个 geospec bin在编译引擎上运行项目的规范,从 geospec-engine: 如果这个平台有一个本地插件,那么它就是WASM构建。的模型, STEP或GLB不是来自 exporters 项目的 geospec.config.* 声明,在每个池工作线程中导入一次; 没有一个,这样的加载拒绝 与 GEOSPEC_EXPORTER_MISSING。

geospec run .
geospec run . --include "parts/**/*.geospec.ts"
geospec run . --file main.geospec.ts --test-name-pattern volume
geospec run . --workers            # worker pool, auto-sized
geospec run . --workers 4 --shard-timeout 600000
geospec run . --config ci.geospec.config.ts
geospec run . --json

规范进口。 CLI将每个规范与本机esbuild捆绑在 project:一个规范可以导入项目文件和GeoSpec内置(geospec, geospec/model, geospec/config)。npm包或URL导入拒绝使用 BUNDLER_FAILED 以及命名说明符的消息;没有什么是牵强的 安装。解析包的主机将自己的模块VM传递为 createModuleVm (CreateModuleVm 在 geospec/runner;对于节点池, moduleVmModule)。Tau的主机以这种方式注入Tau的esbuild VM。浏览器主机 没有默认VM,必须注入一个。

国旗意义
--file <path>GeoSpec文件或目录根;可重复的。从项目根目录发现空输入。
--include <glob> / --exclude <glob>vitest风格的文件globs;可重复的。包括默认值为 **/*.geospec.{ts,js}。
-t, --test-name-pattern <re>JavaScript正则表达式与完整匹配 suite > test 名字。
--test-timeout <ms>每个异步测试一下回调的超时。
--workers [n]在工作池中运行。默认值是1;忽略标志后的计数以请求可用的CPU并行性。
--shard-timeout <ms>每个分片 non-verdict 看门狗。默认关闭。
--bail在第一个红色文件后停止。仅限互动使用-奖励运行需要完整的红色套装。
--config <path>这个 geospec.config.* 来代替项目根目录中的.
--json在stdout上打印一个JSON结果文档,没有别的。

标志替换同名的config字段。 退出代码是 判决。 0 只有当跑步成功时;任何失败,任何运行级问题, 和一个空的选择都是 1。

检查没有规格的文件

geospec check 在STEP或GLB文件上运行一个捆绑的有效性规范,因此 首次使用无需 *.geospec.ts。它需要相同的转轮,引擎和报告 作为 geospec run;该文件的文件夹是项目根目录。

geospec check bracket.step
geospec check assembly.glb --components 3 --json

每个索赔都是自己的测试一下: 没有错误诊断,封闭边缘发生率 (toBeWatertight)和一个在每个轴上都是正大小的边界框,加上 GLB的网格完整性或STEP文件的有效BRep的封闭外壳。 --components <n> 添加精确的连接组件计数。发动机索赔 不能决定被报告为不确定的,从不作为通过,退出代码是 判决结果。

要嵌入池,请使用 createGeoSpecNodePoolRunner 从 geospec/runner/node; 每个工人拥有一台发动机和自己的出口,而不是活的对象 跨越工人界限。要在此进程中串行运行,请将引擎从 createNodeGeoSpecEngine 来 createNativeGeoSpecRunner 从 geospec/runner/native;它构建本机模型加载器并释放每个 每次跑步后入院。其他嵌入必须符合其实际 绑定、输入表示和支持域;共享创作语法 单独不能建立判决对等。

下面的过滤器是CLI的共享词汇表,即嵌入式运行程序 和Tau test_model 工具:

  • files: 要运行的GeoSpec文件或目录根目录。空输入递归地从项目根目录中发现。
  • include: GeoSpec文件包括globs,默认为 ["**/*.geospec.{ts,js}"]
  • exclude: GeoSpec文件排除globs
  • testNamePattern:与full匹配的JavaScript正则表达式 suite > test 的名字
  • testTimeout:异步测试超时时间,单位为毫秒

主机使用Tau运行时导出或已经导出的GLB/glTF/STEP字节。编写的测试使用 loadModel 对于代码和直接几何输入; 低级解析/主机api不是替代的创作测试一下方言。

负载故障带有结构化诊断。主张报告保留选定的主张、证据、出处和诊断;检查这些报告,而不是期望不透明主题上的可变证据字段。

保持每个测试都是可读的 loadModel() 呼叫。每个负载捕获电流源/参数标识;主机只能在匹配身份的情况下重用被承认的计算。不要认为文件名单独允许跨文件记忆:

import { describe, expectGeo, it } from 'geospec';
import { loadModel } from 'geospec/model';

describe('assembly', () => {
  it('has no global part interference', async () => {
    const model = await loadModel({ file: 'main.ts' });
    expectGeo(model).toHaveNoComponentInterference({ tolerance: 0.1 });
  });

  it('keeps the ring and planet free of interference', async () => {
    const model = await loadModel({ file: 'main.ts' });
    expectGeo(model).toHaveNoComponentInterference({
      tolerance: 0.05,
      pairs: [{ left: /ring/i, right: /planet gear/i }],
    });
  });
});

生产装配套件可以结合网格-完整性、发生性、空间 关系,以及精确的BRep断言,而无需添加特定于域的断言 每个机械子系统的匹配器:

expectGeo(model).toHaveMeshIntegrity({
  finitePositions: true,
  degenerateTriangles: { count: 0 },
  duplicateFaces: { count: 0 },
});

expectGeo(model).toHaveAssemblyOccurrences({
  uniqueNames: true,
  occurrences: [
    { name: 'Housing', count: 1 },
    { name: /^Fastener \d+$/, count: 8 },
  ],
});

expectGeo(model).toHaveSpatialRelationships({
  relationships: [
    { id: 'shaft seats in bearing', kind: 'contact', subject: 'Shaft', target: 'Bearing', tolerance: 0.05 },
    { id: 'pin remains inside yoke', kind: 'containment', subject: 'Pin', target: 'Yoke', tolerance: 0.05 },
  ],
});

选择被接纳的源支持的选择器。一个合格的网格 body 选择器标识一种材料根及其型腔边界; 断开连接 根和洞里的岛是分开的。它的 of 范围 匹配完全保留的基元标签,包括任何序号后缀。 检查该标签并保留基数,而不是猜测发生的情况 路径。网格输入未发明装配祖先或分析面; 缺少 测量、调查或责令证据拒绝,甚至通过询问否定。 步骤体索引公开了每次出现的实体聚合,也是如此 不假设它的体计数一对一地映射到网格材质根。

全身接触不需要内部重叠和边界分离 宣称的包容性宽容。没有建立接触区域或密封; 有限面角度要求需要其实际的分析证据。

通过相同的编写API加载STEP:

import { loadModel } from 'geospec/model';

const subject = await loadModel({ file: 'part.step', format: 'step' });

对于CAD源, loadModel({ file: 'main.ts', format: 'step' }) 要求主机导出STEP。配置的编译引擎通过其OCCT绑定承认精确返回的字节。出口和来源本身并不构成几何要求。

测量匹配程序支持网格证据,并且在存在时更喜欢精确的BRep证据:

expectGeo(subject).toHaveSurfaceArea({ value: 12_345, tolerance: 1 });
expectGeo(subject).toHaveVolume({ value: 120_000, tolerance: 10 });
expectGeo(subject).toHaveMass({ value: 94.2, density: 0.000_785, tolerance: 0.5 });
expectGeo(subject).toHaveCenterOfMass({ point: { x: 0, y: 0, z: 10 }, tolerance: 0.05 });

当加载器提供BRep证据时,初始BRep特征匹配器可用:

import { loadModel } from 'geospec/model';

const subject = await loadModel({ file: 'main.ts', format: 'step' });

expectGeo(subject).toBeValidBrep({ maxTolerance: 0.01, closedShells: true });
expectGeo(subject).toHavePlanarFace({ normal: { x: 0, y: 0, z: 1 }, offset: 20, tolerance: 0.05 });
expectGeo(subject).toHaveCylindricalFace({ radius: 15, axis: 'z', tolerance: 0.05 });
expectGeo(subject).toHaveCircularHole({ diameter: 8, through: true, axis: 'z', center: { x: 25, y: 15 } });
expectGeo(subject).toHaveChamferFeature({ distance: 2, selection: 'outer top perimeter', tolerance: 0.05 });
expectGeo(subject).toHaveMinimumWallThickness({ value: { greaterThanOrEqual: 2 }, tolerance: 0.05 });
expectGeo(subject).toHaveVoidContinuity({
  path: [{ occurrence: 'Throttle Body 1' }, { occurrence: 'Cylinder Head R' }],
  material: ['Throttle Body 1', 'Intake Manifold 1', 'Cylinder Head R'],
  minCrossSection: 900,
  isolatedFrom: [[120, 0, 40]],
});

这些是需求示例,而不是每个被认可的模型都支持的声明 他们。 toHaveVoidContinuity 要求声明的路径、材料和隔离 在限定域中证明的命题。取样的横截面不能 建立连续最小值:一般抽样配置文件拒绝请求 minCrossSection。受限制的名义解析域有独立的前提; 一般网格流明,壁和运动资格仍然不完整。

同样,水密边缘入射不能证明流形有效性,布尔 保险丝或材料连接性。边界和回放无法建立联系, 间隙、密封或密封。保留预期的几何形状和公差; 报告不可用的证据,而不是用代理替换需求。

这个 规范API索引 描述了 普通的创作。单独的 完整的公共API索引 保留主机和框架契约。

当几何断言需要参数变量时,将该变量直接传递给 loadModel. 省略 parameters 练习由模型创作的默认值:

import { describe, expectGeo, it } from 'geospec';
import { loadModel } from 'geospec/model';

describe('parameter variants', () => {
  it('uses the model defaults', async () => {
    const model = await loadModel({ file: 'main.ts' });
    expectGeo(model).toHaveBoundingBox({ size: { x: 40 }, tolerance: 1 });
  });

  it('accepts an explicit width', async () => {
    const width = 80;
    const model = await loadModel({
      file: 'main.ts',
      parameters: { width },
    });

    expectGeo(model).toHaveBoundingBox({ size: { x: width }, tolerance: 1 });
  });
});

许可证

apache - 2.0。 这个包是允许的周边: 你的规格,你的 模型和你的判决不继承这个包的许可。看到 许可 对于路由映射 以及内部常见问题解答。

版本与发布记录

geospec 共发布 20 个版本,首次发布于 2026/09/30;过去 12 个月发布了 20 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.5.1latest2026/11/04今天
0.5.1-next.361next2026/11/03今天
0.5.1-next.3512026/10/305 天前
0.5.1-next.3472026/10/295 天前
0.5.1-next.3422026/10/295 天前
0.5.1-next.3402026/10/295 天前

其他发布通道:bootstrap → 0.0.0,beta → 0.1.0-beta.9,next → 0.5.1-next.361。

关于 geospec 的常见问题

geospec 是什么?

用于CAD模型的几何规范API: DSL、选择器语言、诊断模式和本机运行器集成

如何安装 geospec?

在项目目录运行 npm install geospec,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 geospec,可以用 npx geospec 直接运行。

geospec 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

geospec 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

geospec 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

geospec 可以商用吗?

geospec 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

geospec 还在维护吗?

最新版本 0.5.1 发布于 2026/11/04(今天);至今共发布 20 个版本,其中过去 12 个月发布了 20 个;首次发布于 2026/09/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。