geospec 0.0.0 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +244 -0
- package/agent/doctrine.md +55 -0
- package/agent/geospec-authoring/SKILL.md +495 -0
- package/agent/geospec-authoring/api-classes.md +13 -0
- package/agent/geospec-authoring/api-constants.md +16 -0
- package/agent/geospec-authoring/api-functions.md +57 -0
- package/agent/geospec-authoring/api-index.md +377 -0
- package/agent/geospec-authoring/api-types.md +1788 -0
- package/agent/geospec-authoring/public-api-classes.md +22 -0
- package/agent/geospec-authoring/public-api-constants.md +51 -0
- package/agent/geospec-authoring/public-api-functions.md +215 -0
- package/agent/geospec-authoring/public-api-index.md +893 -0
- package/agent/geospec-authoring/public-api-types-2.md +1560 -0
- package/agent/geospec-authoring/public-api-types-3.md +217 -0
- package/agent/geospec-authoring/public-api-types.md +1948 -0
- package/agent/resources.d.ts +19 -0
- package/agent/resources.js +27 -0
- package/agent/skills.d.cts +13 -0
- package/agent/skills.json +28 -0
- package/dist/assertion-client/client.d.mts +134 -0
- package/dist/assertion-client/client.mjs +2 -0
- package/dist/assertion-client/index.d.mts +5 -0
- package/dist/assertion-client/index.mjs +1 -0
- package/dist/config/index.d.mts +3 -0
- package/dist/config/index.mjs +1 -0
- package/dist/config/node/index.d.mts +3 -0
- package/dist/config/node/index.mjs +1 -0
- package/dist/config/node/load.d.mts +19 -0
- package/dist/config/node/load.mjs +1 -0
- package/dist/config/tau-project-artifact.d.mts +54 -0
- package/dist/config/tau-project-artifact.mjs +3 -0
- package/dist/config/types.d.mts +57 -0
- package/dist/config/validate.mjs +1 -0
- package/dist/create-geospec.d.mts +50 -0
- package/dist/create-geospec.mjs +1 -0
- package/dist/engine/client.d.mts +113 -0
- package/dist/engine/client.mjs +1 -0
- package/dist/engine/index.d.mts +3 -0
- package/dist/engine/index.mjs +1 -0
- package/dist/engine/matchers.d.mts +70 -0
- package/dist/engine/matchers.mjs +1 -0
- package/dist/engine/pmi.types.d.mts +78 -0
- package/dist/engine/protocol.d.mts +20 -0
- package/dist/engine/protocol.mjs +1 -0
- package/dist/geometry-unit.d.mts +12 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +1 -0
- package/dist/mesh/index.d.mts +4 -0
- package/dist/mesh/index.mjs +1 -0
- package/dist/mesh/types.d.mts +575 -0
- package/dist/model/errors.d.mts +20 -0
- package/dist/model/errors.mjs +2 -0
- package/dist/model/export-intent.d.mts +79 -0
- package/dist/model/export-intent.mjs +1 -0
- package/dist/model/index.d.mts +7 -0
- package/dist/model/index.mjs +1 -0
- package/dist/model/load-model.d.mts +25 -0
- package/dist/model/load-model.mjs +1 -0
- package/dist/model/native-model-loader.d.mts +142 -0
- package/dist/model/native-model-loader.mjs +1 -0
- package/dist/model/region-scope.d.mts +23 -0
- package/dist/model/region-scope.mjs +1 -0
- package/dist/model/subject-assertions.mjs +1 -0
- package/dist/model/subject.d.mts +11 -0
- package/dist/model/subject.mjs +1 -0
- package/dist/model/types.d.mts +254 -0
- package/dist/runner/collector.d.mts +64 -0
- package/dist/runner/collector.mjs +2 -0
- package/dist/runner/discovery.d.mts +93 -0
- package/dist/runner/discovery.mjs +1 -0
- package/dist/runner/filter.d.mts +50 -0
- package/dist/runner/filter.mjs +1 -0
- package/dist/runner/index.d.mts +7 -0
- package/dist/runner/index.mjs +1 -0
- package/dist/runner/native/index.d.mts +4 -0
- package/dist/runner/native/index.mjs +1 -0
- package/dist/runner/native/native-pool-grants.d.mts +21 -0
- package/dist/runner/native/native-pool-grants.mjs +1 -0
- package/dist/runner/native/native-serial-runner.d.mts +29 -0
- package/dist/runner/native/native-serial-runner.mjs +1 -0
- package/dist/runner/pool/pool-messages.d.mts +94 -0
- package/dist/runner/run-geospec-module.d.mts +13 -0
- package/dist/runner/run-geospec-module.mjs +47 -0
- package/dist/runner/timeout-codes.d.mts +45 -0
- package/dist/runner/timeout-codes.mjs +1 -0
- package/dist/runner/types.d.mts +776 -0
- package/dist/runner/worker/index.d.mts +4 -0
- package/dist/runner/worker/index.mjs +1 -0
- package/dist/runner/worker/no-matching-tests-issue.d.mts +12 -0
- package/dist/runner/worker/no-matching-tests-issue.mjs +1 -0
- package/dist/runner/worker/runner-types.d.mts +167 -0
- package/dist/runner/worker/serial-runner.mjs +1 -0
- package/dist/selector/types.d.mts +271 -0
- package/dist/step/types.d.mts +134 -0
- package/dist/vitest/adapter.d.mts +56 -0
- package/dist/vitest/adapter.mjs +3 -0
- package/dist/vitest/index.d.mts +4 -0
- package/dist/vitest/index.mjs +1 -0
- package/package.json +114 -5
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createNoMatchingGeoSpecTestsIssue } from "./no-matching-tests-issue.mjs";
|
|
2
|
+
import { GeoSpecPoolHostMessage, GeoSpecPoolShard, GeoSpecPoolWorkerHandle, GeoSpecPoolWorkerMessage } from "../pool/pool-messages.mjs";
|
|
3
|
+
import { GeoSpecForensicEvent, GeoSpecRunner, GeoSpecRunnerEvent, GeoSpecRunnerFileResult, GeoSpecRunnerOptions, GeoSpecRunnerResult, GeoSpecRunnerRunOptions } from "./runner-types.mjs";
|
|
4
|
+
export { type GeoSpecForensicEvent, type GeoSpecPoolHostMessage, type GeoSpecPoolShard, type GeoSpecPoolWorkerHandle, type GeoSpecPoolWorkerMessage, type GeoSpecRunner, type GeoSpecRunnerEvent, type GeoSpecRunnerFileResult, type GeoSpecRunnerOptions, type GeoSpecRunnerResult, type GeoSpecRunnerRunOptions, createNoMatchingGeoSpecTestsIssue };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createNoMatchingGeoSpecTestsIssue as e}from"./no-matching-tests-issue.mjs";export{e as createNoMatchingGeoSpecTestsIssue};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { VmIssue } from "@taucad/esbuild/vm";
|
|
2
|
+
//#region src/runner/worker/no-matching-tests-issue.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Create a run-level issue when filters select no tests.
|
|
5
|
+
*
|
|
6
|
+
* @returns A structured VM issue for empty GeoSpec filter selections.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
declare const createNoMatchingGeoSpecTestsIssue: () => VmIssue;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { createNoMatchingGeoSpecTestsIssue };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=()=>({code:`NO_MATCHING_GEOSPEC_TESTS`,message:`No matching GeoSpec tests were selected by the supplied filters.`,severity:`error`,type:`runtime`});export{e as createNoMatchingGeoSpecTestsIssue};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { ManagedGeoSpecNativeModelLoader } from "../../model/native-model-loader.mjs";
|
|
2
|
+
import { GeoSpecRunResult, GeoSpecTestAccounting, GeoSpecTestCase, RunGeoSpecModuleOptions } from "../types.mjs";
|
|
3
|
+
import { VmFileSystem, VmIssue } from "@taucad/esbuild/vm";
|
|
4
|
+
//#region src/runner/worker/runner-types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* One GeoSpec test file executed by a worker-style runner.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
type GeoSpecRunnerFileResult = {
|
|
11
|
+
/** Absolute or project-relative GeoSpec test file path supplied to the runner. */
|
|
12
|
+
file: string;
|
|
13
|
+
/** Low-level module execution result for this file. */
|
|
14
|
+
result: GeoSpecRunResult;
|
|
15
|
+
/** Wall-clock cost of executing this file, in milliseconds (R1). */
|
|
16
|
+
durationMs?: number;
|
|
17
|
+
/** First deterministic model-load cache key observed in this file (R9 affinity telemetry). */
|
|
18
|
+
primaryLoadKey?: string;
|
|
19
|
+
/** Executing worker's isolate-resident memory at file completion, in bytes (R15 memory-class telemetry). */
|
|
20
|
+
workerMemoryBytes?: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Aggregate result returned by GeoSpec worker-style runners.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
type GeoSpecRunnerResult = {
|
|
28
|
+
/** True when no files or tests failed and at least one test was selected. */
|
|
29
|
+
success: boolean;
|
|
30
|
+
/** Number of non-skipped tests that passed. */
|
|
31
|
+
passed: number;
|
|
32
|
+
/** Number of file-level or test-level failures. */
|
|
33
|
+
failed: number;
|
|
34
|
+
/** Number of collected tests after filters were applied. */
|
|
35
|
+
selectedTests: number;
|
|
36
|
+
/** Per-file module execution results. */
|
|
37
|
+
files: GeoSpecRunnerFileResult[];
|
|
38
|
+
/** Run-level issues such as aborts or empty filter selections. */
|
|
39
|
+
issues?: VmIssue[];
|
|
40
|
+
/** Wall-clock cost of the whole run, in milliseconds (R1). */
|
|
41
|
+
durationMs?: number;
|
|
42
|
+
/** Complete requested-file accounting; discovery may remain unknown in unstarted or broken modules. */
|
|
43
|
+
accounting?: GeoSpecRunnerAccounting;
|
|
44
|
+
/** Coherence of the consumed source graphs, not a geometry verdict. */
|
|
45
|
+
lineageStatus?: 'complete' | 'unavailable' | 'mixed';
|
|
46
|
+
};
|
|
47
|
+
/** File and observed-test accounting for a worker run. @public */
|
|
48
|
+
type GeoSpecRunnerAccounting = GeoSpecTestAccounting & {
|
|
49
|
+
requestedFiles: readonly string[];
|
|
50
|
+
completedFiles: readonly string[];
|
|
51
|
+
notRunFiles: readonly string[];
|
|
52
|
+
discoveryComplete: boolean;
|
|
53
|
+
cancelled: boolean;
|
|
54
|
+
bailed: boolean;
|
|
55
|
+
};
|
|
56
|
+
/** Identity of a test that has started but not settled. @public */
|
|
57
|
+
type GeoSpecRunnerTestRef = {
|
|
58
|
+
readonly suite: readonly string[];
|
|
59
|
+
readonly name: string;
|
|
60
|
+
readonly ordinal?: number;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Lifecycle event emitted by GeoSpec worker-style runners. Test events are
|
|
64
|
+
* emitted by in-process runners; a pool reports per file.
|
|
65
|
+
*
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
type GeoSpecRunnerEvent = {
|
|
69
|
+
type: 'run-start';
|
|
70
|
+
files: readonly string[];
|
|
71
|
+
} | {
|
|
72
|
+
type: 'file-start';
|
|
73
|
+
file: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'test-start';
|
|
76
|
+
file: string;
|
|
77
|
+
test: GeoSpecRunnerTestRef;
|
|
78
|
+
} | {
|
|
79
|
+
type: 'test-complete';
|
|
80
|
+
file: string;
|
|
81
|
+
test: GeoSpecTestCase;
|
|
82
|
+
} | {
|
|
83
|
+
type: 'file-complete';
|
|
84
|
+
file: string;
|
|
85
|
+
result: GeoSpecRunResult;
|
|
86
|
+
durationMs?: number;
|
|
87
|
+
primaryLoadKey?: string;
|
|
88
|
+
workerMemoryBytes?: number;
|
|
89
|
+
} | {
|
|
90
|
+
type: 'run-complete';
|
|
91
|
+
result: GeoSpecRunnerResult;
|
|
92
|
+
} | GeoSpecForensicEvent | {
|
|
93
|
+
type: 'abort';
|
|
94
|
+
reason?: string;
|
|
95
|
+
} | {
|
|
96
|
+
type: 'close';
|
|
97
|
+
};
|
|
98
|
+
/** One structured forensic measurement emitted by a runner. @public */
|
|
99
|
+
type GeoSpecForensicEvent = {
|
|
100
|
+
type: 'forensic';
|
|
101
|
+
name: string;
|
|
102
|
+
value: number;
|
|
103
|
+
unit: 'milliseconds' | 'count';
|
|
104
|
+
shardId?: number;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Options accepted by a GeoSpec worker-style runner run.
|
|
108
|
+
*
|
|
109
|
+
* @public
|
|
110
|
+
*/
|
|
111
|
+
type GeoSpecRunnerRunOptions = {
|
|
112
|
+
/** GeoSpec test files to execute. Files run serially by default. */
|
|
113
|
+
files: readonly string[];
|
|
114
|
+
/** JavaScript regular expression matched against full `suite > test` names. */
|
|
115
|
+
testNamePattern?: string | RegExp;
|
|
116
|
+
/** Timeout for each async test callback, in milliseconds. */
|
|
117
|
+
testTimeout?: number;
|
|
118
|
+
/** Non-verdict matcher wall backstop. Milliseconds. */
|
|
119
|
+
matcherWallBackstop?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Engine work-unit budget for this run's claims, replacing the runner's
|
|
122
|
+
* `nativeAssertions.workUnitLimit`. A `loadModel` or `expectGeo` budget still
|
|
123
|
+
* wins for its own claims.
|
|
124
|
+
*/
|
|
125
|
+
workUnitLimit?: number;
|
|
126
|
+
/** Emit structured forensic measurements for this run. */
|
|
127
|
+
forensic?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Stop after the first failing file (R1). Interactive fail-fast only —
|
|
130
|
+
* never the default for reward runs, which want the complete red set.
|
|
131
|
+
*/
|
|
132
|
+
bail?: boolean;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Shared options for GeoSpec runner factories.
|
|
136
|
+
*
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
type GeoSpecRunnerOptions = {
|
|
140
|
+
/** Filesystem containing the project and test modules. */
|
|
141
|
+
filesystem: VmFileSystem;
|
|
142
|
+
/** Protocol-3 assertion client shared by every authored assertion and model admission. */
|
|
143
|
+
nativeAssertions: RunGeoSpecModuleOptions['nativeAssertions'];
|
|
144
|
+
/** Managed native model loader released after each settled run. */
|
|
145
|
+
nativeModelLoader?: ManagedGeoSpecNativeModelLoader;
|
|
146
|
+
/** Additional in-memory modules made available to the VM. */
|
|
147
|
+
builtinModules?: RunGeoSpecModuleOptions['builtinModules'];
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Public GeoSpec runner lifecycle surface.
|
|
151
|
+
*
|
|
152
|
+
* @public
|
|
153
|
+
*/
|
|
154
|
+
type GeoSpecRunner = {
|
|
155
|
+
/** Execute GeoSpec files and return a compact aggregate result. */
|
|
156
|
+
run(options: GeoSpecRunnerRunOptions): Promise<GeoSpecRunnerResult>;
|
|
157
|
+
/** Subscribe to one lifecycle event type. */
|
|
158
|
+
on<Type extends GeoSpecRunnerEvent['type']>(event: Type, handler: (event: Extract<GeoSpecRunnerEvent, {
|
|
159
|
+
type: Type;
|
|
160
|
+
}>) => void): () => void;
|
|
161
|
+
/** Request cooperative abort before the next file starts. */
|
|
162
|
+
abort(reason?: string): void;
|
|
163
|
+
/** Close the runner and release owned resources. */
|
|
164
|
+
close(): Promise<void>;
|
|
165
|
+
};
|
|
166
|
+
//#endregion
|
|
167
|
+
export { GeoSpecForensicEvent, GeoSpecRunner, GeoSpecRunnerAccounting, GeoSpecRunnerEvent, GeoSpecRunnerFileResult, GeoSpecRunnerOptions, GeoSpecRunnerResult, GeoSpecRunnerRunOptions, GeoSpecRunnerTestRef };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{runGeoSpecModule as e}from"../run-geospec-module.mjs";import{createNoMatchingGeoSpecTestsIssue as t}from"./no-matching-tests-issue.mjs";const n=()=>({code:`GEOSPEC_RUNNER_CLOSED`,message:`GeoSpec runner is closed.`,severity:`error`,type:`runtime`}),r=()=>({code:`GEOSPEC_RUNNER_ACTIVE`,message:`GeoSpec runner already has an active run.`,severity:`error`,type:`runtime`}),i=e=>({code:`GEOSPEC_RUNNER_ABORTED`,message:e?`GeoSpec run aborted: ${e}`:`GeoSpec run aborted.`,severity:`error`,type:`runtime`}),a=e=>({code:`GEOSPEC_RUNNER_BAILED`,message:`GeoSpec run stopped after first failure (--bail): ${e}. Remaining files were not executed.`,severity:`error`,type:`runtime`}),o=e=>{let t=0,n=0;for(let r of e)r.status!==`skipped`&&(r.status===`failed`?n+=1:r.status===`passed`&&(t+=1));return{passed:t,failed:n}},s=s=>{let c={closed:!1},l=new Set,u,d,f=new Map,p=e=>{for(let t of l)t(e)},m=()=>c.aborted,h=e=>({requestedFiles:[...e],completedFiles:[],notRunFiles:[...e],discoveryComplete:!1,discovered:0,selected:0,completed:0,passed:0,failed:0,unsupported:0,inconclusive:0,skipped:0,notRun:0,cancelled:!1,bailed:!1}),g=(e,t)=>({success:!1,passed:0,failed:1,selectedTests:0,files:[],issues:[e],accounting:h(t),lineageStatus:`unavailable`}),_=async n=>{let r=[...n.files],c=performance.now();p({type:`run-start`,files:r});let l=!1,u=async()=>{l||(l=!0,await s.nativeModelLoader?.releaseAll())},d=0,g=0,_=0,v=[],y=[],b=h(r),x=!0,S=`complete`,C=new Map;try{for(let t of r){let c=m();if(c!==void 0){let e=i(c);y.push(e),g+=1,p({type:`abort`,reason:c}),b.cancelled=!0,x=!1;break}p({type:`file-start`,file:t});let l=performance.now(),u=await e({filesystem:s.filesystem,entryPath:t,testNamePattern:n.testNamePattern,testTimeout:n.testTimeout,matcherWallBackstop:n.matcherWallBackstop,forensic:n.forensic,onTestEvent:e=>{p(e.type===`test-start`?{type:`test-start`,file:t,test:{suite:[...e.test.suite],name:e.test.name,...e.test.ordinal===void 0?{}:{ordinal:e.test.ordinal}}}:{type:`test-complete`,file:t,test:e.test})},bundleCache:f,nativeAssertions:n.workUnitLimit===void 0?s.nativeAssertions:{...s.nativeAssertions,workUnitLimit:n.workUnitLimit},...s.nativeModelLoader?{nativeModelLoader:s.nativeModelLoader}:{},...s.builtinModules?{builtinModules:s.builtinModules}:{}}).catch(e=>({success:!1,issues:[{code:`GEOSPEC_MODULE_INTERRUPTED`,message:e instanceof Error?e.message:String(e),severity:`error`,type:`runtime`}]})),h=performance.now()-l;p({type:`file-complete`,file:t,result:u,durationMs:h}),v.push({file:t,result:u,durationMs:h}),b.completedFiles=v.map(e=>e.file),b.notRunFiles=r.slice(v.length),x&&=u.success&&u.passed,u.lineage===void 0||u.lineage.status===`unavailable`?S!==`mixed`&&(S=`unavailable`):u.lineage.status===`mixed`&&(S=`mixed`);let w=u.lineage?.loads.flatMap(e=>{let{evidence:t}=e,n=t?.artifacts[0];return t?.exportOptions===void 0?[...(t?.artifacts??[]).flatMap(e=>e.sourcePath===void 0?[]:[{[e.sourcePath]:`sha256:${e.sha256}`}]),...t?.sourcePath===void 0||n===void 0?[]:[{[t.sourcePath]:`sha256:${n.sha256}`}]]:[]})??[];for(let e of[...u.lineage?.modules.map(e=>e.files)??[],...w,...u.lineage?.loads.map(e=>e.evidence?.sourceRevision?.files??{})??[]])for(let[t,n]of Object.entries(e))C.has(t)&&C.get(t)!==n&&(S=`mixed`),C.set(t,n);if(u.accounting!==void 0)for(let e of[`discovered`,`selected`,`completed`,`passed`,`failed`,`unsupported`,`inconclusive`,`skipped`,`notRun`])b[e]+=u.accounting[e];if(u.success){_+=u.tests.length;let e=o(u.tests);d+=e.passed,g+=e.failed}else g+=1;if(n.bail===!0&&(!x||g>0)){y.push(a(t)),b.bailed=!0;break}}_===0&&g===0&&(y.push(t()),g+=1);try{await u()}catch(e){y.push({code:`GEOSPEC_NATIVE_CLEANUP_FAILED`,message:e instanceof Error?e.message:String(e),severity:`error`,type:`runtime`}),x=!1}b.discoveryComplete=b.notRunFiles.length===0&&v.every(e=>e.result.success&&e.result.accounting!==void 0);let l={success:x&&S===`complete`&&g===0&&y.length===0,passed:d,failed:g,selectedTests:_,files:v,...y.length>0?{issues:y}:{},durationMs:performance.now()-c,accounting:b,lineageStatus:S};return p({type:`run-complete`,result:l}),l}finally{await u()}};return{async run(e){if(new Set(e.files).size!==e.files.length)return g({code:`GEOSPEC_DUPLICATE_FILES`,message:`GeoSpec requested files must be unique.`,severity:`error`,type:`runtime`},e.files);if(c.closed)return g(n(),e.files);if(u!==void 0)return g(r(),e.files);delete c.aborted;let t=()=>void 0,i=new Promise(e=>{t=e});u=i;try{return await _(e)}finally{t(),u===i&&(u=void 0)}},on(e,t){let n=n=>{n.type===e&&t(n)};return l.add(n),()=>l.delete(n)},abort(e){c.aborted=e??`requested`},async close(){d===void 0&&(c.closed=!0,c.aborted??=`runner closed`,d=(async()=>{await u,f.clear(),p({type:`close`})})()),await d}}};export{o as countRunnerTests,s as createSerialGeoSpecRunner};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { Vec3 } from "../mesh/types.mjs";
|
|
2
|
+
//#region src/selector/types.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Surface classification carried by selector face facts, matching the
|
|
5
|
+
* verification kernel's `faceFacts` payload vocabulary.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
type SelectorSurfaceType = 'plane' | 'cylinder' | 'cone' | 'sphere' | 'torus' | 'bspline' | 'other';
|
|
10
|
+
/**
|
|
11
|
+
* Inclusive numeric band. A bare number matches within the linear tolerance.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
type NumericRange = number | {
|
|
16
|
+
min?: number;
|
|
17
|
+
max?: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Cartesian coordinate record used by coordinate-band (`near`) predicates.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
type Vec3Record = {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
z: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Cardinality expectation for a selector resolution (master catalog G7).
|
|
31
|
+
* `'one'` is the default for relationship endpoints; `'many'` for groups.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
type Cardinality = 'one' | 'many' | {
|
|
36
|
+
exactly: number;
|
|
37
|
+
} | {
|
|
38
|
+
atLeast: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Direction predicate with optional angular tolerance in degrees.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
type DirectionPredicate = {
|
|
46
|
+
direction: Vec3;
|
|
47
|
+
angularToleranceDegrees?: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Ray probe predicate (world-space origin and direction, millimetres).
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
type RayPredicate = {
|
|
55
|
+
origin: Vec3;
|
|
56
|
+
direction: Vec3;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Face query predicates (master catalog G1/G2): geometric fact predicates,
|
|
60
|
+
* world-space probes, scoping, ordering with deterministic pick, and set
|
|
61
|
+
* algebra. All tolerances default to the shared tolerance contract.
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
type FaceQuery = {
|
|
66
|
+
surfaceType?: SelectorSurfaceType;
|
|
67
|
+
/** Face normal parallelism (planar faces). */
|
|
68
|
+
normal?: DirectionPredicate;
|
|
69
|
+
/** Rotation-axis parallelism (cylindrical/conical faces). */
|
|
70
|
+
axis?: DirectionPredicate;
|
|
71
|
+
radius?: NumericRange;
|
|
72
|
+
area?: NumericRange;
|
|
73
|
+
/** Plane offset band: signed distance of the plane from the origin. */
|
|
74
|
+
offset?: NumericRange;
|
|
75
|
+
/** Centroid coordinate bands, per-axis. */
|
|
76
|
+
near?: Partial<Vec3Record> & {
|
|
77
|
+
tolerance?: number;
|
|
78
|
+
};
|
|
79
|
+
/** Probe: point lying on the face surface (bounds + analytic residual). */
|
|
80
|
+
containsPoint?: Vec3;
|
|
81
|
+
/** Probe: face whose centroid is nearest to the point; ties are ambiguous. */
|
|
82
|
+
nearestTo?: Vec3;
|
|
83
|
+
/** Probe: first face hit by the ray (analytic plane/cylinder only in V1). */
|
|
84
|
+
hitByRay?: RayPredicate;
|
|
85
|
+
/** Restrict candidates to entities resolved by another selector. */
|
|
86
|
+
within?: GeometrySelector;
|
|
87
|
+
/** Deterministic ordering; `offsetAlong` projects centroids on `along`. */
|
|
88
|
+
orderBy?: 'area' | 'radius' | 'offsetAlong';
|
|
89
|
+
/** Projection direction for `orderBy: 'offsetAlong'`. */
|
|
90
|
+
along?: Vec3;
|
|
91
|
+
/** Deterministic pick after ordering: `'first' | 'last'` or 0-based index. */
|
|
92
|
+
pick?: 'first' | 'last' | number;
|
|
93
|
+
allOf?: FaceQuery[];
|
|
94
|
+
anyOf?: FaceQuery[];
|
|
95
|
+
not?: FaceQuery;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Axis query predicates over cylindrical/conical face facts.
|
|
99
|
+
*
|
|
100
|
+
* @public
|
|
101
|
+
*/
|
|
102
|
+
type AxisQuery = {
|
|
103
|
+
/** Axis direction parallelism. */
|
|
104
|
+
axis?: DirectionPredicate;
|
|
105
|
+
radius?: NumericRange;
|
|
106
|
+
near?: Partial<Vec3Record> & {
|
|
107
|
+
tolerance?: number;
|
|
108
|
+
};
|
|
109
|
+
containsPoint?: Vec3;
|
|
110
|
+
nearestTo?: Vec3;
|
|
111
|
+
within?: GeometrySelector;
|
|
112
|
+
orderBy?: 'radius' | 'offsetAlong';
|
|
113
|
+
along?: Vec3;
|
|
114
|
+
pick?: 'first' | 'last' | number;
|
|
115
|
+
allOf?: AxisQuery[];
|
|
116
|
+
anyOf?: AxisQuery[];
|
|
117
|
+
not?: AxisQuery;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Plane query predicates over planar face facts.
|
|
121
|
+
*
|
|
122
|
+
* @public
|
|
123
|
+
*/
|
|
124
|
+
type PlaneQuery = {
|
|
125
|
+
normal?: DirectionPredicate;
|
|
126
|
+
offset?: NumericRange;
|
|
127
|
+
area?: NumericRange;
|
|
128
|
+
near?: Partial<Vec3Record> & {
|
|
129
|
+
tolerance?: number;
|
|
130
|
+
};
|
|
131
|
+
containsPoint?: Vec3;
|
|
132
|
+
nearestTo?: Vec3;
|
|
133
|
+
within?: GeometrySelector;
|
|
134
|
+
orderBy?: 'area' | 'offsetAlong';
|
|
135
|
+
along?: Vec3;
|
|
136
|
+
pick?: 'first' | 'last' | number;
|
|
137
|
+
allOf?: PlaneQuery[];
|
|
138
|
+
anyOf?: PlaneQuery[];
|
|
139
|
+
not?: PlaneQuery;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Body query predicates over available source facts. The STEP index currently
|
|
143
|
+
* exposes per-occurrence solid aggregates. Qualified mesh Bodies are material
|
|
144
|
+
* roots, including their cavities; disconnected roots and cavity islands stay
|
|
145
|
+
* separate. Mesh measure, probe and ordering predicates without the required
|
|
146
|
+
* facts refuse, including inside boolean queries.
|
|
147
|
+
*
|
|
148
|
+
* @public
|
|
149
|
+
*/
|
|
150
|
+
type BodyQuery = {
|
|
151
|
+
area?: NumericRange;
|
|
152
|
+
near?: Partial<Vec3Record> & {
|
|
153
|
+
tolerance?: number;
|
|
154
|
+
};
|
|
155
|
+
nearestTo?: Vec3;
|
|
156
|
+
within?: GeometrySelector;
|
|
157
|
+
orderBy?: 'area' | 'offsetAlong';
|
|
158
|
+
along?: Vec3;
|
|
159
|
+
pick?: 'first' | 'last' | number;
|
|
160
|
+
allOf?: BodyQuery[];
|
|
161
|
+
anyOf?: BodyQuery[];
|
|
162
|
+
not?: BodyQuery;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Occurrence selector: a placed instance in the assembly tree.
|
|
166
|
+
*
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
type OccurrenceSelector = {
|
|
170
|
+
kind: 'occurrence';
|
|
171
|
+
/** Product or instance name to match. */
|
|
172
|
+
name?: string | RegExp;
|
|
173
|
+
/** Occurrence path (dot-joined instance segments, root omitted) to match. */
|
|
174
|
+
path?: string | RegExp;
|
|
175
|
+
expect?: Cardinality;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Body selector over source-backed solid evidence. Qualified mesh input exposes
|
|
179
|
+
* one material root with its cavities; the STEP index currently exposes one
|
|
180
|
+
* solid aggregate per occurrence. These are not interchangeable body counts.
|
|
181
|
+
*
|
|
182
|
+
* @public
|
|
183
|
+
*/
|
|
184
|
+
type BodySelector = {
|
|
185
|
+
kind: 'body';
|
|
186
|
+
/** STEP occurrence scope, or the exact retained mesh primitive label including any ordinal suffix. */
|
|
187
|
+
of?: string | RegExp;
|
|
188
|
+
query?: BodyQuery;
|
|
189
|
+
expect?: Cardinality;
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Face selector resolved via query/probe predicates.
|
|
193
|
+
*
|
|
194
|
+
* @public
|
|
195
|
+
*/
|
|
196
|
+
type FaceSelector = {
|
|
197
|
+
kind: 'face';
|
|
198
|
+
of?: string | RegExp;
|
|
199
|
+
query?: FaceQuery;
|
|
200
|
+
expect?: Cardinality;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Axis selector resolved from cylindrical/conical face facts.
|
|
204
|
+
*
|
|
205
|
+
* @public
|
|
206
|
+
*/
|
|
207
|
+
type AxisSelector = {
|
|
208
|
+
kind: 'axis';
|
|
209
|
+
of?: string | RegExp;
|
|
210
|
+
query?: AxisQuery;
|
|
211
|
+
expect?: Cardinality;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Plane selector resolved from planar face facts.
|
|
215
|
+
*
|
|
216
|
+
* @public
|
|
217
|
+
*/
|
|
218
|
+
type PlaneSelector = {
|
|
219
|
+
kind: 'plane';
|
|
220
|
+
of?: string | RegExp;
|
|
221
|
+
query?: PlaneQuery;
|
|
222
|
+
expect?: Cardinality;
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Datum selector: a named coordinate frame authored as a native AP242 datum
|
|
226
|
+
* placement.
|
|
227
|
+
*
|
|
228
|
+
* @public
|
|
229
|
+
*/
|
|
230
|
+
type DatumSelector = {
|
|
231
|
+
kind: 'datum';
|
|
232
|
+
/** Full datum name, or part-relative name when `of` scopes an occurrence. */
|
|
233
|
+
name: string;
|
|
234
|
+
of?: string | RegExp;
|
|
235
|
+
expect?: Cardinality;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Interface selector: an authored named interface transported as a STEP
|
|
239
|
+
* `SHAPE_ASPECT` subshape name — the production-preferred selector.
|
|
240
|
+
*
|
|
241
|
+
* @public
|
|
242
|
+
*/
|
|
243
|
+
type InterfaceSelector = {
|
|
244
|
+
kind: 'interface';
|
|
245
|
+
/** Full interface name, or part-relative name when `of` scopes an occurrence. */
|
|
246
|
+
name: string;
|
|
247
|
+
of?: string | RegExp;
|
|
248
|
+
expect?: Cardinality;
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* Group selector: an ordered shared-name family (`bore[1]`…`bore[N]`).
|
|
252
|
+
*
|
|
253
|
+
* @public
|
|
254
|
+
*/
|
|
255
|
+
type GroupSelector = {
|
|
256
|
+
kind: 'group';
|
|
257
|
+
/** Full group prefix, or part-relative prefix when `of` scopes an occurrence. */
|
|
258
|
+
name: string;
|
|
259
|
+
of?: string | RegExp;
|
|
260
|
+
expect?: Cardinality;
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* The V1 geometry selector union (D4 scope). Strings are shorthand: authored
|
|
264
|
+
* paths (`'block.deck.left'`, `'headL.boltHole[*]'`) or snapshot topology
|
|
265
|
+
* refs (`'#o1.2.f7'`, always `stability: 'derived-ordinal'`).
|
|
266
|
+
*
|
|
267
|
+
* @public
|
|
268
|
+
*/
|
|
269
|
+
type GeometrySelector = string | OccurrenceSelector | BodySelector | FaceSelector | AxisSelector | PlaneSelector | DatumSelector | InterfaceSelector | GroupSelector;
|
|
270
|
+
//#endregion
|
|
271
|
+
export { AxisQuery, AxisSelector, BodyQuery, BodySelector, Cardinality, DatumSelector, DirectionPredicate, FaceQuery, FaceSelector, GeometrySelector, GroupSelector, InterfaceSelector, NumericRange, OccurrenceSelector, PlaneQuery, PlaneSelector, RayPredicate, SelectorSurfaceType, Vec3Record };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
//#region src/step/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* STEP source and AP242 structure types shared by model loading and subject evidence.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* STEP source forms accepted by `loadModel`.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
type StepSource = string | URL | Uint8Array<ArrayBuffer> | ArrayBuffer | Blob | File | ReadableStream<Uint8Array<ArrayBuffer>> | AsyncIterable<Uint8Array<ArrayBuffer>>;
|
|
13
|
+
/**
|
|
14
|
+
* STEP reader strategy used by GeoSpec model loading.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
type StepStreamingMode = 'auto' | 'native-stream' | 'filesystem';
|
|
19
|
+
/**
|
|
20
|
+
* One placed occurrence recovered from an AP242 STEP structure read.
|
|
21
|
+
*
|
|
22
|
+
* `path` is dot-joined instance-name segments from the root (root omitted) per
|
|
23
|
+
* the GeoSpec AP242 profile; repeated names under one parent are disambiguated
|
|
24
|
+
* `name[k]` in the parent's stored component order.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
type XdeOccurrence = {
|
|
29
|
+
path: string;
|
|
30
|
+
productName: string;
|
|
31
|
+
instanceName?: string;
|
|
32
|
+
/** 4x4 row-major placement transform (part-local frame -> subject frame). */
|
|
33
|
+
transform: number[];
|
|
34
|
+
/** Index into the native result's retained shape table (proof calls use it). */
|
|
35
|
+
shapeIndex: number;
|
|
36
|
+
/** Analytic axis-aligned bounds of the placed occurrence in subject space. */
|
|
37
|
+
bounds?: {
|
|
38
|
+
min: [number, number, number];
|
|
39
|
+
max: [number, number, number];
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* One part-relative authored subshape name, expanded per occurrence of the
|
|
44
|
+
* owning product (full selector name = `${occurrencePath}.${name}`).
|
|
45
|
+
*
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
type XdeSubshapeName = {
|
|
49
|
+
occurrencePath: string;
|
|
50
|
+
name: string;
|
|
51
|
+
shapeType: 'face' | 'edge' | 'vertex' | 'solid';
|
|
52
|
+
/** Index within the owning product shape's deterministic face traversal order. */
|
|
53
|
+
faceIndex: number;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* One native AP242 datum placement row (a coordinate *frame* from the
|
|
57
|
+
* supplemental-geometry channel), expanded per occurrence like subshape names
|
|
58
|
+
* and expressed in subject-frame coordinates.
|
|
59
|
+
*
|
|
60
|
+
* Distinct from {@link XdeSemanticDatum}: this is supplemental geometry
|
|
61
|
+
* (`AXIS2_PLACEMENT_3D` items in a CONSTRUCTIVE_GEOMETRY_REPRESENTATION), not
|
|
62
|
+
* the GD&T `DATUM` family.
|
|
63
|
+
*
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
type XdeDatumPlacement = {
|
|
67
|
+
occurrencePath: string;
|
|
68
|
+
name: string;
|
|
69
|
+
origin: [number, number, number];
|
|
70
|
+
xAxis: [number, number, number];
|
|
71
|
+
zAxis: [number, number, number];
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* One semantic GD&T datum (`DATUM` + `DATUM_FEATURE` family) recovered from an
|
|
75
|
+
* AP242 file, attached to product faces via GEOMETRIC_ITEM_SPECIFIC_USAGE and
|
|
76
|
+
* expanded per occurrence of the owning product.
|
|
77
|
+
*
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
type XdeSemanticDatum = {
|
|
81
|
+
occurrencePath: string;
|
|
82
|
+
/** The GD&T datum identification letter(s): 'A', 'B', … */
|
|
83
|
+
label: string;
|
|
84
|
+
/** DATUM_FEATURE name when the file authored one. */
|
|
85
|
+
featureName?: string;
|
|
86
|
+
/** Attached faces in the owning product's deterministic face traversal order. */
|
|
87
|
+
faceIndexes: number[];
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* One GD&T datum reference frame (`DATUM_SYSTEM`) with its precedence
|
|
91
|
+
* compartments, expanded per occurrence of the owning product.
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
type XdeDatumSystem = {
|
|
96
|
+
occurrencePath: string;
|
|
97
|
+
name: string;
|
|
98
|
+
/** Compartments in precedence order; each holds one or more datum labels (common datums). */
|
|
99
|
+
references: string[][];
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* One supplemental-geometry `PLANE` item (e.g. `'Datum Plane 1'`), expanded per
|
|
103
|
+
* occurrence and expressed in subject-frame millimetres (per-context units
|
|
104
|
+
* resolved by the reader).
|
|
105
|
+
*
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
type XdeSupplementalPlane = {
|
|
109
|
+
occurrencePath: string;
|
|
110
|
+
name: string;
|
|
111
|
+
origin: [number, number, number];
|
|
112
|
+
normal: [number, number, number];
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Structured AP242 read result produced by the GeoSpec verification kernel's
|
|
116
|
+
* XDE reader (SB1). One STEP-XDE read yields structure and geometry together.
|
|
117
|
+
*
|
|
118
|
+
* @public
|
|
119
|
+
*/
|
|
120
|
+
type XdeReadResult = {
|
|
121
|
+
occurrences: XdeOccurrence[];
|
|
122
|
+
subshapeNames: XdeSubshapeName[];
|
|
123
|
+
datumPlacements: XdeDatumPlacement[];
|
|
124
|
+
/** Semantic GD&T datums (the `DATUM` family) — empty for graphical-only files. */
|
|
125
|
+
semanticDatums: XdeSemanticDatum[];
|
|
126
|
+
/** GD&T datum reference frames (`DATUM_SYSTEM`). */
|
|
127
|
+
datumSystems: XdeDatumSystem[];
|
|
128
|
+
/** Supplemental-geometry `PLANE` items. */
|
|
129
|
+
supplementalPlanes: XdeSupplementalPlane[];
|
|
130
|
+
/** Free (non-assembly) top-level shapes — the flat-export degenerate case. */
|
|
131
|
+
freeShapeCount: number;
|
|
132
|
+
};
|
|
133
|
+
//#endregion
|
|
134
|
+
export { StepSource, StepStreamingMode, XdeDatumPlacement, XdeDatumSystem, XdeOccurrence, XdeReadResult, XdeSemanticDatum, XdeSubshapeName, XdeSupplementalPlane };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { GeoSpecSubject } from "../model/subject.mjs";
|
|
2
|
+
import { GeoSpecCanonicalClaimReport, GeoSpecNativeSubject } from "../engine/client.mjs";
|
|
3
|
+
import { GeoSpecAssertionClient, GeoSpecAssertionClientOptions, GeoSpecMatcherMethods } from "../assertion-client/client.mjs";
|
|
4
|
+
import "../assertion-client/index.mjs";
|
|
5
|
+
import { MatcherState } from "vitest";
|
|
6
|
+
//#region src/vitest/adapter.d.ts
|
|
7
|
+
type GeoSpecVitestMatcherMethods = GeoSpecMatcherMethods<Promise<void>>;
|
|
8
|
+
type GeoSpecVitestResult = {
|
|
9
|
+
readonly actual: GeoSpecCanonicalClaimReport;
|
|
10
|
+
readonly expected: Readonly<{
|
|
11
|
+
claimId: string;
|
|
12
|
+
polarity: string;
|
|
13
|
+
status: string;
|
|
14
|
+
}>;
|
|
15
|
+
readonly message: () => string;
|
|
16
|
+
readonly meta: Readonly<{
|
|
17
|
+
geoSpec: GeoSpecCanonicalClaimReport;
|
|
18
|
+
}>;
|
|
19
|
+
readonly pass: boolean;
|
|
20
|
+
};
|
|
21
|
+
type GeoSpecVitestMatcher = (this: MatcherState, received: GeoSpecNativeSubject | GeoSpecSubject | PromiseLike<GeoSpecNativeSubject | GeoSpecSubject>, ...arguments_: readonly unknown[]) => Promise<GeoSpecVitestResult>;
|
|
22
|
+
type GeoSpecVitestMatcherMap = Record<string, GeoSpecVitestMatcher>;
|
|
23
|
+
declare module 'vitest' {
|
|
24
|
+
interface Matchers<T = any> extends GeoSpecVitestMatcherMethods {}
|
|
25
|
+
}
|
|
26
|
+
/** Installed Vitest matcher map and lifecycle settlement hook. @public */
|
|
27
|
+
type GeoSpecVitestAdapter = {
|
|
28
|
+
readonly matchers: GeoSpecVitestMatcherMap;
|
|
29
|
+
flush(): Promise<void>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Create Vitest matchers over an existing runner-independent client.
|
|
33
|
+
*
|
|
34
|
+
* @param client - Native GeoSpec assertion client shared with standalone use.
|
|
35
|
+
* @returns Matchers and a hook that settles every operation started by a test.
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
declare const createGeoSpecVitestAdapter: (client: GeoSpecAssertionClient) => GeoSpecVitestAdapter;
|
|
39
|
+
/**
|
|
40
|
+
* Register GeoSpec matchers and their settlement hook in the active Vitest file.
|
|
41
|
+
*
|
|
42
|
+
* @param client - Native client shared with standalone assertion calls.
|
|
43
|
+
* @returns The installed adapter for reporters or explicit flushing.
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
declare const installGeoSpecVitest: (client: GeoSpecAssertionClient) => GeoSpecVitestAdapter;
|
|
47
|
+
/**
|
|
48
|
+
* Create a native client and register it with the active Vitest file.
|
|
49
|
+
*
|
|
50
|
+
* @param options - Flat native assertion-client options.
|
|
51
|
+
* @returns The installed adapter for reporters or explicit flushing.
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
declare const setupGeoSpecVitest: (options: GeoSpecAssertionClientOptions) => GeoSpecVitestAdapter;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { GeoSpecVitestAdapter, createGeoSpecVitestAdapter, installGeoSpecVitest, setupGeoSpecVitest };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{geoSpecMatcherDescriptors as e}from"../engine/matchers.mjs";import{GeoSpecAssertionError as t,createGeoSpecAssertionClient as n}from"../assertion-client/client.mjs";import{afterEach as r,expect as i}from"vitest";const a=e=>e.evidence!==null&&typeof e.evidence==`object`&&!Array.isArray(e.evidence)?e.evidence:void 0,o=(e,t)=>{let n=a(t)?.positiveSatisfied;return{pass:(t.status===`passed`||t.status===`failed`)&&typeof n==`boolean`&&t.status===`passed`==(n===(t.polarity===`positive`))?n:e.isNot,actual:t,expected:{claimId:t.claimId,polarity:t.polarity,status:t.status},meta:{geoSpec:t},message:()=>JSON.stringify(t.result)}};var s=class{task;tracked=[];constructor(e){this.task=e,e.onFinished??=[],e.onFinished.push(()=>{for(;this.tracked.length>0;){let[e]=this.tracked;if(e===void 0)break;this.remove(e)}})}replace(e,t){return this.remove(e),this.track(t)}track(e){let t=new c(e,this);return this.task.promises??=[],this.task.promises.push(t),this.tracked.push(t),t}remove(e){let t=this.task.promises?.indexOf(e)??-1;t!==-1&&this.task.promises?.splice(t,1);let n=this.tracked.indexOf(e);n!==-1&&this.tracked.splice(n,1)}},c=class{promise;tracker;constructor(e,t){this.promise=e,this.tracker=t,e.catch(()=>void 0)}get[Symbol.toStringTag](){return`Promise`}then(e,t){return this.tracker.replace(this,this.promise.then(e,t))}catch(e){return this.tracker.replace(this,this.promise.catch(e))}finally(e){return this.tracker.replace(this,this.promise.finally(e))}},l=class{invocationStack;promise;task;constructor(e,t,n){this.promise=e,this.task=t,this.invocationStack=n}get[Symbol.toStringTag](){return`Promise`}then(e,t){let n=this.promise.then(e,t).catch(e=>{if(e instanceof Error&&this.invocationStack!==void 0){let t=this.invocationStack.split(`
|
|
2
|
+
`).slice(1).join(`
|
|
3
|
+
`);e.stack=`${e.stack??e.message}\nGeoSpec assertion invoked at:\n${t}`}throw e});return this.task===void 0?n:new s(this.task).track(n)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}};const u=n=>{let r=new Set,i={};for(let a of Object.keys(e))i[a]=function(e,...i){if(!Reflect.has(this,`assertion`))throw TypeError(`GeoSpec Vitest matchers do not support asymmetric use.`);let s=Reflect.get(this,`task`),c=(async()=>{let r=await e,o=n.expectGeo(r),s=this.isNot?o.not:o;try{return Reflect.apply(s[a],s,i)}catch(e){if(e instanceof t)return e.report;throw e}})();return s===void 0&&r.add(c),new l((async()=>o(this,await c))(),s,Error(`Track GeoSpec assertion origin.`).stack)};let a=async()=>{let e=[...r];r.clear();let n=(await Promise.all(e)).find(e=>e.status!==`passed`);if(n!==void 0)throw new t(n);r.size>0&&await a()};return{matchers:i,flush:a}},d=e=>{let t=u(e);return i.extend(t.matchers),r(async()=>t.flush()),t},f=e=>d(n(e));export{u as createGeoSpecVitestAdapter,d as installGeoSpecVitest,f as setupGeoSpecVitest};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { GeoSpecAssertionClient, GeoSpecAssertionClientOptions } from "../assertion-client/client.mjs";
|
|
2
|
+
import "../assertion-client/index.mjs";
|
|
3
|
+
import { GeoSpecVitestAdapter, createGeoSpecVitestAdapter, installGeoSpecVitest, setupGeoSpecVitest } from "./adapter.mjs";
|
|
4
|
+
export { type GeoSpecAssertionClient, type GeoSpecAssertionClientOptions, type GeoSpecVitestAdapter, createGeoSpecVitestAdapter, installGeoSpecVitest, setupGeoSpecVitest };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createGeoSpecVitestAdapter as e,installGeoSpecVitest as t,setupGeoSpecVitest as n}from"./adapter.mjs";export{e as createGeoSpecVitestAdapter,t as installGeoSpecVitest,n as setupGeoSpecVitest};
|