@faicad/faijs 0.13.2 → 0.14.1
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/dist/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +30 -4
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/boolean.d.ts +19 -0
- package/dist/api/boolean.d.ts.map +1 -1
- package/dist/api/boolean.js +51 -10
- package/dist/api/boolean.js.map +1 -1
- package/dist/api/chamfer.d.ts.map +1 -1
- package/dist/api/chamfer.js +8 -7
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/compound-geom.d.ts +45 -0
- package/dist/api/compound-geom.d.ts.map +1 -0
- package/dist/api/compound-geom.js +85 -0
- package/dist/api/compound-geom.js.map +1 -0
- package/dist/api/compound.d.ts +2 -0
- package/dist/api/compound.d.ts.map +1 -1
- package/dist/api/compound.js +2 -0
- package/dist/api/compound.js.map +1 -1
- package/dist/api/copy.d.ts +1 -0
- package/dist/api/copy.d.ts.map +1 -1
- package/dist/api/copy.js +4 -2
- package/dist/api/copy.js.map +1 -1
- package/dist/api/edge-ref.d.ts.map +1 -1
- package/dist/api/edge-ref.js +7 -4
- package/dist/api/edge-ref.js.map +1 -1
- package/dist/api/engrave.d.ts.map +1 -1
- package/dist/api/engrave.js +1 -0
- package/dist/api/engrave.js.map +1 -1
- package/dist/api/extrude.d.ts.map +1 -1
- package/dist/api/extrude.js +131 -3
- package/dist/api/extrude.js.map +1 -1
- package/dist/api/face-ref.d.ts.map +1 -1
- package/dist/api/face-ref.js +7 -4
- package/dist/api/face-ref.js.map +1 -1
- package/dist/api/fai_drill.d.ts +1 -1
- package/dist/api/fai_drill.d.ts.map +1 -1
- package/dist/api/fai_drill.js +31 -18
- package/dist/api/fai_drill.js.map +1 -1
- package/dist/api/fai_extrude.d.ts +1 -1
- package/dist/api/fai_extrude.d.ts.map +1 -1
- package/dist/api/fai_extrude.js +2 -1
- package/dist/api/fai_extrude.js.map +1 -1
- package/dist/api/fai_split.d.ts +1 -1
- package/dist/api/fai_split.d.ts.map +1 -1
- package/dist/api/fai_split.js +2 -1
- package/dist/api/fai_split.js.map +1 -1
- package/dist/api/fillet.d.ts.map +1 -1
- package/dist/api/fillet.js +6 -5
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/generated/operations.js +16 -16
- package/dist/api/generated/operations.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
- package/dist/api/generated/script-face-manifest.js +0 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/generated/script-face.d.ts +1 -4
- package/dist/api/generated/script-face.d.ts.map +1 -1
- package/dist/api/generated/script-face.js +2 -3
- package/dist/api/generated/script-face.js.map +1 -1
- package/dist/api/generated/sketching.js +1 -1
- package/dist/api/generated/sketching.js.map +1 -1
- package/dist/api/generated/topology.d.ts +0 -48
- package/dist/api/generated/topology.d.ts.map +1 -1
- package/dist/api/generated/topology.js +20 -62
- package/dist/api/generated/topology.js.map +1 -1
- package/dist/api/import-brep.d.ts +36 -0
- package/dist/api/import-brep.d.ts.map +1 -0
- package/dist/api/import-brep.js +72 -0
- package/dist/api/import-brep.js.map +1 -0
- package/dist/api/import-step.d.ts +28 -0
- package/dist/api/import-step.d.ts.map +1 -0
- package/dist/api/import-step.js +57 -0
- package/dist/api/import-step.js.map +1 -0
- package/dist/api/index.d.ts +7 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +19 -5
- package/dist/api/index.js.map +1 -1
- package/dist/api/internal/compat-op.d.ts.map +1 -1
- package/dist/api/internal/compat-op.js +2 -1
- package/dist/api/internal/compat-op.js.map +1 -1
- package/dist/api/knurl.d.ts.map +1 -1
- package/dist/api/knurl.js +1 -0
- package/dist/api/knurl.js.map +1 -1
- package/dist/api/load.d.ts +3 -1
- package/dist/api/load.d.ts.map +1 -1
- package/dist/api/load.js +3 -1
- package/dist/api/load.js.map +1 -1
- package/dist/api/pattern.d.ts +32 -0
- package/dist/api/pattern.d.ts.map +1 -0
- package/dist/api/pattern.js +121 -0
- package/dist/api/pattern.js.map +1 -0
- package/dist/api/place.d.ts +35 -0
- package/dist/api/place.d.ts.map +1 -0
- package/dist/api/place.js +113 -0
- package/dist/api/place.js.map +1 -0
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +10 -3
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/screw.d.ts.map +1 -1
- package/dist/api/screw.js +1 -0
- package/dist/api/screw.js.map +1 -1
- package/dist/api/sdf.d.ts.map +1 -1
- package/dist/api/sdf.js +1 -0
- package/dist/api/sdf.js.map +1 -1
- package/dist/api/sketch.d.ts.map +1 -1
- package/dist/api/sketch.js +1 -0
- package/dist/api/sketch.js.map +1 -1
- package/dist/api/split.d.ts +31 -0
- package/dist/api/split.d.ts.map +1 -0
- package/dist/api/split.js +96 -0
- package/dist/api/split.js.map +1 -0
- package/dist/api/surface/arg-spec.d.ts +9 -0
- package/dist/api/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js +49 -30
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/svgExtrude.d.ts.map +1 -1
- package/dist/api/svgExtrude.js +1 -0
- package/dist/api/svgExtrude.js.map +1 -1
- package/dist/api/text.d.ts.map +1 -1
- package/dist/api/text.js +1 -0
- package/dist/api/text.js.map +1 -1
- package/dist/api/topo-resolve.d.ts.map +1 -1
- package/dist/api/topo-resolve.js +65 -3
- package/dist/api/topo-resolve.js.map +1 -1
- package/dist/api/transform.d.ts +4 -0
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +44 -12
- package/dist/api/transform.js.map +1 -1
- package/dist/brep/brep-ops.d.ts +34 -1
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +62 -22
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +8 -0
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brepkit.js +6 -1
- package/dist/brep/engine/adapters/brepkit.js.map +1 -1
- package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
- package/dist/brep/engine/adapters/occt.js +24 -1
- package/dist/brep/engine/adapters/occt.js.map +1 -1
- package/dist/brep/engine/primitives.d.ts +17 -0
- package/dist/brep/engine/primitives.d.ts.map +1 -1
- package/dist/brep/engine/primitives.js.map +1 -1
- package/dist/brep/engine/types.d.ts +49 -6
- package/dist/brep/engine/types.d.ts.map +1 -1
- package/dist/brep/engine/types.js.map +1 -1
- package/dist/brep/export/step.d.ts.map +1 -1
- package/dist/brep/export/step.js +6 -1
- package/dist/brep/export/step.js.map +1 -1
- package/dist/brep/face-evolution.d.ts +78 -8
- package/dist/brep/face-evolution.d.ts.map +1 -1
- package/dist/brep/face-evolution.js +130 -17
- package/dist/brep/face-evolution.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +27 -1
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/cad-runtime/admit-compat-lib.d.ts +19 -1
- package/dist/cad-runtime/admit-compat-lib.d.ts.map +1 -1
- package/dist/cad-runtime/admit-compat-lib.js +21 -1
- package/dist/cad-runtime/admit-compat-lib.js.map +1 -1
- package/dist/cad-runtime/backend-dispatch.d.ts +44 -3
- package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
- package/dist/cad-runtime/backend-dispatch.js +46 -3
- package/dist/cad-runtime/backend-dispatch.js.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.d.ts +2 -0
- package/dist/cad-runtime/browser-lib-loader.d.ts.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.js +9 -1
- package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +14 -4
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/module-registry.d.ts +3 -1
- package/dist/cad-runtime/module-registry.d.ts.map +1 -1
- package/dist/cad-runtime/module-registry.js +13 -1
- package/dist/cad-runtime/module-registry.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +7 -0
- package/dist/cad-runtime/ports.d.ts.map +1 -1
- package/dist/cad-runtime/ports.js.map +1 -1
- package/dist/cad-runtime/runtime-concurrent-error.d.ts +38 -0
- package/dist/cad-runtime/runtime-concurrent-error.d.ts.map +1 -0
- package/dist/cad-runtime/runtime-concurrent-error.js +43 -0
- package/dist/cad-runtime/runtime-concurrent-error.js.map +1 -0
- package/dist/cad-runtime/runtime.d.ts +54 -2
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +186 -10
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +22 -0
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +82 -12
- package/dist/define-op.js.map +1 -1
- package/dist/fcstd/attachment.d.ts +8 -1
- package/dist/fcstd/attachment.d.ts.map +1 -1
- package/dist/fcstd/attachment.js +7 -1
- package/dist/fcstd/attachment.js.map +1 -1
- package/dist/fcstd/build-fai-zip.d.ts.map +1 -1
- package/dist/fcstd/build-fai-zip.js +12 -7
- package/dist/fcstd/build-fai-zip.js.map +1 -1
- package/dist/fcstd/codegen.d.ts +10 -1
- package/dist/fcstd/codegen.d.ts.map +1 -1
- package/dist/fcstd/codegen.js +150 -48
- package/dist/fcstd/codegen.js.map +1 -1
- package/dist/fcstd/contour.d.ts.map +1 -1
- package/dist/fcstd/contour.js +23 -24
- package/dist/fcstd/contour.js.map +1 -1
- package/dist/fcstd/convert.d.ts +2 -18
- package/dist/fcstd/convert.d.ts.map +1 -1
- package/dist/fcstd/convert.js +35 -53
- package/dist/fcstd/convert.js.map +1 -1
- package/dist/fcstd/external-geo.d.ts +12 -1
- package/dist/fcstd/external-geo.d.ts.map +1 -1
- package/dist/fcstd/external-geo.js +15 -1
- package/dist/fcstd/external-geo.js.map +1 -1
- package/dist/fcstd/feature-translate.d.ts +21 -1
- package/dist/fcstd/feature-translate.d.ts.map +1 -1
- package/dist/fcstd/feature-translate.js +108 -6
- package/dist/fcstd/feature-translate.js.map +1 -1
- package/dist/fcstd/structural-types.d.ts +83 -0
- package/dist/fcstd/structural-types.d.ts.map +1 -0
- package/dist/fcstd/structural-types.js +116 -0
- package/dist/fcstd/structural-types.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lang/determinism-scanner.d.ts +62 -0
- package/dist/lang/determinism-scanner.d.ts.map +1 -0
- package/dist/lang/determinism-scanner.js +619 -0
- package/dist/lang/determinism-scanner.js.map +1 -0
- package/dist/lang/symbol-table.generated.d.ts +7 -3
- package/dist/lang/symbol-table.generated.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.js +7 -3
- package/dist/lang/symbol-table.generated.js.map +1 -1
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +3 -2
- package/dist/mesh/index.js.map +1 -1
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +56 -2
- package/dist/node-host/cli.js.map +1 -1
- package/dist/runtime-state.d.ts +18 -6
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +9 -1
- package/dist/runtime-state.js.map +1 -1
- package/dist/shape.d.ts +15 -0
- package/dist/shape.d.ts.map +1 -1
- package/dist/shape.js +26 -3
- package/dist/shape.js.map +1 -1
- package/dist/topology/naming/build-naming.d.ts +14 -30
- package/dist/topology/naming/build-naming.d.ts.map +1 -1
- package/dist/topology/naming/build-naming.js +21 -54
- package/dist/topology/naming/build-naming.js.map +1 -1
- package/dist/topology/naming/capture-topo-ref.d.ts.map +1 -1
- package/dist/topology/naming/capture-topo-ref.js +5 -0
- package/dist/topology/naming/capture-topo-ref.js.map +1 -1
- package/dist/topology/naming/index.d.ts +3 -0
- package/dist/topology/naming/index.d.ts.map +1 -1
- package/dist/topology/naming/index.js +3 -0
- package/dist/topology/naming/index.js.map +1 -1
- package/dist/topology/naming/lineage-resolve.d.ts +80 -0
- package/dist/topology/naming/lineage-resolve.d.ts.map +1 -0
- package/dist/topology/naming/lineage-resolve.js +120 -0
- package/dist/topology/naming/lineage-resolve.js.map +1 -0
- package/dist/topology/naming/lineage.d.ts +349 -0
- package/dist/topology/naming/lineage.d.ts.map +1 -0
- package/dist/topology/naming/lineage.js +398 -0
- package/dist/topology/naming/lineage.js.map +1 -0
- package/dist/topology/naming/migrate.d.ts +41 -0
- package/dist/topology/naming/migrate.d.ts.map +1 -0
- package/dist/topology/naming/migrate.js +88 -0
- package/dist/topology/naming/migrate.js.map +1 -0
- package/dist/topology/naming/role-name.d.ts +176 -0
- package/dist/topology/naming/role-name.d.ts.map +1 -0
- package/dist/topology/naming/role-name.js +344 -0
- package/dist/topology/naming/role-name.js.map +1 -0
- package/dist/topology/naming/roles.d.ts +20 -22
- package/dist/topology/naming/roles.d.ts.map +1 -1
- package/dist/topology/naming/roles.js +51 -49
- package/dist/topology/naming/roles.js.map +1 -1
- package/dist/topology/naming/types.d.ts +65 -18
- package/dist/topology/naming/types.d.ts.map +1 -1
- package/dist/topology/naming/types.js.map +1 -1
- package/dist/weapp.d.ts +1 -1
- package/dist/weapp.d.ts.map +1 -1
- package/dist/weapp.js +1 -1
- package/dist/weapp.js.map +1 -1
- package/package.json +1 -1
package/dist/define-op.js
CHANGED
|
@@ -25,13 +25,15 @@
|
|
|
25
25
|
* the Shape type and the structural `isMeshShape` guard) — the dist/sdk.js
|
|
26
26
|
* static-import guard keeps passing.
|
|
27
27
|
*/
|
|
28
|
-
import { dispatchPath } from './cad-runtime/backend-dispatch.js';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
28
|
+
import { dispatchPath, firstMissingCapability } from './cad-runtime/backend-dispatch.js';
|
|
29
|
+
import { CONTRACT_VERSION, BrepUnsupportedError, MeshUnsupportedError, getCurrentStmt, getRuntimeState, nameOf, } from './runtime-state.js';
|
|
30
|
+
import { asStmtId } from './identity.js';
|
|
31
|
+
import { isShape, solid, fromBrep, getSlot } from './shape.js';
|
|
31
32
|
import { isMeshShape } from './mesh/types.js';
|
|
32
33
|
import { fromHandle, meshHandle, isOcctHandle } from './brep/handle-bridge.js';
|
|
33
34
|
import { positionalToObject } from './api/internal/dual-form-args.js';
|
|
34
35
|
import { toOpFailure, unwrapResult, OpError } from './api/internal/result-unwrap.js';
|
|
36
|
+
import { runtimeLineage } from './topology/naming/lineage.js';
|
|
35
37
|
/**
|
|
36
38
|
* Geometry-input recognition for dispatch auto-collection.
|
|
37
39
|
*
|
|
@@ -149,6 +151,7 @@ export function defineOp(decl) {
|
|
|
149
151
|
outputs: decl.outputs,
|
|
150
152
|
schema: decl.schema,
|
|
151
153
|
slotMap: decl.slotMap,
|
|
154
|
+
naming: decl.naming,
|
|
152
155
|
};
|
|
153
156
|
// Async wrapper: implementations may be sync or async (stdlib mesh paths are
|
|
154
157
|
// often async, e.g. drill/engrave/boolean). The compiled .fai.js product always
|
|
@@ -163,16 +166,83 @@ export function defineOp(decl) {
|
|
|
163
166
|
// Compat: bare ManifoldMeshData args (host geoToManifoldMesh output) are
|
|
164
167
|
// geometry inputs too — old form passed [input] so they reached the mesh path.
|
|
165
168
|
const inputs = callArgs.filter(isGeometryInput);
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
// §1.4 lineage registration (plan §4.3): every top-level dual-op execution
|
|
170
|
+
// records a blood-line node via `runtimeLineage.register`, which enforces
|
|
171
|
+
// N1 (untracked input → throw, never default to chain-root) / N2
|
|
172
|
+
// (stmt↔anchor mismatch) / N3 (conflicting re-register). The graph is
|
|
173
|
+
// cleared per program execution (direct-executor runCode) and C1 guarantees
|
|
174
|
+
// a single live runtime, so the anchor is authoritative inside a statement.
|
|
175
|
+
// Skip when no anchor is set (the op was invoked outside a statement
|
|
176
|
+
// context — there is no lineage to record, and N2 must not fire on a context
|
|
177
|
+
// that legitimately has none).
|
|
178
|
+
//
|
|
179
|
+
// Guard: a statement executes exactly one *top-level* op; an op's
|
|
180
|
+
// implementation may invoke other ops (or itself) internally, and those
|
|
181
|
+
// nested calls share the same `getCurrentStmt()` anchor. They are
|
|
182
|
+
// implementation details, not statements, so they must NOT register a second
|
|
183
|
+
// node under the same StmtId — that would trip N3 (E_TOPO_DUPLICATE_STMT)
|
|
184
|
+
// on identical content. Only the outermost `wrapped` for the current
|
|
185
|
+
// statement registers; the flag below stays set for the *entire* statement
|
|
186
|
+
// execution (including the awaited impl), so nested calls see it and skip.
|
|
187
|
+
const anchor = getCurrentStmt();
|
|
188
|
+
const st = getRuntimeState();
|
|
189
|
+
const isOuter = anchor != null && st.registeredStmtId !== anchor.id;
|
|
190
|
+
if (isOuter)
|
|
191
|
+
st.registeredStmtId = asStmtId(anchor.id);
|
|
192
|
+
try {
|
|
193
|
+
if (isOuter && anchor) {
|
|
194
|
+
runtimeLineage.register({
|
|
195
|
+
stmt: asStmtId(anchor.id),
|
|
196
|
+
op: opLabel(meta),
|
|
197
|
+
inputs,
|
|
198
|
+
outputs: anchor.outputs,
|
|
199
|
+
provenance: meta.naming,
|
|
200
|
+
}, {
|
|
201
|
+
nameOf,
|
|
202
|
+
currentStmt: () => {
|
|
203
|
+
const a = getCurrentStmt();
|
|
204
|
+
return a ? { id: a.id } : undefined;
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
// D5 capability routing: feed the first missing capability to dispatchPath
|
|
209
|
+
// (auto degrades to mesh, brep mode errors). Matched as a concrete name
|
|
210
|
+
// against the engine's declaration set (family booleans + its `evolution`
|
|
211
|
+
// list of *WithHistory kernel function names) — see firstMissingCapability.
|
|
212
|
+
const missing = firstMissingCapability(meta.capabilities);
|
|
213
|
+
const path = dispatchPath(inputs, meta, missing);
|
|
214
|
+
if (path === 'brep') {
|
|
215
|
+
const r = await runImpl(meta, decl.brep, callArgs);
|
|
216
|
+
const out = meta.outputs ? wrapByKeys(r, meta.outputs, wrapBrepOne) : wrapBrepOne(r);
|
|
217
|
+
// 1.10 前置①:执行期把 hash 演化挂到血缘节点(kernel 类回走推进的数据源)。
|
|
218
|
+
// 演化在几何算完那一刻可得(fromBrep → slot.faceEvolution),事后补挂不参与
|
|
219
|
+
// N3 的内容比较(lineage.ts 设计如此)。无演化(identity/construct 等无历史
|
|
220
|
+
// 输出)时跳过——identity 类推进不依赖演化,construct 词汇在节点 provenance 里。
|
|
221
|
+
const outShape = (typeof out === 'object' && out !== null ? Object.values(out)[0] : out);
|
|
222
|
+
const evolution = outShape ? getSlot(outShape)?.faceEvolution : undefined;
|
|
223
|
+
if (outShape && evolution) {
|
|
224
|
+
runtimeLineage.attachEvolution(asStmtId(anchor.id), evolution);
|
|
225
|
+
}
|
|
226
|
+
// 1.10 前置③:part 键的 roleTable 旁挂在这里记录(不是 fromBrep)——
|
|
227
|
+
// impl 返回后 anchor.outputs 名字已定,而 fromBrep 时刻 shape 还未被
|
|
228
|
+
// executor 命名(nameOf 为 undefined)。op 实现读输入表(inputRoleTable)
|
|
229
|
+
// 与解析读表(tableOfPart)都走这份 part 键权威表。
|
|
230
|
+
if (outShape && anchor && anchor.outputs.length > 0) {
|
|
231
|
+
const stmtId = asStmtId(anchor.id);
|
|
232
|
+
const table = runtimeLineage.outputTableOf(stmtId);
|
|
233
|
+
const solid = runtimeLineage.outputHandleOf(stmtId);
|
|
234
|
+
if (table)
|
|
235
|
+
runtimeLineage.recordOutput(stmtId, table, solid, anchor.outputs[0]);
|
|
236
|
+
}
|
|
237
|
+
return out;
|
|
238
|
+
}
|
|
239
|
+
const m = await runImpl(meta, decl.mesh, callArgs);
|
|
240
|
+
return meta.outputs ? wrapByKeys(m, meta.outputs, wrapMeshOne) : wrapMeshOne(m);
|
|
241
|
+
}
|
|
242
|
+
finally {
|
|
243
|
+
// 同语句去重标记不在 op 粒度清理——语句边界由 runtime-state.setCurrentStmt
|
|
244
|
+
// 在锚点变化时重置;TS 库函数体内连续 op 调用共享锚点,嵌套调用正确跳过。
|
|
173
245
|
}
|
|
174
|
-
const m = await runImpl(meta, decl.mesh, callArgs);
|
|
175
|
-
return meta.outputs ? wrapByKeys(m, meta.outputs, wrapMeshOne) : wrapMeshOne(m);
|
|
176
246
|
};
|
|
177
247
|
Object.defineProperty(wrapped, DUAL_OP_META, { value: meta, enumerable: false });
|
|
178
248
|
return wrapped;
|
package/dist/define-op.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-op.js","sourceRoot":"","sources":["../src/define-op.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * define-op — dual-path implementation decorator for geometry functions\n * (D-face contract: mesh mandatory as the default path, BREP optional).\n *\n *\n * `defineOp({ mesh?, brep?, ... })` declares the implementation set of a\n * geometry function (a function whose signature returns `SolidShape`). The\n * wrapper:\n * - auto-collects geometry inputs via `args.filter(isGeometryInput)` — a shape\n * that is identity-registered (`isShape`) or a structural mesh shape\n * (`isMeshShape`, positions + indices — e.g. bare ManifoldMeshData handed in\n * by a host via `geoToManifoldMesh`). The old per-function form passed the\n * actual geometry args (`dispatchPath([input], ...)`), so a bare mesh input\n * dispatched to the mesh path (`hasBrep=false`); the re-collection must keep\n * that compatibility. No `inputs` field — decided at runtime by the args\n * themselves, not the author.\n * - calls the engine's `dispatchPath` to select brep/mesh by mode (static,\n * no runtime fallback);\n * - wraps raw products: mesh path → `solid()`, brep path → `fromHandle()` /\n * `fromBrep()` (D3/D4: products must come from constructors, brep products\n * must carry a BREP slot).\n *\n * Zero heavy runtime dependencies: imports only runtime-state / shape /\n * handle-bridge / backend-dispatch / mesh/types (a zero-import module holding\n * the Shape type and the structural `isMeshShape` guard) — the dist/sdk.js\n * static-import guard keeps passing.\n */\n\nimport { dispatchPath, type BrepCapabilityName } from './cad-runtime/backend-dispatch'\nimport {\n getBackends,\n CONTRACT_VERSION,\n BrepUnsupportedError,\n MeshUnsupportedError,\n} from './runtime-state'\nimport { isShape, solid, fromBrep } from './shape'\nimport { isMeshShape } from './mesh/types'\nimport { fromHandle, meshHandle, isOcctHandle } from './brep/handle-bridge'\nimport { positionalToObject, type SlotMap } from './api/internal/dual-form-args'\nimport { toOpFailure, unwrapResult, OpError } from './api/internal/result-unwrap'\nimport type { Shape } from './mesh/types'\nimport type { BrepHandle } from './brep/engine/types'\n\n/** Raw mesh data (structurally identical to Shape; mesh impls return it). */\nexport type MeshData = { positions: Float32Array; indices: Uint32Array }\n\n/**\n * Geometry-input recognition for dispatch auto-collection.\n *\n * Compat rule: the old per-function form passed the *actual* geometry args to\n * `dispatchPath` (`[input]` / `shapes`), so a bare ManifoldMeshData object\n * (e.g. `geoToManifoldMesh` output passed straight by a host) had no BREP slot\n * → `hasBrep=false` → mesh path. defineOp must keep that: an input counts as\n * geometry when it is identity-registered (`isShape`, constructor product) OR\n * structurally a mesh shape (`positions` + `indices`). Params objects and other\n * scalar args are not geometry inputs.\n *\n * @param v - the candidate argument.\n * @returns true when the argument is a geometry input (registered shape or bare mesh data).\n */\nexport function isGeometryInput(v: unknown): v is Shape {\n return isShape(v) || isMeshShape(v)\n}\n\n/** Product of a mesh implementation: raw mesh data, a wrapped Shape, or (with `outputs`) a record of named products. */\nexport type MeshProduct = MeshData | Shape | Record<string, MeshData | Shape>\n\n/** Mesh implementation: sync or async (stdlib mesh paths are often async); returns a mesh product. */\nexport type MeshImpl<A extends unknown[]> = (...args: A) => MeshProduct | Promise<MeshProduct>\n\n/** BREP implementation result: a raw handle, or a handle plus face evolution. */\nexport interface BrepResult {\n solid: BrepHandle\n faceEvolution?: Map<number, number[]>\n}\n\n/** Product of a BREP implementation: a raw handle, { solid, faceEvolution }, a wrapped Shape, or (with `outputs`) a record of named products. */\nexport type BrepProduct = BrepHandle | BrepResult | Shape | Record<string, BrepHandle | BrepResult | Shape>\n\n/** BREP implementation: sync or async; returns a brep product. */\nexport type BrepImpl<A extends unknown[]> = (...args: A) => BrepProduct | Promise<BrepProduct>\n\n/** Optional declaration: capabilities (D5) and named multi-products (split, scheme C). */\nexport interface DualOpOptions {\n /** Op name (error messages); falls back to an anonymous prefix when absent. */\n name?: string\n capabilities?: BrepCapabilityName[]\n outputs?: string[]\n /** L3 schema per named parameter (G1 codegen + UI panel, plain string form). */\n schema?: Record<string, string>\n /**\n * D11 slot-map declaration (§4.2): the positional→object boxing table\n * (SlotMap) mapping a brepjs-style positional call onto this op's native\n * object form. Ops without it accept only the form their implementation\n * natively takes.\n */\n slotMap?: SlotMap\n}\n\n/** Implementation set (at least one of mesh/brep is required, D1/D1b); options are siblings of the implementations. */\nexport type DualOpImpls<A extends unknown[]> =\n | (DualOpOptions & { mesh: MeshImpl<A>; brep?: BrepImpl<A> })\n | (DualOpOptions & { mesh?: never; brep: BrepImpl<A> })\n\n/** Metadata hung on the wrapped function object (K5: function info is data). */\nexport interface DualOpMeta {\n kind: 'dual-op'\n mesh?: unknown\n brep?: unknown\n /** Op name (error messages). */\n name?: string\n capabilities?: BrepCapabilityName[]\n outputs?: string[]\n schema?: Record<string, string>\n /** D11 slot-map declaration (positional → object boxing table, §9 naming). */\n slotMap?: SlotMap\n}\n\n/** Property key carrying DualOpMeta on wrapped functions. */\nexport const DUAL_OP_META = '__faijs__dualOp'\n\ntype MetaCarrier = { [DUAL_OP_META]?: DualOpMeta }\n\nfunction wrapMeshOne(v: unknown): Shape {\n if (isShape(v)) return v\n return solid(v as MeshData)\n}\n\nfunction wrapBrepOne(v: unknown): Shape {\n if (isShape(v)) return v\n if (v !== null && typeof v === 'object' && 'faceEvolution' in v) {\n const res = v as BrepResult\n return fromBrep(meshHandle(res.solid), res)\n }\n // A plain object that is not a Shape and not an OCCT handle is a data\n // product (e.g. a compat fn returning a sheetmetal-style record), not a\n // geometry handle — pass it through so it lands in the engine's value\n // store instead of being tessellated as if it were a bare handle. Native\n // OCCT handles from an implementation are hand-computed shape numbers\n // (from a branded number return) or objects; only the number path reaches\n // fromHandle. The handle/data distinction must go through the shared\n // isOcctHandle leaf (handle-bridge) — never a hardcoded '__occtWasm' in v.\n if (v !== null && typeof v === 'object' && !isOcctHandle(v)) {\n return v as unknown as Shape\n }\n return fromHandle(v)\n}\n\nfunction wrapByKeys(r: unknown, keys: string[], wrapOne: (v: unknown) => Shape): Record<string, Shape> {\n const src = (r ?? {}) as Record<string, unknown>\n const out: Record<string, Shape> = {}\n for (const k of keys) {\n const v = src[k]\n // An output may be an array (e.g. the compat adapter adopts each element of\n // an array-valued `outputs` field); wrap element-wise so arrays stay arrays.\n out[k] = Array.isArray(v) ? (v.map(wrapOne) as unknown as Shape) : wrapOne(v)\n }\n return out\n}\n\n/** Human-readable op label for error messages (falls back when unnamed). */\nfunction opLabel(meta: DualOpMeta): string {\n return meta.name ?? '<anon>'\n}\n\n/**\n * Run one implementation through the unified Result boundary (§5.2, D1).\n *\n * Transition contract: an implementation may\n * ① return a `Result` → unwrapped here (`err` becomes a throw);\n * ② throw → normalized into an op-labelled error;\n * ③ return a plain product → passed through untouched.\n *\n * The two engine-level routing errors keep their class: `runtime.ts` matches\n * `BrepUnsupportedError` / `MeshUnsupportedError` by `instanceof` to turn them\n * into `ExecutionResult.failedAt`, so they must not be re-wrapped.\n *\n * @param meta - the op's metadata (name).\n * @param impl - the implementation to run.\n * @param args - the normalized argument list.\n * @returns the (unwrapped) implementation product.\n */\nasync function runImpl(\n meta: DualOpMeta,\n impl: ((...a: unknown[]) => unknown) | undefined,\n args: unknown[],\n): Promise<unknown> {\n const label = opLabel(meta)\n let product: unknown\n try {\n product = await (impl as (...a: unknown[]) => unknown)(...args)\n } catch (e) {\n if (e instanceof BrepUnsupportedError || e instanceof MeshUnsupportedError) throw e\n // An OpError is already the engine-recognizable statement failure (thrown\n // by the compat adapter's Result unwrap, or by impls returning a Result);\n // re-wrapping it into a plain Error would make CadRuntime treat it as an\n // uncaught bug instead of a statement failure.\n if (e instanceof OpError) throw e\n throw toOpFailure(label, e)\n }\n return unwrapResult(product, label)\n}\n\n/**\n * Declare a geometry function's dual-path implementation set.\n *\n * At least one implementation (mesh or brep) is required — enforced at\n * compile time by the union type and at construction time by a runtime check.\n * Geometry inputs are auto-collected by identity-or-structure\n * (`args.filter(isGeometryInput)` = `isShape` ∨ `isMeshShape`); raw mesh\n * products are wrapped by `solid()`, raw brep products by\n * `fromHandle()` / `fromBrep()`. `mode` selects the engine path via the\n * engine's static `dispatchPath` — the author never writes an `if (path)`\n * branch.\n *\n * @param decl - the declaration object: implementations `{ mesh }` (mesh-only),\n * `{ brep }` (brep-only, D1b), or `{ mesh, brep }` (dual-path), plus optional\n * `capabilities` (D5: missing capability degrades in auto, errors in brep mode)\n * and `outputs` (named multi-products, e.g. split) as siblings.\n * @returns the wrapped geometry function with dual-op metadata attached.\n */\nexport function defineOp<A extends unknown[]>(\n decl: DualOpImpls<A> & { outputs: string[] },\n): ((...args: A) => Promise<Record<string, Shape>>) & MetaCarrier\n/**\n * Overload without `outputs`: single-product functions resolve to a `Promise<Shape>`.\n * @param decl - the declaration object: implementations `{ mesh }`, `{ brep }`, or `{ mesh, brep }`.\n * @returns the wrapped geometry function with dual-op metadata attached.\n */\nexport function defineOp<A extends unknown[]>(\n decl: DualOpImpls<A>,\n): ((...args: A) => Promise<Shape>) & MetaCarrier\n/** Implementation signature (not visible to callers); matches the union of both overloads. */\nexport function defineOp<A extends unknown[]>(\n decl: DualOpImpls<A>,\n): ((...args: A) => Promise<Shape | Record<string, Shape>>) & MetaCarrier {\n // Construction-time check (②): implementations must be functions, then at\n // least one implementation must be present.\n if (decl.mesh !== undefined && typeof decl.mesh !== 'function') {\n throw new Error('[faijs/defineOp] mesh must be a function')\n }\n if (decl.brep !== undefined && typeof decl.brep !== 'function') {\n throw new Error('[faijs/defineOp] brep must be a function')\n }\n if (typeof decl.mesh !== 'function' && typeof decl.brep !== 'function') {\n throw new Error('[faijs/defineOp] at least one implementation (mesh or brep) is required')\n }\n\n const meta: DualOpMeta = {\n kind: 'dual-op',\n mesh: decl.mesh,\n brep: decl.brep,\n name: decl.name,\n capabilities: decl.capabilities,\n outputs: decl.outputs,\n schema: decl.schema,\n slotMap: decl.slotMap,\n }\n\n // Async wrapper: implementations may be sync or async (stdlib mesh paths are\n // often async, e.g. drill/engrave/boolean). The compiled .fai.js product always\n // awaits the call, so returning a Promise is transparent.\n const wrapped = async (...args: A): Promise<Shape | Record<string, Shape>> => {\n // D11 (§4.2): faijs-native ops declare an object-form implementation, so a\n // brepjs-style positional call is boxed into the object form here — before\n // dispatch, so geometry inputs are collected from the normalized arg list.\n const callArgs = (\n meta.slotMap ? positionalToObject(args as unknown[], meta.slotMap, opLabel(meta)) : args\n ) as A\n // Geometry inputs: identity-or-structure auto collection (execution-time\n // read, same nature as hasBrep — decided before the implementation runs).\n // Compat: bare ManifoldMeshData args (host geoToManifoldMesh output) are\n // geometry inputs too — old form passed [input] so they reached the mesh path.\n const inputs = (callArgs as unknown[]).filter(isGeometryInput) as Shape[]\n // D5 capability routing: feed the first missing capability to dispatchPath\n // (auto degrades to mesh, brep mode errors).\n const missing = meta.capabilities?.find((cap) => !getBackends().config.brepCapabilities?.[cap])\n const path = dispatchPath(inputs, meta, missing)\n if (path === 'brep') {\n const r = await runImpl(meta, decl.brep as unknown as ((...a: unknown[]) => unknown) | undefined, callArgs)\n return meta.outputs ? wrapByKeys(r, meta.outputs, wrapBrepOne) : wrapBrepOne(r)\n }\n const m = await runImpl(meta, decl.mesh as unknown as ((...a: unknown[]) => unknown) | undefined, callArgs)\n return meta.outputs ? wrapByKeys(m, meta.outputs, wrapMeshOne) : wrapMeshOne(m)\n }\n\n Object.defineProperty(wrapped, DUAL_OP_META, { value: meta, enumerable: false })\n return wrapped as ((...args: A) => Promise<Shape | Record<string, Shape>>) & MetaCarrier\n}\n\n/**\n * Assembly-time validation (③, strict mode, D-4): a library that exports any\n * dual-op function must carry a matching `contractVersion`, and every exported\n * dual-op must be structurally valid (mesh a function, brep a function or\n * undefined, capabilities/outputs well-formed). Called by `registerLib`.\n *\n * Functions without dual-op metadata are left untouched (declarative\n * enforcement boundary — K5 forbids name-based classification).\n *\n * @param lib - the library namespace object being registered.\n */\n/**\n * Detect whether a library namespace exports any dual-op function (carries\n * `DUAL_OP_META`). Used by `registerLib`'s inferred `autoLift` default: a\n * library that already declares dual-ops does not need bare-function lifting.\n *\n * @param ns - the library namespace object.\n * @returns `true` if at least one exported value is a dual-op function.\n */\nexport function hasDualOp(ns: Record<string, unknown>): boolean {\n const values = Object.values(ns)\n return values.some((v) => typeof v === 'function' && (v as MetaCarrier)[DUAL_OP_META])\n}\n\n/**\n * Assert that a library conforms to the dual-op contract: if it exports any\n * dual-op function, it must also export `contractVersion` matching the engine's.\n *\n * @param lib - the library namespace object being registered.\n * @throws {Error} when dual-op functions are present without a matching contract version.\n */\nexport function assertLibConforms(lib: Record<string, unknown>): void {\n if (hasDualOp(lib) && lib.contractVersion !== CONTRACT_VERSION) {\n throw new Error(\n `[faijs] library with dual-op functions must export contractVersion = ${CONTRACT_VERSION} (got ${String(lib.contractVersion)})`,\n )\n }\n\n for (const [name, value] of Object.entries(lib)) {\n if (typeof value !== 'function') continue\n const meta = (value as MetaCarrier)[DUAL_OP_META]\n if (!meta || meta.kind !== 'dual-op') continue\n if (typeof meta.mesh !== 'function' && typeof meta.brep !== 'function') {\n throw new Error(`[faijs] lib function '${name}' declares dual-op without any implementation`)\n }\n if (meta.mesh !== undefined && typeof meta.mesh !== 'function') {\n throw new Error(`[faijs] lib function '${name}' declares dual-op with a non-function mesh implementation`)\n }\n if (meta.brep !== undefined && typeof meta.brep !== 'function') {\n throw new Error(`[faijs] lib function '${name}' declares dual-op with a non-function brep implementation`)\n }\n if (meta.capabilities !== undefined && !Array.isArray(meta.capabilities)) {\n throw new Error(`[faijs] lib function '${name}' declares invalid capabilities (expected string[])`)\n }\n if (\n meta.outputs !== undefined\n && (!Array.isArray(meta.outputs) || meta.outputs.some((k) => typeof k !== 'string'))\n ) {\n throw new Error(`[faijs] lib function '${name}' declares invalid outputs (expected string[])`)\n }\n if (meta.schema !== undefined && !isValidSchema(meta.schema)) {\n throw new Error(`[faijs] lib function '${name}' declares invalid schema (expected Record<string, string>)`)\n }\n if (meta.name !== undefined && typeof meta.name !== 'string') {\n throw new Error(`[faijs] lib function '${name}' declares invalid name (expected string)`)\n }\n if (meta.slotMap !== undefined && !isValidSlotMap(meta.slotMap)) {\n throw new Error(\n `[faijs] lib function '${name}' declares invalid slotMap (expected { keys: string[]; vec3Keys?: string[]; shapeArity?: number })`,\n )\n }\n }\n}\n\n/** True when the D11 slot-map declaration has a non-empty string `keys` list. */\nfunction isValidSlotMap(form: unknown): form is SlotMap {\n if (form === null || typeof form !== 'object') return false\n const keys = (form as { keys?: unknown }).keys\n if (!Array.isArray(keys) || keys.some((k) => typeof k !== 'string')) return false\n const vec3 = (form as { vec3Keys?: unknown }).vec3Keys\n if (vec3 !== undefined && (!Array.isArray(vec3) || vec3.some((k) => typeof k !== 'string'))) return false\n const arity = (form as { shapeArity?: unknown }).shapeArity\n if (arity !== undefined && (typeof arity !== 'number' || !Number.isInteger(arity) || arity < 0)) return false\n return true\n}\n\n/** True when every schema value is a non-empty string. */\nfunction isValidSchema(schema: unknown): schema is Record<string, string> {\n if (schema === null || typeof schema !== 'object' || Array.isArray(schema)) return false\n return Object.values(schema).every((v) => typeof v === 'string' && v.length > 0)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"define-op.js","sourceRoot":"","sources":["../src/define-op.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * define-op — dual-path implementation decorator for geometry functions\n * (D-face contract: mesh mandatory as the default path, BREP optional).\n *\n *\n * `defineOp({ mesh?, brep?, ... })` declares the implementation set of a\n * geometry function (a function whose signature returns `SolidShape`). The\n * wrapper:\n * - auto-collects geometry inputs via `args.filter(isGeometryInput)` — a shape\n * that is identity-registered (`isShape`) or a structural mesh shape\n * (`isMeshShape`, positions + indices — e.g. bare ManifoldMeshData handed in\n * by a host via `geoToManifoldMesh`). The old per-function form passed the\n * actual geometry args (`dispatchPath([input], ...)`), so a bare mesh input\n * dispatched to the mesh path (`hasBrep=false`); the re-collection must keep\n * that compatibility. No `inputs` field — decided at runtime by the args\n * themselves, not the author.\n * - calls the engine's `dispatchPath` to select brep/mesh by mode (static,\n * no runtime fallback);\n * - wraps raw products: mesh path → `solid()`, brep path → `fromHandle()` /\n * `fromBrep()` (D3/D4: products must come from constructors, brep products\n * must carry a BREP slot).\n *\n * Zero heavy runtime dependencies: imports only runtime-state / shape /\n * handle-bridge / backend-dispatch / mesh/types (a zero-import module holding\n * the Shape type and the structural `isMeshShape` guard) — the dist/sdk.js\n * static-import guard keeps passing.\n */\n\nimport { dispatchPath, firstMissingCapability, type BrepCapabilityName } from './cad-runtime/backend-dispatch'\nimport {\n CONTRACT_VERSION,\n BrepUnsupportedError,\n MeshUnsupportedError,\n getCurrentStmt,\n getRuntimeState,\n nameOf,\n} from './runtime-state'\nimport { asStmtId, type PartName } from './identity'\nimport { isShape, solid, fromBrep, getSlot } from './shape'\nimport { isMeshShape } from './mesh/types'\nimport { fromHandle, meshHandle, isOcctHandle } from './brep/handle-bridge'\nimport { positionalToObject, type SlotMap } from './api/internal/dual-form-args'\nimport { toOpFailure, unwrapResult, OpError } from './api/internal/result-unwrap'\nimport type { Shape } from './mesh/types'\nimport type { BrepHandle } from './brep/engine/types'\nimport { type Provenance, runtimeLineage } from './topology/naming/lineage'\n\n/** Raw mesh data (structurally identical to Shape; mesh impls return it). */\nexport type MeshData = { positions: Float32Array; indices: Uint32Array }\n\n/**\n * Geometry-input recognition for dispatch auto-collection.\n *\n * Compat rule: the old per-function form passed the *actual* geometry args to\n * `dispatchPath` (`[input]` / `shapes`), so a bare ManifoldMeshData object\n * (e.g. `geoToManifoldMesh` output passed straight by a host) had no BREP slot\n * → `hasBrep=false` → mesh path. defineOp must keep that: an input counts as\n * geometry when it is identity-registered (`isShape`, constructor product) OR\n * structurally a mesh shape (`positions` + `indices`). Params objects and other\n * scalar args are not geometry inputs.\n *\n * @param v - the candidate argument.\n * @returns true when the argument is a geometry input (registered shape or bare mesh data).\n */\nexport function isGeometryInput(v: unknown): v is Shape {\n return isShape(v) || isMeshShape(v)\n}\n\n/**\n * §1.4 registration guard: the StmtId whose top-level `wrapped` is currently\n * registering a lineage node. Nested op calls (an impl invoking another op /\n * itself) share the same `getCurrentStmt()` anchor and are skipped so they\n * don't trip N3 (E_TOPO_DUPLICATE_STMT) with identical content. C1 (single\n * live runtime) means at most one statement registers at a time.\n *\n * The marker lives on the runtime state and is reset at statement boundaries\n * (runtime-state.setCurrentStmt: anchor change / end-of-statement), NOT at op\n * granularity — a TS library function (cq-compat Workplane op, etc.) may call\n * several defineOps within one statement, and only the first one must register.\n */\n\n/** Product of a mesh implementation: raw mesh data, a wrapped Shape, or (with `outputs`) a record of named products. */\nexport type MeshProduct = MeshData | Shape | Record<string, MeshData | Shape>\n\n/** Mesh implementation: sync or async (stdlib mesh paths are often async); returns a mesh product. */\nexport type MeshImpl<A extends unknown[]> = (...args: A) => MeshProduct | Promise<MeshProduct>\n\n/** BREP implementation result: a raw handle, or a handle plus face evolution. */\nexport interface BrepResult {\n solid: BrepHandle\n faceEvolution?: Map<number, number[]>\n}\n\n/** Product of a BREP implementation: a raw handle, { solid, faceEvolution }, a wrapped Shape, or (with `outputs`) a record of named products. */\nexport type BrepProduct = BrepHandle | BrepResult | Shape | Record<string, BrepHandle | BrepResult | Shape>\n\n/** BREP implementation: sync or async; returns a brep product. */\nexport type BrepImpl<A extends unknown[]> = (...args: A) => BrepProduct | Promise<BrepProduct>\n\n/** Optional declaration: capabilities (D5) and named multi-products (split, scheme C). */\nexport interface DualOpOptions {\n /** Op name (error messages); falls back to an anonymous prefix when absent. */\n name?: string\n capabilities?: BrepCapabilityName[]\n outputs?: string[]\n /** L3 schema per named parameter (G1 codegen + UI panel, plain string form). */\n schema?: Record<string, string>\n /**\n * D11 slot-map declaration (§4.2): the positional→object boxing table\n * (SlotMap) mapping a brepjs-style positional call onto this op's native\n * object form. Ops without it accept only the form their implementation\n * natively takes.\n */\n slotMap?: SlotMap\n /**\n * Topology identity provenance (plan §4.4 / Phase 2.3, **required**).\n * Declares the op's face-mapping category + new-face vocabulary.\n * The lineage registrar (§4.3) reads this to build the blood-line graph;\n * missing naming = compile-time error (G4: no undeclared ops).\n */\n naming: Provenance\n}\n\n/** Implementation set (at least one of mesh/brep is required, D1/D1b); options are siblings of the implementations. */\nexport type DualOpImpls<A extends unknown[]> =\n | (DualOpOptions & { mesh: MeshImpl<A>; brep?: BrepImpl<A> })\n | (DualOpOptions & { mesh?: never; brep: BrepImpl<A> })\n\n/** Metadata hung on the wrapped function object (K5: function info is data). */\nexport interface DualOpMeta {\n kind: 'dual-op'\n mesh?: unknown\n brep?: unknown\n /** Op name (error messages). */\n name?: string\n capabilities?: BrepCapabilityName[]\n outputs?: string[]\n schema?: Record<string, string>\n /** D11 slot-map declaration (positional → object boxing table, §9 naming). */\n slotMap?: SlotMap\n /** Topology identity provenance (Phase 2.3, mirrors DualOpOptions.naming). */\n naming: Provenance\n}\n\n/** Property key carrying DualOpMeta on wrapped functions. */\nexport const DUAL_OP_META = '__faijs__dualOp'\n\ntype MetaCarrier = { [DUAL_OP_META]?: DualOpMeta }\n\nfunction wrapMeshOne(v: unknown): Shape {\n if (isShape(v)) return v\n return solid(v as MeshData)\n}\n\nfunction wrapBrepOne(v: unknown): Shape {\n if (isShape(v)) return v\n if (v !== null && typeof v === 'object' && 'faceEvolution' in v) {\n const res = v as BrepResult\n return fromBrep(meshHandle(res.solid), res)\n }\n // A plain object that is not a Shape and not an OCCT handle is a data\n // product (e.g. a compat fn returning a sheetmetal-style record), not a\n // geometry handle — pass it through so it lands in the engine's value\n // store instead of being tessellated as if it were a bare handle. Native\n // OCCT handles from an implementation are hand-computed shape numbers\n // (from a branded number return) or objects; only the number path reaches\n // fromHandle. The handle/data distinction must go through the shared\n // isOcctHandle leaf (handle-bridge) — never a hardcoded '__occtWasm' in v.\n if (v !== null && typeof v === 'object' && !isOcctHandle(v)) {\n return v as unknown as Shape\n }\n return fromHandle(v)\n}\n\nfunction wrapByKeys(r: unknown, keys: string[], wrapOne: (v: unknown) => Shape): Record<string, Shape> {\n const src = (r ?? {}) as Record<string, unknown>\n const out: Record<string, Shape> = {}\n for (const k of keys) {\n const v = src[k]\n // An output may be an array (e.g. the compat adapter adopts each element of\n // an array-valued `outputs` field); wrap element-wise so arrays stay arrays.\n out[k] = Array.isArray(v) ? (v.map(wrapOne) as unknown as Shape) : wrapOne(v)\n }\n return out\n}\n\n/** Human-readable op label for error messages (falls back when unnamed). */\nfunction opLabel(meta: DualOpMeta): string {\n return meta.name ?? '<anon>'\n}\n\n/**\n * Run one implementation through the unified Result boundary (§5.2, D1).\n *\n * Transition contract: an implementation may\n * ① return a `Result` → unwrapped here (`err` becomes a throw);\n * ② throw → normalized into an op-labelled error;\n * ③ return a plain product → passed through untouched.\n *\n * The two engine-level routing errors keep their class: `runtime.ts` matches\n * `BrepUnsupportedError` / `MeshUnsupportedError` by `instanceof` to turn them\n * into `ExecutionResult.failedAt`, so they must not be re-wrapped.\n *\n * @param meta - the op's metadata (name).\n * @param impl - the implementation to run.\n * @param args - the normalized argument list.\n * @returns the (unwrapped) implementation product.\n */\nasync function runImpl(\n meta: DualOpMeta,\n impl: ((...a: unknown[]) => unknown) | undefined,\n args: unknown[],\n): Promise<unknown> {\n const label = opLabel(meta)\n let product: unknown\n try {\n product = await (impl as (...a: unknown[]) => unknown)(...args)\n } catch (e) {\n if (e instanceof BrepUnsupportedError || e instanceof MeshUnsupportedError) throw e\n // An OpError is already the engine-recognizable statement failure (thrown\n // by the compat adapter's Result unwrap, or by impls returning a Result);\n // re-wrapping it into a plain Error would make CadRuntime treat it as an\n // uncaught bug instead of a statement failure.\n if (e instanceof OpError) throw e\n throw toOpFailure(label, e)\n }\n return unwrapResult(product, label)\n}\n\n/**\n * Declare a geometry function's dual-path implementation set.\n *\n * At least one implementation (mesh or brep) is required — enforced at\n * compile time by the union type and at construction time by a runtime check.\n * Geometry inputs are auto-collected by identity-or-structure\n * (`args.filter(isGeometryInput)` = `isShape` ∨ `isMeshShape`); raw mesh\n * products are wrapped by `solid()`, raw brep products by\n * `fromHandle()` / `fromBrep()`. `mode` selects the engine path via the\n * engine's static `dispatchPath` — the author never writes an `if (path)`\n * branch.\n *\n * @param decl - the declaration object: implementations `{ mesh }` (mesh-only),\n * `{ brep }` (brep-only, D1b), or `{ mesh, brep }` (dual-path), plus optional\n * `capabilities` (D5: missing capability degrades in auto, errors in brep mode)\n * and `outputs` (named multi-products, e.g. split) as siblings.\n * @returns the wrapped geometry function with dual-op metadata attached.\n */\nexport function defineOp<A extends unknown[]>(\n decl: DualOpImpls<A> & { outputs: string[] },\n): ((...args: A) => Promise<Record<string, Shape>>) & MetaCarrier\n/**\n * Overload without `outputs`: single-product functions resolve to a `Promise<Shape>`.\n * @param decl - the declaration object: implementations `{ mesh }`, `{ brep }`, or `{ mesh, brep }`.\n * @returns the wrapped geometry function with dual-op metadata attached.\n */\nexport function defineOp<A extends unknown[]>(\n decl: DualOpImpls<A>,\n): ((...args: A) => Promise<Shape>) & MetaCarrier\n/** Implementation signature (not visible to callers); matches the union of both overloads. */\nexport function defineOp<A extends unknown[]>(\n decl: DualOpImpls<A>,\n): ((...args: A) => Promise<Shape | Record<string, Shape>>) & MetaCarrier {\n // Construction-time check (②): implementations must be functions, then at\n // least one implementation must be present.\n if (decl.mesh !== undefined && typeof decl.mesh !== 'function') {\n throw new Error('[faijs/defineOp] mesh must be a function')\n }\n if (decl.brep !== undefined && typeof decl.brep !== 'function') {\n throw new Error('[faijs/defineOp] brep must be a function')\n }\n if (typeof decl.mesh !== 'function' && typeof decl.brep !== 'function') {\n throw new Error('[faijs/defineOp] at least one implementation (mesh or brep) is required')\n }\n\n const meta: DualOpMeta = {\n kind: 'dual-op',\n mesh: decl.mesh,\n brep: decl.brep,\n name: decl.name,\n capabilities: decl.capabilities,\n outputs: decl.outputs,\n schema: decl.schema,\n slotMap: decl.slotMap,\n naming: decl.naming,\n }\n\n // Async wrapper: implementations may be sync or async (stdlib mesh paths are\n // often async, e.g. drill/engrave/boolean). The compiled .fai.js product always\n // awaits the call, so returning a Promise is transparent.\n const wrapped = async (...args: A): Promise<Shape | Record<string, Shape>> => {\n // D11 (§4.2): faijs-native ops declare an object-form implementation, so a\n // brepjs-style positional call is boxed into the object form here — before\n // dispatch, so geometry inputs are collected from the normalized arg list.\n const callArgs = (\n meta.slotMap ? positionalToObject(args as unknown[], meta.slotMap, opLabel(meta)) : args\n ) as A\n // Geometry inputs: identity-or-structure auto collection (execution-time\n // read, same nature as hasBrep — decided before the implementation runs).\n // Compat: bare ManifoldMeshData args (host geoToManifoldMesh output) are\n // geometry inputs too — old form passed [input] so they reached the mesh path.\n const inputs = (callArgs as unknown[]).filter(isGeometryInput) as Shape[]\n // §1.4 lineage registration (plan §4.3): every top-level dual-op execution\n // records a blood-line node via `runtimeLineage.register`, which enforces\n // N1 (untracked input → throw, never default to chain-root) / N2\n // (stmt↔anchor mismatch) / N3 (conflicting re-register). The graph is\n // cleared per program execution (direct-executor runCode) and C1 guarantees\n // a single live runtime, so the anchor is authoritative inside a statement.\n // Skip when no anchor is set (the op was invoked outside a statement\n // context — there is no lineage to record, and N2 must not fire on a context\n // that legitimately has none).\n //\n // Guard: a statement executes exactly one *top-level* op; an op's\n // implementation may invoke other ops (or itself) internally, and those\n // nested calls share the same `getCurrentStmt()` anchor. They are\n // implementation details, not statements, so they must NOT register a second\n // node under the same StmtId — that would trip N3 (E_TOPO_DUPLICATE_STMT)\n // on identical content. Only the outermost `wrapped` for the current\n // statement registers; the flag below stays set for the *entire* statement\n // execution (including the awaited impl), so nested calls see it and skip.\n const anchor = getCurrentStmt()\n const st = getRuntimeState()\n const isOuter = anchor != null && st.registeredStmtId !== anchor.id\n if (isOuter) st.registeredStmtId = asStmtId(anchor.id)\n try {\n if (isOuter && anchor) {\n runtimeLineage.register(\n {\n stmt: asStmtId(anchor.id),\n op: opLabel(meta),\n inputs,\n outputs: anchor.outputs as [PartName, ...PartName[]],\n provenance: meta.naming,\n },\n {\n nameOf,\n currentStmt: () => {\n const a = getCurrentStmt()\n return a ? { id: a.id } : undefined\n },\n },\n )\n }\n // D5 capability routing: feed the first missing capability to dispatchPath\n // (auto degrades to mesh, brep mode errors). Matched as a concrete name\n // against the engine's declaration set (family booleans + its `evolution`\n // list of *WithHistory kernel function names) — see firstMissingCapability.\n const missing = firstMissingCapability(meta.capabilities)\n const path = dispatchPath(inputs, meta, missing)\n if (path === 'brep') {\n const r = await runImpl(meta, decl.brep as unknown as ((...a: unknown[]) => unknown) | undefined, callArgs)\n const out = meta.outputs ? wrapByKeys(r, meta.outputs, wrapBrepOne) : wrapBrepOne(r)\n // 1.10 前置①:执行期把 hash 演化挂到血缘节点(kernel 类回走推进的数据源)。\n // 演化在几何算完那一刻可得(fromBrep → slot.faceEvolution),事后补挂不参与\n // N3 的内容比较(lineage.ts 设计如此)。无演化(identity/construct 等无历史\n // 输出)时跳过——identity 类推进不依赖演化,construct 词汇在节点 provenance 里。\n const outShape = (typeof out === 'object' && out !== null ? Object.values(out)[0] : out) as Shape | undefined\n const evolution = outShape ? getSlot(outShape)?.faceEvolution : undefined\n if (outShape && evolution) {\n runtimeLineage.attachEvolution(asStmtId(anchor!.id), evolution)\n }\n // 1.10 前置③:part 键的 roleTable 旁挂在这里记录(不是 fromBrep)——\n // impl 返回后 anchor.outputs 名字已定,而 fromBrep 时刻 shape 还未被\n // executor 命名(nameOf 为 undefined)。op 实现读输入表(inputRoleTable)\n // 与解析读表(tableOfPart)都走这份 part 键权威表。\n if (outShape && anchor && anchor.outputs.length > 0) {\n const stmtId = asStmtId(anchor.id)\n const table = runtimeLineage.outputTableOf(stmtId)\n const solid = runtimeLineage.outputHandleOf(stmtId)\n if (table) runtimeLineage.recordOutput(stmtId, table, solid, anchor.outputs[0] as PartName)\n }\n return out\n }\n const m = await runImpl(meta, decl.mesh as unknown as ((...a: unknown[]) => unknown) | undefined, callArgs)\n return meta.outputs ? wrapByKeys(m, meta.outputs, wrapMeshOne) : wrapMeshOne(m)\n } finally {\n // 同语句去重标记不在 op 粒度清理——语句边界由 runtime-state.setCurrentStmt\n // 在锚点变化时重置;TS 库函数体内连续 op 调用共享锚点,嵌套调用正确跳过。\n }\n }\n\n Object.defineProperty(wrapped, DUAL_OP_META, { value: meta, enumerable: false })\n return wrapped as ((...args: A) => Promise<Shape | Record<string, Shape>>) & MetaCarrier\n}\n\n/**\n * Assembly-time validation (③, strict mode, D-4): a library that exports any\n * dual-op function must carry a matching `contractVersion`, and every exported\n * dual-op must be structurally valid (mesh a function, brep a function or\n * undefined, capabilities/outputs well-formed). Called by `registerLib`.\n *\n * Functions without dual-op metadata are left untouched (declarative\n * enforcement boundary — K5 forbids name-based classification).\n *\n * @param lib - the library namespace object being registered.\n */\n/**\n * Detect whether a library namespace exports any dual-op function (carries\n * `DUAL_OP_META`). Used by `registerLib`'s inferred `autoLift` default: a\n * library that already declares dual-ops does not need bare-function lifting.\n *\n * @param ns - the library namespace object.\n * @returns `true` if at least one exported value is a dual-op function.\n */\nexport function hasDualOp(ns: Record<string, unknown>): boolean {\n const values = Object.values(ns)\n return values.some((v) => typeof v === 'function' && (v as MetaCarrier)[DUAL_OP_META])\n}\n\n/**\n * Assert that a library conforms to the dual-op contract: if it exports any\n * dual-op function, it must also export `contractVersion` matching the engine's.\n *\n * @param lib - the library namespace object being registered.\n * @throws {Error} when dual-op functions are present without a matching contract version.\n */\nexport function assertLibConforms(lib: Record<string, unknown>): void {\n if (hasDualOp(lib) && lib.contractVersion !== CONTRACT_VERSION) {\n throw new Error(\n `[faijs] library with dual-op functions must export contractVersion = ${CONTRACT_VERSION} (got ${String(lib.contractVersion)})`,\n )\n }\n\n for (const [name, value] of Object.entries(lib)) {\n if (typeof value !== 'function') continue\n const meta = (value as MetaCarrier)[DUAL_OP_META]\n if (!meta || meta.kind !== 'dual-op') continue\n if (typeof meta.mesh !== 'function' && typeof meta.brep !== 'function') {\n throw new Error(`[faijs] lib function '${name}' declares dual-op without any implementation`)\n }\n if (meta.mesh !== undefined && typeof meta.mesh !== 'function') {\n throw new Error(`[faijs] lib function '${name}' declares dual-op with a non-function mesh implementation`)\n }\n if (meta.brep !== undefined && typeof meta.brep !== 'function') {\n throw new Error(`[faijs] lib function '${name}' declares dual-op with a non-function brep implementation`)\n }\n if (meta.capabilities !== undefined && !Array.isArray(meta.capabilities)) {\n throw new Error(`[faijs] lib function '${name}' declares invalid capabilities (expected string[])`)\n }\n if (\n meta.outputs !== undefined\n && (!Array.isArray(meta.outputs) || meta.outputs.some((k) => typeof k !== 'string'))\n ) {\n throw new Error(`[faijs] lib function '${name}' declares invalid outputs (expected string[])`)\n }\n if (meta.schema !== undefined && !isValidSchema(meta.schema)) {\n throw new Error(`[faijs] lib function '${name}' declares invalid schema (expected Record<string, string>)`)\n }\n if (meta.name !== undefined && typeof meta.name !== 'string') {\n throw new Error(`[faijs] lib function '${name}' declares invalid name (expected string)`)\n }\n if (meta.slotMap !== undefined && !isValidSlotMap(meta.slotMap)) {\n throw new Error(\n `[faijs] lib function '${name}' declares invalid slotMap (expected { keys: string[]; vec3Keys?: string[]; shapeArity?: number })`,\n )\n }\n }\n}\n\n/** True when the D11 slot-map declaration has a non-empty string `keys` list. */\nfunction isValidSlotMap(form: unknown): form is SlotMap {\n if (form === null || typeof form !== 'object') return false\n const keys = (form as { keys?: unknown }).keys\n if (!Array.isArray(keys) || keys.some((k) => typeof k !== 'string')) return false\n const vec3 = (form as { vec3Keys?: unknown }).vec3Keys\n if (vec3 !== undefined && (!Array.isArray(vec3) || vec3.some((k) => typeof k !== 'string'))) return false\n const arity = (form as { shapeArity?: unknown }).shapeArity\n if (arity !== undefined && (typeof arity !== 'number' || !Number.isInteger(arity) || arity < 0)) return false\n return true\n}\n\n/** True when every schema value is a non-empty string. */\nfunction isValidSchema(schema: unknown): schema is Record<string, string> {\n if (schema === null || typeof schema !== 'object' || Array.isArray(schema)) return false\n return Object.values(schema).every((v) => typeof v === 'string' && v.length > 0)\n}\n"]}
|
|
@@ -37,6 +37,7 @@ export declare const ATTACH_MAP_MODE: {
|
|
|
37
37
|
readonly FLAT_FACE: 5;
|
|
38
38
|
readonly TANGENT_PLANE: 6;
|
|
39
39
|
};
|
|
40
|
+
/** 附件链解析结果:合成后的 placement + 原始 MapMode + support 引用。 */
|
|
40
41
|
export interface AttachmentResolution {
|
|
41
42
|
/** the composed placement (support ∘ mode-adjustment ∘ AttachmentOffset) */
|
|
42
43
|
placement: Placement;
|
|
@@ -60,6 +61,12 @@ export interface AttachmentResolution {
|
|
|
60
61
|
* @returns the resolved attachment, or undefined when not attached / not resolvable.
|
|
61
62
|
*/
|
|
62
63
|
export declare function resolveAttachment(obj: FcstdObject, placements: Map<string, Placement>): AttachmentResolution | undefined;
|
|
63
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Convenience: an object's effective placement — attachment-resolved when attached, stored otherwise.
|
|
66
|
+
*
|
|
67
|
+
* @param obj - the FCStd object to resolve.
|
|
68
|
+
* @param placements - per-object placements of the document (resolved earlier).
|
|
69
|
+
* @returns the object's effective placement.
|
|
70
|
+
*/
|
|
64
71
|
export declare function effectivePlacement(obj: FcstdObject, placements: Map<string, Placement>): Placement;
|
|
65
72
|
//# sourceMappingURL=attachment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/fcstd/attachment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAChE,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE9E,wEAAwE;AACxE,eAAO,MAAM,eAAe;;;;;;;;CAQlB,CAAC;AA+CX,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,SAAS,EAAE,SAAS,CAAC;IACrB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,GACjC,oBAAoB,GAAG,SAAS,CAelC;AAED
|
|
1
|
+
{"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/fcstd/attachment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAChE,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE9E,wEAAwE;AACxE,eAAO,MAAM,eAAe;;;;;;;;CAQlB,CAAC;AA+CX,wDAAwD;AACxD,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,SAAS,EAAE,SAAS,CAAC;IACrB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,GACjC,oBAAoB,GAAG,SAAS,CAelC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,SAAS,CAElG"}
|
package/dist/fcstd/attachment.js
CHANGED
|
@@ -80,7 +80,13 @@ export function resolveAttachment(obj, placements) {
|
|
|
80
80
|
const placement = compose(supportPlacement, offset);
|
|
81
81
|
return { placement, mapMode: mode, support };
|
|
82
82
|
}
|
|
83
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Convenience: an object's effective placement — attachment-resolved when attached, stored otherwise.
|
|
85
|
+
*
|
|
86
|
+
* @param obj - the FCStd object to resolve.
|
|
87
|
+
* @param placements - per-object placements of the document (resolved earlier).
|
|
88
|
+
* @returns the object's effective placement.
|
|
89
|
+
*/
|
|
84
90
|
export function effectivePlacement(obj, placements) {
|
|
85
91
|
return resolveAttachment(obj, placements)?.placement ?? placementOf(obj);
|
|
86
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../src/fcstd/attachment.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../src/fcstd/attachment.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * H3 — attachment resolution: Support → MapMode → AttachmentOffset.\n *\n * FreeCAD saves an attached object's Placement as the ALREADY-COMPOSED result\n * of the attachment chain (recomputed on load/save). The chain for the modes\n * that matter to the corpus (probe: fcstd-port/tools/probe-attachment-usage.mjs):\n * MapMode 5 = mmFlatFace (68 objects — dominant)\n * MapMode 6 = mmTangentPlane (3)\n * MapMode 1 = mmTranslate (1)\n * MapMode 0 = mmDeactivated (no attachment; Placement stands alone)\n *\n * Full Attacher.cpp semantics (normal-projection onto a face, Frenet frames on\n * curves, three-point modes) are far beyond what the corpus exercises: all\n * corpus Support targets are datum planes / origin planes, where the resolved\n * frame IS the support's placement, then rotated per-mode and composed with\n * AttachmentOffset. This module implements that plane-support subset and\n * reports what it resolved so the caller can bake with an explicit reason when\n * the support is not a plane.\n *\n * GOTCHAs (probed on real files):\n * - MapMode is `App::PropertyEnumeration` stored as `<Integer value=\"N\"/>`,\n * NEVER a `<String>` — matching the string name finds nothing.\n * - The support link property is `Support` (old) or `AttachmentSupport`\n * (newer FreeCAD); both must be read.\n * - `App::Plane` objects carry the origin-plane identity placement; their\n * orientation comes from their own Placement property like any object.\n */\nimport type { FcstdObject, FcstdProperty } from './document.js';\nimport { placementOf, placementOfProp, type Placement } from './placement.js';\n\n/** eMapMode values from FreeCAD Attacher.h (subset the corpus uses). */\nexport const ATTACH_MAP_MODE = {\n DEACTIVATED: 0,\n TRANSLATE: 1,\n OBJECT_XY: 2,\n OBJECT_XZ: 3,\n OBJECT_YZ: 4,\n FLAT_FACE: 5,\n TANGENT_PLANE: 6,\n} as const;\n\n/** Property names that may carry the support link (old / new FreeCAD). */\nconst SUPPORT_PROPS = ['Support', 'AttachmentSupport'] as const;\n\nfunction firstLinkSub(obj: FcstdObject): { target: string; sub: string } | undefined {\n for (const name of SUPPORT_PROPS) {\n const prop: FcstdProperty | undefined = obj.properties.get(name);\n const link = prop?.children[0]?.children[0];\n const target = link?.attributes['obj'];\n if (target) return { target, sub: link?.attributes['sub'] ?? '' };\n }\n return undefined;\n}\n\nfunction mapMode(obj: FcstdObject): number | undefined {\n const raw = obj.properties.get('MapMode')?.children[0]?.attributes['value'];\n return raw === undefined ? undefined : Number(raw);\n}\n\n/**\n * Compose two placements: `outer ∘ inner` (apply inner first, then outer).\n * Quaternion product q = qo * qi, position = outer(inner(0)).\n */\nfunction compose(outer: Placement, inner: Placement): Placement {\n const [ox, oy, oz, ow] = outer.q;\n const [ix, iy, iz, iw] = inner.q;\n // Hamilton product (x,y,z,w)\n const q: [number, number, number, number] = [\n ow * ix + ox * iw + oy * iz - oz * iy,\n ow * iy - ox * iz + oy * iw + oz * ix,\n ow * iz + ox * iy - oy * ix + oz * iw,\n ow * iw - ox * ix - oy * iy - oz * iz,\n ];\n const [px, py, pz] = inner.p;\n const [x, y, z, w] = q;\n const n = Math.hypot(x, y, z, w);\n const nx = x / n, ny = y / n, nz = z / n, nw = w / n;\n const s = 2;\n const p: [number, number, number] = [\n (1 - s * (ny * ny + nz * nz)) * px + s * (nx * ny - nw * nz) * py + s * (nx * nz + nw * ny) * pz + outer.p[0],\n s * (nx * ny + nw * nz) * px + (1 - s * (nx * nx + nz * nz)) * py + s * (ny * nz - nw * nx) * pz + outer.p[1],\n s * (nx * nz - nw * ny) * px + s * (ny * nz + nw * nx) * py + (1 - s * (nx * nx + ny * ny)) * pz + outer.p[2],\n ];\n return { p, q };\n}\n\n/** 附件链解析结果:合成后的 placement + 原始 MapMode + support 引用。 */\nexport interface AttachmentResolution {\n /** the composed placement (support ∘ mode-adjustment ∘ AttachmentOffset) */\n placement: Placement;\n /** eMapMode integer as stored */\n mapMode: number;\n /** support target object name and sub-element */\n support: { target: string; sub: string };\n}\n\n/**\n * Resolve the attachment chain of an object carrying AttachExtension\n * properties. Only plane-type supports are composed (corpus reality: all\n * active attachments target datum/origin planes); anything else — or a\n * missing support — returns undefined so the caller keeps the stored\n * Placement or bakes with an explicit reason.\n *\n * @param obj - the FCStd object (sketch or datum) with MapMode/Support/AttachmentOffset.\n * @param placements - per-object placements of the document (resolved earlier).\n * @returns the resolved attachment, or undefined when not attached / not resolvable.\n */\nexport function resolveAttachment(\n obj: FcstdObject,\n placements: Map<string, Placement>,\n): AttachmentResolution | undefined {\n const mode = mapMode(obj);\n if (mode === undefined || mode === ATTACH_MAP_MODE.DEACTIVATED) return undefined;\n const support = firstLinkSub(obj);\n if (!support) return undefined;\n const supportPlacement = placements.get(support.target);\n if (!supportPlacement) return undefined;\n\n // Plane-support modes: the support's frame IS the base frame. (mmFlatFace\n // on a plane, mmObjectXY/XZ/YZ and mmTranslate all coincide here; on a real\n // face or curve they diverge — those return undefined via the support-type\n // check below once face frames are needed.)\n const offset = placementOfProp(obj.properties.get('AttachmentOffset'));\n const placement = compose(supportPlacement, offset);\n return { placement, mapMode: mode, support };\n}\n\n/**\n * Convenience: an object's effective placement — attachment-resolved when attached, stored otherwise.\n *\n * @param obj - the FCStd object to resolve.\n * @param placements - per-object placements of the document (resolved earlier).\n * @returns the object's effective placement.\n */\nexport function effectivePlacement(obj: FcstdObject, placements: Map<string, Placement>): Placement {\n return resolveAttachment(obj, placements)?.placement ?? placementOf(obj);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-fai-zip.d.ts","sourceRoot":"","sources":["../../src/fcstd/build-fai-zip.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAW,OAAO,EAAE,MAAM,QAAQ,CAAC;AAG1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAExB,mHAAmH;AACnH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,GAAG,EAAE,UAAU,CAAC;IAChB,uCAAuC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAQD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,YAAY,EACpB,cAAc,EAAE,MAAM,GACrB;IAAE,MAAM,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"build-fai-zip.d.ts","sourceRoot":"","sources":["../../src/fcstd/build-fai-zip.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAW,OAAO,EAAE,MAAM,QAAQ,CAAC;AAG1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAC;AAExB,mHAAmH;AACnH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,GAAG,EAAE,UAAU,CAAC;IAChB,uCAAuC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAQD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,YAAY,EACpB,cAAc,EAAE,MAAM,GACrB;IAAE,MAAM,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAkE3C;AAkBD,qEAAqE;AACrE,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -43,16 +43,21 @@ export function buildFaiZip(source, sourceFileName) {
|
|
|
43
43
|
shadowHashes[path] = { source: h, shadow: h }; // same bytes → same hash
|
|
44
44
|
}
|
|
45
45
|
// M2.3 — baked assets: copy .brp members as-is into assets/
|
|
46
|
+
// GOTCHA (E4 / asset-resolver, 2026-09-21): the collector used to read ONLY
|
|
47
|
+
// the `Shape` property. SubShape carriers (feature result caches in
|
|
48
|
+
// Body-less CAM files, e.g. motor_mount_inch PartShape5/PartShape8) point
|
|
49
|
+
// their `cad.import_brep` at a member that was never copied into assets/
|
|
50
|
+
// — the product converted clean and died at run with
|
|
51
|
+
// "not found in manifest". SubShape joins the same collection.
|
|
46
52
|
const brpOwners = new Map();
|
|
47
53
|
for (const obj of doc.objects) {
|
|
48
|
-
const shapeProp = obj.properties.get('Shape');
|
|
49
|
-
if (!shapeProp)
|
|
50
|
-
continue;
|
|
51
|
-
// brp file names appear as <File ...> inside the Part::PropertyPartShape
|
|
52
|
-
const fileEl = shapeProp.children[0]?.attributes['file'];
|
|
53
|
-
void fileEl; // file attribute lives on the wrapping element in some schemas
|
|
54
54
|
const files = [];
|
|
55
|
-
|
|
55
|
+
for (const propName of ['Shape', 'SubShape']) {
|
|
56
|
+
const shapeProp = obj.properties.get(propName);
|
|
57
|
+
if (!shapeProp)
|
|
58
|
+
continue;
|
|
59
|
+
collectBrpRefs(shapeProp.valueXml ?? '', files);
|
|
60
|
+
}
|
|
56
61
|
if (files.length)
|
|
57
62
|
brpOwners.set(obj.name, files);
|
|
58
63
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-fai-zip.js","sourceRoot":"","sources":["../../src/fcstd/build-fai-zip.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAsB,MAAM,eAAe,CAAC;AACrE,OAAO,EACL,aAAa,EACb,kBAAkB,GAGnB,MAAM,gBAAgB,CAAC;AAaxB,SAAS,MAAM,CAAC,KAAiB;IAC/B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,qBAAqB,GAAG,UAAU,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CACzB,MAAoB,EACpB,cAAsB;IAEtB,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,0CAA0C,EAAE,CAAC;IACpF,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC1D,MAAM,GAAG,GAAkB,MAAM,CAAC,KAAK,CAAC;IAExC,MAAM,GAAG,GAAwC,EAAE,CAAC;IACpD,MAAM,YAAY,GAAuD,EAAE,CAAC;IAE5E,4EAA4E;IAC5E,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,qBAAqB,GAAG,IAAI,CAAC;QAChD,GAAG,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;QACxB,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,yBAAyB;IAC1E,CAAC;IAED,4DAA4D;IAC5D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,
|
|
1
|
+
{"version":3,"file":"build-fai-zip.js","sourceRoot":"","sources":["../../src/fcstd/build-fai-zip.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * M2.2/M2.3/M2.4 — .fai.zip builder.\n *\n * freecad/ shadow: byte-exact copy of every source ZIP member except\n * Document.xml / GuiDocument.xml (kept too — nothing is dropped), verified by\n * sha256 equality (V1). Baked geometry comes from the ZIP's .brp members\n * directly (M2.3 — no FreeCAD runtime involved). Unit normalization (D7/M2.4):\n * FCStd internal storage is mm, matching faijs; the units field records this.\n */\nimport { zipSync, strToU8 } from 'fflate';\nimport { createHash } from 'node:crypto';\nimport { isOk } from '../api/result.js';\nimport type { FcstdArchive } from './unpack.js';\nimport { memberText } from './unpack.js';\nimport { parseDocumentXml, type FcstdDocument } from './document.js';\nimport {\n buildManifest,\n initialDisposition,\n type FaiMapping,\n type ObjectMappingEntry,\n} from './container.js';\n\n/** Build output: the .fai.zip bytes, the serialized manifest, the per-object mapping and the shadow hash table. */\nexport interface FaiZipResult {\n /** the produced .fai.zip archive bytes */\n zip: Uint8Array;\n /** serialized manifest.json content */\n manifest: unknown;\n mapping: FaiMapping;\n /** sha256 verification table for the freecad/ shadow (V1) */\n shadowHashes: Record<string, { source: string; shadow: string }>;\n}\n\nfunction sha256(bytes: Uint8Array): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\nconst FREECAD_SHADOW_PREFIX = 'freecad/';\n\n/**\n * Build the .fai.zip container: byte-exact freecad/ shadow of every source\n * member, baked .brp-derived assets, mapping ledger and manifest.\n * Returns `{ error }` when Document.xml is missing or unparseable.\n * @param source unpacked FCStd archive (ZIP members + metadata)\n * @param sourceFileName original FCStd file name recorded in the manifest\n * @returns the built archive or an error message\n */\nexport function buildFaiZip(\n source: FcstdArchive,\n sourceFileName: string,\n): { result?: FaiZipResult; error?: string } {\n const xml = memberText(source, 'Document.xml');\n if (xml === undefined) return { error: 'Document.xml missing from source archive' };\n const parsed = parseDocumentXml(xml);\n if (!isOk(parsed)) return { error: parsed.error.message };\n const doc: FcstdDocument = parsed.value;\n\n const out: Record<string, Uint8Array | string> = {};\n const shadowHashes: Record<string, { source: string; shadow: string }> = {};\n\n // M2.2 — byte-exact freecad/ shadow of ALL members (including Document.xml)\n for (const [path, bytes] of source.members) {\n const shadowPath = FREECAD_SHADOW_PREFIX + path;\n out[shadowPath] = bytes;\n const h = sha256(bytes);\n shadowHashes[path] = { source: h, shadow: h }; // same bytes → same hash\n }\n\n // M2.3 — baked assets: copy .brp members as-is into assets/\n // GOTCHA (E4 / asset-resolver, 2026-09-21): the collector used to read ONLY\n // the `Shape` property. SubShape carriers (feature result caches in\n // Body-less CAM files, e.g. motor_mount_inch PartShape5/PartShape8) point\n // their `cad.import_brep` at a member that was never copied into assets/\n // — the product converted clean and died at run with\n // \"not found in manifest\". SubShape joins the same collection.\n const brpOwners = new Map<string, string[]>();\n for (const obj of doc.objects) {\n const files: string[] = [];\n for (const propName of ['Shape', 'SubShape']) {\n const shapeProp = obj.properties.get(propName);\n if (!shapeProp) continue;\n collectBrpRefs(shapeProp.valueXml ?? '', files);\n }\n if (files.length) brpOwners.set(obj.name, files);\n }\n\n const mapping: FaiMapping = { objects: [] };\n const usedAssets = new Set<string>();\n for (const obj of doc.objects) {\n const entry: ObjectMappingEntry = {\n name: obj.name,\n type: obj.type,\n ...initialDisposition(obj),\n artifacts: [],\n };\n // attach baked .brp-derived assets where the object owns shape members\n const brps = brpOwners.get(obj.name) ?? [];\n for (const brp of brps) {\n const bytes = source.members.get(brp);\n if (!bytes) continue;\n const assetPath = `assets/${brp}`;\n out[assetPath] = bytes;\n entry.artifacts.push(assetPath);\n usedAssets.add(brp);\n }\n mapping.objects.push(entry);\n }\n\n // M2.4 — units: FCStd stores mm internally; faijs contract is mm. No\n // scaling is applied; manifest.units records the normalized unit (D7).\n // fflate requires Uint8Array values — strings must go through strToU8.\n out['manifest.json'] = strToU8(JSON.stringify(buildManifest(doc, sourceFileName, readProgramVersion(doc)), null, 2));\n out['mapping.json'] = strToU8(JSON.stringify(mapping, null, 2));\n\n const zip = zipSync(out as Record<string, Uint8Array>, { level: 6 });\n return { result: { zip, manifest: out['manifest.json'], mapping, shadowHashes } };\n}\n\nfunction readProgramVersion(doc: FcstdDocument): string {\n // ProgramVersion is an attribute of <Document> captured in meta? xmldom:\n // meta holds child property elements only, so fall back to a sane default.\n return doc.meta.get('ProgramVersion')?.valueText ?? 'unknown';\n}\n\n/** Extract .brp file references from a serialized property value. */\nfunction collectBrpRefs(xml: string, out: string[]): void {\n const re = /file=\"([^\"]+\\.brp)\"/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(xml)) !== null) {\n const name = m[1]!.replace(/^.*[/\\\\]/, '');\n if (!out.includes(name)) out.push(name);\n }\n}\n\n/** Re-export strToU8 for callers that need to embed text members. */\nexport { strToU8 };\n"]}
|
package/dist/fcstd/codegen.d.ts
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* heuristics — explicit downgrade per plan §12).
|
|
7
7
|
* M5.2 lowering: params → JS constants; calls → `const partN = await cad.x(...)`;
|
|
8
8
|
* statement ids sN. Sketch contours enter as blueprint literals.
|
|
9
|
+
*
|
|
10
|
+
* 本文件为 Placement 发射平台 `cad.place`(旋转四元数 + 平移,单点)、为产物聚合发射
|
|
11
|
+
* 平台 `cad.compound`(几何复合体,内核 `makeCompound`,持 OCCT 句柄)。这两个是 faijs
|
|
12
|
+
* 平台几何 op(H11,方案 §4),不再借用 `../3d_editor` 的 `cad.group` /
|
|
13
|
+
* `cad.translate` / `cad.rotate_euler`(编辑器交互 op,JSDoc 已 @deprecated)。
|
|
9
14
|
*/
|
|
10
15
|
import type { FcstdDocument } from './document.js';
|
|
11
16
|
import type { CadCall } from './feature-translate.js';
|
|
@@ -56,6 +61,8 @@ export interface GenResult {
|
|
|
56
61
|
* @param sketchContours solved contours per L0 sketch, keyed by object name
|
|
57
62
|
* @param baseName source base name used in generated file headers/labels
|
|
58
63
|
* @param placements per-object Placement used to re-orient placed geometry; missing → identity
|
|
64
|
+
* @param shapeCarriers objects whose Shape is a ZIP .brp member (pure-Shape carriers → shape-asset)
|
|
65
|
+
* @param brokenShapeAssets objects whose Shape `file` attribute points at a missing/empty member (explicit gap)
|
|
59
66
|
* @returns the lowered call plan, per-object dispositions and generated code
|
|
60
67
|
*/
|
|
61
68
|
export declare function generateModel(doc: FcstdDocument, sketchVerdict: Map<string, {
|
|
@@ -66,5 +73,7 @@ export declare function generateModel(doc: FcstdDocument, sketchVerdict: Map<str
|
|
|
66
73
|
/** M8.3: per-object Placement (sketches + features); missing → identity */
|
|
67
74
|
placements?: Map<string, Placement>,
|
|
68
75
|
/** H7: objects whose Shape is a ZIP .brp member (pure-Shape carriers → shape-asset). */
|
|
69
|
-
shapeCarriers?: ReadonlySet<string
|
|
76
|
+
shapeCarriers?: ReadonlySet<string>,
|
|
77
|
+
/** E4: objects whose Shape `file` attribute points at a missing/empty member (explicit gap). */
|
|
78
|
+
brokenShapeAssets?: ReadonlySet<string>): GenResult;
|
|
70
79
|
//# sourceMappingURL=codegen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/fcstd/codegen.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/fcstd/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,wBAAwB,CAAC;AAExE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,KAAK,SAAS,EAA6C,MAAM,gBAAgB,CAAC;AAG3F,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,WAAW,EAAE,YAAY,GAAG,OAAO,GAAG,gBAAgB,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E;AAED,qFAAqF;AACrF,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb;wFACoF;IACpF,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9F,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EACtC,QAAQ,EAAE,MAAM;AAChB,2EAA2E;AAC3E,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;AACnC,wFAAwF;AACxF,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC;AACnC,gGAAgG;AAChG,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACtC,SAAS,CAwZX"}
|