@faicad/faijs 0.19.0 → 0.29.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 +202 -28
- package/dist/api/api-namespace.d.ts +5 -5
- package/dist/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +4 -4
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/assert.d.ts +2 -2
- package/dist/api/assert.js +8 -8
- package/dist/api/assert.js.map +1 -1
- package/dist/api/asset.d.ts +1 -1
- package/dist/api/asset.js +2 -2
- package/dist/api/asset.js.map +1 -1
- package/dist/api/boolean.d.ts +1 -1
- package/dist/api/boolean.d.ts.map +1 -1
- package/dist/api/boolean.js +128 -16
- package/dist/api/boolean.js.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.js +3 -1
- package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
- package/dist/api/cadquery-selectors/borrow-bridge.d.ts +14 -0
- package/dist/api/cadquery-selectors/borrow-bridge.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/borrow-bridge.js +52 -0
- package/dist/api/cadquery-selectors/borrow-bridge.js.map +1 -0
- package/dist/api/cadquery-selectors/edge.d.ts +40 -0
- package/dist/api/cadquery-selectors/edge.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/edge.js +70 -0
- package/dist/api/cadquery-selectors/edge.js.map +1 -0
- package/dist/api/cadquery-selectors/entity.d.ts +121 -0
- package/dist/api/cadquery-selectors/entity.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/entity.js +167 -0
- package/dist/api/cadquery-selectors/entity.js.map +1 -0
- package/dist/api/cadquery-selectors/face.d.ts +33 -0
- package/dist/api/cadquery-selectors/face.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/face.js +353 -0
- package/dist/api/cadquery-selectors/face.js.map +1 -0
- package/dist/api/cadquery-selectors/grammar.d.ts +50 -0
- package/dist/api/cadquery-selectors/grammar.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/grammar.js +345 -0
- package/dist/api/cadquery-selectors/grammar.js.map +1 -0
- package/dist/api/cadquery-selectors/index.d.ts +18 -0
- package/dist/api/cadquery-selectors/index.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/index.js +17 -0
- package/dist/api/cadquery-selectors/index.js.map +1 -0
- package/dist/api/cadquery-selectors/predicates.d.ts +76 -0
- package/dist/api/cadquery-selectors/predicates.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/predicates.js +85 -0
- package/dist/api/cadquery-selectors/predicates.js.map +1 -0
- package/dist/api/cadquery-selectors/resolve.d.ts +41 -0
- package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/resolve.js +243 -0
- package/dist/api/cadquery-selectors/resolve.js.map +1 -0
- package/dist/api/cadquery-selectors/types.d.ts +96 -0
- package/dist/api/cadquery-selectors/types.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/types.js +11 -0
- package/dist/api/cadquery-selectors/types.js.map +1 -0
- package/dist/api/chamfer.d.ts +13 -5
- package/dist/api/chamfer.d.ts.map +1 -1
- package/dist/api/chamfer.js +63 -7
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/compound-geom.d.ts +1 -1
- package/dist/api/compound-geom.js +1 -1
- package/dist/api/compound-geom.js.map +1 -1
- package/dist/api/draft.d.ts +1 -1
- package/dist/api/draft.js +1 -1
- package/dist/api/draft.js.map +1 -1
- package/dist/api/edge-ref.d.ts +1 -1
- package/dist/api/edge-ref.d.ts.map +1 -1
- package/dist/api/edge-ref.js +11 -3
- package/dist/api/edge-ref.js.map +1 -1
- package/dist/api/engrave.d.ts +1 -1
- package/dist/api/engrave.js +7 -7
- package/dist/api/engrave.js.map +1 -1
- package/dist/api/extrude.d.ts +6 -1
- package/dist/api/extrude.d.ts.map +1 -1
- package/dist/api/extrude.js +59 -5
- package/dist/api/extrude.js.map +1 -1
- package/dist/api/face-ref.d.ts +1 -1
- package/dist/api/face-ref.js +1 -1
- package/dist/api/face-ref.js.map +1 -1
- package/dist/api/feature-repair.d.ts +1 -1
- package/dist/api/feature-repair.js +1 -1
- package/dist/api/feature-repair.js.map +1 -1
- package/dist/api/fillet-variable.d.ts +1 -1
- package/dist/api/fillet-variable.js +1 -1
- package/dist/api/fillet-variable.js.map +1 -1
- package/dist/api/fillet.d.ts +28 -8
- package/dist/api/fillet.d.ts.map +1 -1
- package/dist/api/fillet.js +64 -9
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts +4 -0
- package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/geom.d.ts +1 -1
- package/dist/api/geom.js +1 -1
- package/dist/api/geom.js.map +1 -1
- package/dist/api/helix.d.ts +1 -1
- package/dist/api/helix.js +1 -1
- package/dist/api/helix.js.map +1 -1
- package/dist/api/import-brep.d.ts +20 -2
- package/dist/api/import-brep.d.ts.map +1 -1
- package/dist/api/import-brep.js +28 -3
- package/dist/api/import-brep.js.map +1 -1
- package/dist/api/import-step.d.ts +17 -2
- package/dist/api/import-step.d.ts.map +1 -1
- package/dist/api/import-step.js +23 -3
- package/dist/api/import-step.js.map +1 -1
- package/dist/api/index.d.ts +2 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +5 -2
- package/dist/api/index.js.map +1 -1
- package/dist/api/internal/compat-op.js +1 -1
- package/dist/api/internal/compat-op.js.map +1 -1
- package/dist/api/internal/mesh-solid-op.d.ts +236 -0
- package/dist/api/internal/mesh-solid-op.d.ts.map +1 -0
- package/dist/api/internal/mesh-solid-op.js +352 -0
- package/dist/api/internal/mesh-solid-op.js.map +1 -0
- package/dist/api/internal/svg-asset-resolver.d.ts +1 -1
- package/dist/api/internal/svg-asset-resolver.js +1 -1
- package/dist/api/internal/svg-asset-resolver.js.map +1 -1
- package/dist/api/knurl.d.ts +1 -1
- package/dist/api/knurl.d.ts.map +1 -1
- package/dist/api/knurl.js +3 -2
- package/dist/api/knurl.js.map +1 -1
- package/dist/api/loft.d.ts +1 -1
- package/dist/api/loft.js +1 -1
- package/dist/api/loft.js.map +1 -1
- package/dist/api/measurement/index.d.ts +9 -5
- package/dist/api/measurement/index.d.ts.map +1 -1
- package/dist/api/measurement/index.js +47 -20
- package/dist/api/measurement/index.js.map +1 -1
- package/dist/api/pattern.d.ts +5 -3
- package/dist/api/pattern.d.ts.map +1 -1
- package/dist/api/pattern.js +32 -4
- package/dist/api/pattern.js.map +1 -1
- package/dist/api/place.d.ts +1 -1
- package/dist/api/place.js +1 -1
- package/dist/api/place.js.map +1 -1
- package/dist/api/primitives.d.ts +5 -4
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +11 -5
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/profile.d.ts +64 -8
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +61 -10
- package/dist/api/profile.js.map +1 -1
- package/dist/api/punch-hole.d.ts +3 -0
- package/dist/api/punch-hole.d.ts.map +1 -1
- package/dist/api/punch-hole.js.map +1 -1
- package/dist/api/reconcile.d.ts +1 -1
- package/dist/api/reconcile.js +1 -1
- package/dist/api/reconcile.js.map +1 -1
- package/dist/api/replicate.d.ts.map +1 -1
- package/dist/api/replicate.js +122 -1
- package/dist/api/replicate.js.map +1 -1
- package/dist/api/screw.d.ts +1 -1
- package/dist/api/screw.js +3 -3
- package/dist/api/screw.js.map +1 -1
- package/dist/api/sdf.d.ts +1 -1
- package/dist/api/sdf.js +2 -2
- package/dist/api/sdf.js.map +1 -1
- package/dist/api/section-by-plane.d.ts +1 -1
- package/dist/api/section-by-plane.d.ts.map +1 -1
- package/dist/api/section-by-plane.js +2 -1
- package/dist/api/section-by-plane.js.map +1 -1
- package/dist/api/shell.d.ts +11 -4
- package/dist/api/shell.d.ts.map +1 -1
- package/dist/api/shell.js +53 -7
- package/dist/api/shell.js.map +1 -1
- package/dist/api/sketch-on-face.d.ts +41 -0
- package/dist/api/sketch-on-face.d.ts.map +1 -1
- package/dist/api/sketch-on-face.js +100 -1
- package/dist/api/sketch-on-face.js.map +1 -1
- package/dist/api/sketch-on-plane.d.ts +17 -9
- package/dist/api/sketch-on-plane.d.ts.map +1 -1
- package/dist/api/sketch-on-plane.js +12 -10
- package/dist/api/sketch-on-plane.js.map +1 -1
- package/dist/api/split-by-plane.d.ts +1 -1
- package/dist/api/split-by-plane.d.ts.map +1 -1
- package/dist/api/split-by-plane.js +2 -1
- package/dist/api/split-by-plane.js.map +1 -1
- package/dist/api/split.d.ts +1 -1
- package/dist/api/split.js +2 -2
- package/dist/api/split.js.map +1 -1
- package/dist/api/surface/arg-spec.d.ts +8 -0
- package/dist/api/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/sweep.d.ts +1 -1
- package/dist/api/sweep.js +1 -1
- package/dist/api/sweep.js.map +1 -1
- package/dist/api/thicken.d.ts +1 -1
- package/dist/api/thicken.js +1 -1
- package/dist/api/thicken.js.map +1 -1
- package/dist/api/topo-resolve.d.ts +74 -1
- package/dist/api/topo-resolve.d.ts.map +1 -1
- package/dist/api/topo-resolve.js +180 -2
- package/dist/api/topo-resolve.js.map +1 -1
- package/dist/api/transform.d.ts +10 -6
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +74 -21
- package/dist/api/transform.js.map +1 -1
- package/dist/api/wire.d.ts +1 -1
- package/dist/api/wire.js +1 -1
- package/dist/api/wire.js.map +1 -1
- package/dist/api/xml-dom.d.ts +27 -0
- package/dist/api/xml-dom.d.ts.map +1 -0
- package/dist/api/xml-dom.js +45 -0
- package/dist/api/xml-dom.js.map +1 -0
- package/dist/brep/brep-ops.d.ts +13 -11
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +31 -30
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/brep-topology.d.ts +5 -4
- package/dist/brep/brep-topology.d.ts.map +1 -1
- package/dist/brep/brep-topology.js +9 -6
- package/dist/brep/brep-topology.js.map +1 -1
- package/dist/brep/effective-deflection.d.ts +35 -0
- package/dist/brep/effective-deflection.d.ts.map +1 -0
- package/dist/brep/effective-deflection.js +49 -0
- package/dist/brep/effective-deflection.js.map +1 -0
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +27 -0
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/adapters/brepkit.d.ts +18 -0
- package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brepkit.js +46 -1
- package/dist/brep/engine/adapters/brepkit.js.map +1 -1
- package/dist/brep/engine/adapters/occt.d.ts +1 -1
- package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
- package/dist/brep/engine/adapters/occt.js +3 -1
- package/dist/brep/engine/adapters/occt.js.map +1 -1
- package/dist/brep/engine/primitives.d.ts +29 -7
- package/dist/brep/engine/primitives.d.ts.map +1 -1
- package/dist/brep/engine/primitives.js.map +1 -1
- package/dist/brep/engine/registry.d.ts +24 -1
- package/dist/brep/engine/registry.d.ts.map +1 -1
- package/dist/brep/engine/registry.js +24 -0
- package/dist/brep/engine/registry.js.map +1 -1
- package/dist/brep/engine/types.d.ts +54 -3
- package/dist/brep/engine/types.d.ts.map +1 -1
- package/dist/brep/engine/types.js +10 -0
- package/dist/brep/engine/types.js.map +1 -1
- package/dist/brep/export/export-model.d.ts +79 -0
- package/dist/brep/export/export-model.d.ts.map +1 -0
- package/dist/brep/export/export-model.js +336 -0
- package/dist/brep/export/export-model.js.map +1 -0
- package/dist/brep/face-evolution.d.ts +1 -1
- package/dist/brep/face-evolution.d.ts.map +1 -1
- package/dist/brep/face-evolution.js +20 -1
- package/dist/brep/face-evolution.js.map +1 -1
- package/dist/brep/handle-bridge.d.ts +1 -1
- package/dist/brep/handle-bridge.js +1 -1
- package/dist/brep/handle-bridge.js.map +1 -1
- package/dist/brep/mesh-solid.d.ts +218 -0
- package/dist/brep/mesh-solid.d.ts.map +1 -0
- package/dist/brep/mesh-solid.js +229 -0
- package/dist/brep/mesh-solid.js.map +1 -0
- package/dist/brep/primitives-brep.d.ts.map +1 -1
- package/dist/brep/primitives-brep.js +3 -1
- package/dist/brep/primitives-brep.js.map +1 -1
- package/dist/brep/text/fontRegistry.d.ts +32 -1
- package/dist/brep/text/fontRegistry.d.ts.map +1 -1
- package/dist/brep/text/fontRegistry.js +51 -1
- package/dist/brep/text/fontRegistry.js.map +1 -1
- package/dist/brep/text/text-to-solid.d.ts.map +1 -1
- package/dist/brep/text/text-to-solid.js +8 -3
- package/dist/brep/text/text-to-solid.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts +18 -2
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +453 -125
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts +8 -0
- package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.js +10 -0
- package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
- package/dist/browser-host/browser-font-provider.d.ts +12 -0
- package/dist/browser-host/browser-font-provider.d.ts.map +1 -1
- package/dist/browser-host/browser-font-provider.js +25 -0
- package/dist/browser-host/browser-font-provider.js.map +1 -1
- package/dist/browser.d.ts +6 -3
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +10 -3
- package/dist/browser.js.map +1 -1
- package/dist/cad-runtime/backend-dispatch.d.ts +28 -3
- package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
- package/dist/cad-runtime/backend-dispatch.js +119 -4
- package/dist/cad-runtime/backend-dispatch.js.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
- package/dist/cad-runtime/direct-executor.d.ts +19 -3
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +49 -1
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +3 -3
- package/dist/cad-runtime/ports.d.ts.map +1 -1
- package/dist/cad-runtime/ports.js.map +1 -1
- package/dist/cad-runtime/preview-exec.d.ts +4 -4
- package/dist/cad-runtime/preview-exec.js +2 -2
- package/dist/cad-runtime/preview-exec.js.map +1 -1
- package/dist/cad-runtime/runtime.d.ts +66 -8
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +121 -8
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +37 -1
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +25 -1
- package/dist/define-op.js.map +1 -1
- package/dist/env-agnostic.d.ts +7 -7
- package/dist/env-agnostic.d.ts.map +1 -1
- package/dist/env-agnostic.js +3 -3
- package/dist/env-agnostic.js.map +1 -1
- package/dist/geometry2d/adapt.d.ts +39 -4
- package/dist/geometry2d/adapt.d.ts.map +1 -1
- package/dist/geometry2d/adapt.js +14 -3
- package/dist/geometry2d/adapt.js.map +1 -1
- package/dist/geometry2d/blueprint.d.ts +2 -2
- package/dist/geometry2d/blueprint.js +2 -2
- package/dist/geometry2d/blueprint.js.map +1 -1
- package/dist/geometry2d/bridge/lift-on-plane.d.ts +18 -8
- package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
- package/dist/geometry2d/bridge/lift-on-plane.js +71 -12
- package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
- package/dist/geometry2d/bridge/plane.d.ts +17 -0
- package/dist/geometry2d/bridge/plane.d.ts.map +1 -1
- package/dist/geometry2d/bridge/plane.js +22 -0
- package/dist/geometry2d/bridge/plane.js.map +1 -1
- package/dist/geometry2d/curve2d.d.ts +25 -0
- package/dist/geometry2d/curve2d.d.ts.map +1 -1
- package/dist/geometry2d/curve2d.js +41 -5
- package/dist/geometry2d/curve2d.js.map +1 -1
- package/dist/geometry2d/pen-sketcher.d.ts +25 -0
- package/dist/geometry2d/pen-sketcher.d.ts.map +1 -1
- package/dist/geometry2d/pen-sketcher.js +43 -0
- package/dist/geometry2d/pen-sketcher.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/io/bytes-node.d.ts +11 -0
- package/dist/io/bytes-node.d.ts.map +1 -0
- package/dist/io/bytes-node.js +28 -0
- package/dist/io/bytes-node.js.map +1 -0
- package/dist/io/bytes.d.ts +33 -0
- package/dist/io/bytes.d.ts.map +1 -0
- package/dist/io/bytes.js +41 -0
- package/dist/io/bytes.js.map +1 -0
- package/dist/io/fai-zip/container-read.d.ts +102 -0
- package/dist/io/fai-zip/container-read.d.ts.map +1 -0
- package/dist/io/fai-zip/container-read.js +305 -0
- package/dist/io/fai-zip/container-read.js.map +1 -0
- package/dist/io/fai-zip/container-write.d.ts +70 -0
- package/dist/io/fai-zip/container-write.d.ts.map +1 -0
- package/dist/io/fai-zip/container-write.js +186 -0
- package/dist/io/fai-zip/container-write.js.map +1 -0
- package/dist/io/fai-zip/container.d.ts +107 -0
- package/dist/io/fai-zip/container.d.ts.map +1 -0
- package/dist/io/fai-zip/container.js +89 -0
- package/dist/io/fai-zip/container.js.map +1 -0
- package/dist/io/fai-zip/index.d.ts +18 -0
- package/dist/io/fai-zip/index.d.ts.map +1 -0
- package/dist/io/fai-zip/index.js +4 -0
- package/dist/io/fai-zip/index.js.map +1 -0
- package/dist/io/index.d.ts +10 -0
- package/dist/io/index.d.ts.map +1 -0
- package/dist/io/index.js +13 -0
- package/dist/io/index.js.map +1 -0
- package/dist/io/zip.d.ts +68 -0
- package/dist/io/zip.d.ts.map +1 -0
- package/dist/io/zip.js +147 -0
- package/dist/io/zip.js.map +1 -0
- package/dist/lang/code-to-args.d.ts +30 -4
- package/dist/lang/code-to-args.d.ts.map +1 -1
- package/dist/lang/code-to-args.js +42 -3
- package/dist/lang/code-to-args.js.map +1 -1
- package/dist/lang/codegen.d.ts +45 -1
- package/dist/lang/codegen.d.ts.map +1 -1
- package/dist/lang/codegen.js +135 -6
- package/dist/lang/codegen.js.map +1 -1
- package/dist/lang/host-arg.d.ts +6 -0
- package/dist/lang/host-arg.d.ts.map +1 -1
- package/dist/lang/host-arg.js.map +1 -1
- package/dist/lang/metadata-extractor.d.ts +25 -0
- package/dist/lang/metadata-extractor.d.ts.map +1 -1
- package/dist/lang/metadata-extractor.js +289 -25
- package/dist/lang/metadata-extractor.js.map +1 -1
- package/dist/lang/parse-error.d.ts +7 -1
- package/dist/lang/parse-error.d.ts.map +1 -1
- package/dist/lang/parse-error.js.map +1 -1
- package/dist/lang/security-scanner.d.ts +9 -1
- package/dist/lang/security-scanner.d.ts.map +1 -1
- package/dist/lang/security-scanner.js +38 -1
- package/dist/lang/security-scanner.js.map +1 -1
- package/dist/lang/statement-summary.d.ts +1 -1
- package/dist/lang/statement-summary.js +1 -1
- package/dist/lang/statement-summary.js.map +1 -1
- package/dist/lang/types.d.ts +1 -1
- package/dist/lang/types.js +1 -1
- package/dist/lang/types.js.map +1 -1
- package/dist/mesh/index.d.ts +2 -1
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +2 -1
- package/dist/mesh/index.js.map +1 -1
- package/dist/mesh/io.d.ts +69 -9
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +121 -17
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/reconcile.d.ts +1 -1
- package/dist/mesh/reconcile.js +1 -1
- package/dist/mesh/reconcile.js.map +1 -1
- package/dist/mesh/rigid-transform.d.ts +3 -3
- package/dist/mesh/rigid-transform.js +3 -3
- package/dist/mesh/rigid-transform.js.map +1 -1
- package/dist/mesh/stl-unit.d.ts +24 -0
- package/dist/mesh/stl-unit.d.ts.map +1 -0
- package/dist/mesh/stl-unit.js +17 -0
- package/dist/mesh/stl-unit.js.map +1 -0
- package/dist/mesh/threemf-bambu.d.ts +142 -0
- package/dist/mesh/threemf-bambu.d.ts.map +1 -0
- package/dist/mesh/threemf-bambu.js +334 -0
- package/dist/mesh/threemf-bambu.js.map +1 -0
- package/dist/mesh/threemf-loader.d.ts +50 -0
- package/dist/mesh/threemf-loader.d.ts.map +1 -0
- package/dist/mesh/threemf-loader.js +628 -0
- package/dist/mesh/threemf-loader.js.map +1 -0
- package/dist/mesh/threemf-view.d.ts +71 -0
- package/dist/mesh/threemf-view.d.ts.map +1 -0
- package/dist/mesh/threemf-view.js +100 -0
- package/dist/mesh/threemf-view.js.map +1 -0
- package/dist/mesh/transform.d.ts +2 -2
- package/dist/mesh/transform.d.ts.map +1 -1
- package/dist/mesh/transform.js +3 -3
- package/dist/mesh/transform.js.map +1 -1
- package/dist/mesh/types.d.ts +1 -1
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.js.map +1 -1
- package/dist/node-host/cli.d.ts +44 -6
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +127 -50
- package/dist/node-host/cli.js.map +1 -1
- package/dist/node-host/font-family-index.d.ts +93 -0
- package/dist/node-host/font-family-index.d.ts.map +1 -0
- package/dist/node-host/font-family-index.js +273 -0
- package/dist/node-host/font-family-index.js.map +1 -0
- package/dist/node-host/fs-asset-resolver.d.ts +8 -3
- package/dist/node-host/fs-asset-resolver.d.ts.map +1 -1
- package/dist/node-host/fs-asset-resolver.js +13 -5
- package/dist/node-host/fs-asset-resolver.js.map +1 -1
- package/dist/node-host/index.d.ts +8 -0
- package/dist/node-host/index.d.ts.map +1 -1
- package/dist/node-host/index.js +1 -0
- package/dist/node-host/index.js.map +1 -1
- package/dist/node-host/node-font-provider.d.ts +28 -0
- package/dist/node-host/node-font-provider.d.ts.map +1 -1
- package/dist/node-host/node-font-provider.js +49 -0
- package/dist/node-host/node-font-provider.js.map +1 -1
- package/dist/node.d.ts +1 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +1 -0
- package/dist/node.js.map +1 -1
- package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
- package/dist/occt-kernel/occt-primitives.js +35 -2
- package/dist/occt-kernel/occt-primitives.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts +18 -13
- package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
- package/dist/occt-kernel/occtKernel.js +20 -31
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/dist/occt-kernel/stepColorParser.d.ts +18 -0
- package/dist/occt-kernel/stepColorParser.d.ts.map +1 -1
- package/dist/occt-kernel/stepColorParser.js +38 -0
- package/dist/occt-kernel/stepColorParser.js.map +1 -1
- package/dist/occt-kernel/topologyExt.d.ts +1 -1
- package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
- package/dist/occt-kernel/topologyExt.js +8 -6
- package/dist/occt-kernel/topologyExt.js.map +1 -1
- package/dist/primitives/text/cjk-font.d.ts +2 -15
- package/dist/primitives/text/cjk-font.d.ts.map +1 -1
- package/dist/primitives/text/cjk-font.js +13 -1
- package/dist/primitives/text/cjk-font.js.map +1 -1
- package/dist/runtime-state.d.ts +103 -9
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +95 -2
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdk.d.ts +4 -4
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +6 -6
- package/dist/sdk.js.map +1 -1
- package/dist/shape.d.ts +97 -2
- package/dist/shape.d.ts.map +1 -1
- package/dist/shape.js +126 -1
- package/dist/shape.js.map +1 -1
- package/dist/tolerance.d.ts +38 -0
- package/dist/tolerance.d.ts.map +1 -0
- package/dist/tolerance.js +40 -0
- package/dist/tolerance.js.map +1 -0
- package/dist/topology/naming/lineage.d.ts +6 -0
- package/dist/topology/naming/lineage.d.ts.map +1 -1
- package/dist/topology/naming/lineage.js +8 -0
- package/dist/topology/naming/lineage.js.map +1 -1
- package/dist/topology/naming/resolve-edge.d.ts +20 -1
- package/dist/topology/naming/resolve-edge.d.ts.map +1 -1
- package/dist/topology/naming/resolve-edge.js +54 -20
- package/dist/topology/naming/resolve-edge.js.map +1 -1
- package/dist/topology/naming/score.js +3 -3
- package/dist/topology/naming/score.js.map +1 -1
- package/dist/units.d.ts +248 -0
- package/dist/units.d.ts.map +1 -0
- package/dist/units.js +397 -0
- package/dist/units.js.map +1 -0
- package/dist/weapp.d.ts +6 -2
- package/dist/weapp.d.ts.map +1 -1
- package/dist/weapp.js +7 -1
- package/dist/weapp.js.map +1 -1
- package/package.json +28 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container-write.js","sourceRoot":"","sources":["../../../src/io/fai-zip/container-write.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unified `.fai.zip` write API (docs/fai-zip-format.md §10, Writer obligations).\n *\n * The input is an *assembly* — pure format concepts plus opaque\n * producer-defined members (§3). Nothing here knows about FCStd, editors or\n * filesystems.\n *\n * Environment-independent: ZIP bytes go through `io/zip.ts`, text goes through\n * the UTF-8 codec in `./container.js`. No `node:*`, no fflate, no fs.\n *\n * The point of this layer is that a container which a reader cannot\n * reconstruct is never produced: every §10 obligation that can be checked\n * statically is checked here and throws. A thrown error is always preferable\n * to a container with a dangling reference (spec §10.7, fail loudly).\n */\nimport { writeZipEntries } from '../zip'\nimport {\n assetKeyOf,\n assertDataMemberPath,\n assertModelMemberPath,\n assertSafeMemberPath,\n encodeMemberText,\n type ContainerManifest,\n type ContainerModel,\n} from './container'\n\n/** Assembly input of a container: no producer concept, only format concepts. */\nexport interface ContainerAssembly {\n /** `manifest.models` — the complete model list (spec §4) */\n models: ContainerModel[]\n /** `manifest.active`; must equal some `models[].id` when present */\n active?: string\n /** display-only manifest fields plus §8.2 conversion provenance */\n meta?: {\n createdAt?: string\n appVersion?: string\n label?: string\n source?: ContainerManifest['source']\n }\n /** `model/**` members: full container path → source text. Every `models[].entry` must be present */\n modules: Record<string, string>\n /** `data/**` members: full container path → JSON text (spec §6) */\n dataMembers: Record<string, string>\n /** `files/**` payloads: fileId → bytes. Written as `files/<fileId>.bin` */\n files: Record<string, Uint8Array>\n /** `assets/**` payloads: full container path → bytes (e.g. `assets/bracket.brp`) */\n assets: Record<string, Uint8Array>\n /** producer-defined members (spec §3, e.g. `mapping.json`, `freecad/**`), written as-is */\n producerMembers?: Record<string, Uint8Array>\n}\n\n/** Result of `writeContainer`. */\nexport interface WriteContainerResult {\n /** the assembled container bytes */\n bytes: Uint8Array\n /** the manifest that was serialized into the container */\n manifest: ContainerManifest\n}\n\nconst FILES_PREFIX = 'files/'\nconst ASSETS_PREFIX = 'assets/'\n\n/**\n * Build and validate the container manifest — the single implementation of the\n * §4 schema.\n *\n * Structural only: it cannot check that `models[].entry` and `models[].data`\n * resolve to emitted members, because it never sees the members. That is\n * `writeContainer`'s job, and it is why conversion pipelines that legitimately\n * assemble a container in two passes can still reuse this function.\n *\n * @param input the model list, the optional active id and display metadata\n * @returns the manifest, with `format: 3` and `units: \"mm\"` fixed\n * @throws when `models` is empty, an id/entry is empty, unsafe or duplicated,\n * an `entry` is not a module path under `model/` ending with `.fai.js`, a\n * `data` is not a JSON path under `data/`, or `active` names no model\n */\nexport function createManifest(input: Pick<ContainerAssembly, 'models' | 'active' | 'meta'>): ContainerManifest {\n const { models, active, meta = {} } = input\n if (!Array.isArray(models) || models.length === 0) {\n throw new Error('[fai-zip] createManifest: models must be a non-empty array')\n }\n\n const seenIds = new Set<string>()\n const seenEntries = new Set<string>()\n const normalized: ContainerModel[] = []\n for (let i = 0; i < models.length; i++) {\n const m = models[i] as ContainerModel\n const id = typeof m.id === 'string' ? m.id : ''\n if (id === '') throw new Error(`[fai-zip] createManifest: models[${i}].id must be a non-empty string`)\n if (id.includes('/') || id.includes('\\\\')) {\n throw new Error(`[fai-zip] createManifest: models[${i}].id must not contain \"/\" or \"\\\\\": \"${id}\"`)\n }\n if (seenIds.has(id)) throw new Error(`[fai-zip] createManifest: models[].id must be unique: \"${id}\"`)\n seenIds.add(id)\n\n if (typeof m.entry !== 'string' || m.entry === '') {\n throw new Error(`[fai-zip] createManifest: models[${i}].entry must be a non-empty string`)\n }\n assertModelMemberPath(m.entry, `createManifest: models[${i}].entry`)\n if (seenEntries.has(m.entry)) {\n throw new Error(`[fai-zip] createManifest: models[].entry must be unique: \"${m.entry}\"`)\n }\n seenEntries.add(m.entry)\n\n if (m.data !== undefined) assertDataMemberPath(m.data, `createManifest: models[${i}].data`)\n\n normalized.push({\n id,\n entry: m.entry,\n ...(m.label !== undefined ? { label: m.label } : {}),\n ...(m.data !== undefined ? { data: m.data } : {}),\n })\n }\n\n if (active !== undefined && !seenIds.has(active)) {\n throw new Error(`[fai-zip] createManifest: active must equal some models[].id: \"${active}\"`)\n }\n\n return {\n format: 3,\n units: 'mm',\n models: normalized,\n ...(active !== undefined ? { active } : {}),\n ...(meta.createdAt !== undefined ? { createdAt: meta.createdAt } : {}),\n ...(meta.appVersion !== undefined ? { appVersion: meta.appVersion } : {}),\n ...(meta.label !== undefined ? { label: meta.label } : {}),\n ...(meta.source !== undefined ? { source: meta.source } : {}),\n }\n}\n\n/**\n * Assemble a container from an assembly, enforcing spec §10 before writing any\n * bytes.\n *\n * Enforced (each throws, never silently produces an unreconstructable\n * container):\n * 1. `models` is non-empty, ids and entries are unique (`createManifest`);\n * 2. every `models[].entry` is emitted in `modules`;\n * 3. every `models[].data` is emitted in `dataMembers`;\n * 4. `active`, when present, equals some `models[].id` (`createManifest`);\n * 5. asset keys are unique across `files/**`, `assets/**` and any\n * producer-defined member in those namespaces (spec §7.1) — a fileId that\n * would not survive the base-name key rule is an error, not a silent rename;\n * 6. every `entry`/`data`/module/asset path is a safe relative member path in\n * its namespace, and no path is emitted twice.\n *\n * @param assembly the assembly input (§3.4)\n * @returns the container bytes and the manifest that was written\n * @throws when any of the obligations above is violated\n */\nexport function writeContainer(assembly: ContainerAssembly): WriteContainerResult {\n const { modules, dataMembers, files, assets, producerMembers = {} } = assembly\n const manifest = createManifest(assembly)\n\n const members = new Map<string, Uint8Array>()\n const claimedKeys = new Map<string, string>()\n\n /** Record an asset key; a second member claiming it is an error (spec §7.1). */\n const claim = (key: string, path: string): void => {\n const prev = claimedKeys.get(key)\n if (prev !== undefined) {\n throw new Error(`[fai-zip] writeContainer: duplicate asset key \"${key}\" (members \"${prev}\" and \"${path}\")`)\n }\n claimedKeys.set(key, path)\n }\n\n /** Add one member; a duplicate member path is an error. */\n const put = (path: string, body: Uint8Array): void => {\n if (members.has(path)) {\n throw new Error(`[fai-zip] writeContainer: duplicate member path \"${path}\"`)\n }\n members.set(path, body)\n }\n\n // manifest.json — always first, always present (spec §10.1)\n put('manifest.json', encodeMemberText(JSON.stringify(manifest, null, 2)))\n\n // model/** — every declared entry must be delivered (spec §10.2, §10.3)\n for (const [path, source] of Object.entries(modules)) {\n assertModelMemberPath(path, 'writeContainer: modules key')\n put(path, encodeMemberText(source))\n }\n for (const m of manifest.models) {\n if (!members.has(m.entry)) {\n throw new Error(`[fai-zip] writeContainer: models[].entry \"${m.entry}\" has no module in the assembly`)\n }\n }\n\n // data/** — a declared data member must be delivered, and must be JSON (spec §6.1)\n for (const [path, json] of Object.entries(dataMembers)) {\n assertDataMemberPath(path, 'writeContainer: dataMembers key')\n try {\n JSON.parse(json)\n } catch (e) {\n throw new Error(`[fai-zip] writeContainer: data member \"${path}\" is not valid JSON: ${e instanceof Error ? e.message : String(e)}`, { cause: e })\n }\n put(path, encodeMemberText(json))\n }\n for (const m of manifest.models) {\n if (m.data !== undefined && !members.has(m.data)) {\n throw new Error(`[fai-zip] writeContainer: models[].data \"${m.data}\" has no member in the assembly`)\n }\n }\n\n // files/** — keyed by fileId, stored as files/<fileId>.bin so the key\n // round-trips through the base-name rule (spec §7). A fileId containing a\n // separator would be silently re-keyed on read, so it is rejected here.\n for (const [fileId, body] of Object.entries(files)) {\n if (fileId === '' || fileId.includes('/') || fileId.includes('\\\\')) {\n throw new Error(`[fai-zip] writeContainer: fileId must be a non-empty base name without separators: \"${fileId}\"`)\n }\n const path = `${FILES_PREFIX}${fileId}.bin`\n put(path, body)\n claim(assetKeyOf(path, FILES_PREFIX), path)\n }\n\n // assets/** — the key is the base name, so two paths may collide (spec §7.1)\n for (const [path, body] of Object.entries(assets)) {\n assertSafeMemberPath(path, 'writeContainer: assets key')\n if (!path.startsWith(ASSETS_PREFIX)) {\n throw new Error(`[fai-zip] writeContainer: assets key must be under assets/: \"${path}\"`)\n }\n put(path, body)\n claim(assetKeyOf(path, ASSETS_PREFIX), path)\n }\n\n // producer-defined members (spec §3) — opaque payload, but they still live\n // in the archive, so a member dropped under files//assets/ takes part in the\n // key uniqueness rule whether or not the producer thought of it that way.\n for (const [path, body] of Object.entries(producerMembers)) {\n assertSafeMemberPath(path, 'writeContainer: producerMembers key')\n put(path, body)\n if (path.startsWith(FILES_PREFIX)) claim(assetKeyOf(path, FILES_PREFIX), path)\n else if (path.startsWith(ASSETS_PREFIX)) claim(assetKeyOf(path, ASSETS_PREFIX), path)\n }\n\n return { bytes: writeZipEntries(Object.fromEntries(members)), manifest }\n}\n"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.fai.zip` container schemas (docs/fai-zip-format.md §4, §7).
|
|
3
|
+
*
|
|
4
|
+
* `.fai.zip` is faijs' own container format, so this module carries the format
|
|
5
|
+
* itself and nothing producer-specific: `source` is a §4 manifest field
|
|
6
|
+
* (described in §8.2 as conversion provenance), not an FCStd leak. Producer
|
|
7
|
+
* members such as `mapping.json` and `freecad/**` are passed through opaquely
|
|
8
|
+
* (spec §3, "Optional, producer-defined"). `requiresBrep` was removed in
|
|
9
|
+
* 2026-10-03 (fai-zip-third-party-sdk-and-viewer-plan): BREP is always the
|
|
10
|
+
* default-required execution chain, so no per-container flag exists.
|
|
11
|
+
*
|
|
12
|
+
* Environment-independent by construction: no `node:*`, no DOM, no fflate.
|
|
13
|
+
* Text members go through the UTF-8 codec below, ZIP bytes go through
|
|
14
|
+
* `io/zip.ts` — the container layer never touches a ZIP library directly.
|
|
15
|
+
*/
|
|
16
|
+
/** One model in the container: entry script, plus an optional data member. */
|
|
17
|
+
export interface ContainerModel {
|
|
18
|
+
/** model identifier: unique in the container, stable (switch/data key), no `/` or `\` */
|
|
19
|
+
id: string;
|
|
20
|
+
/** container path of the model's entry script, inside `model/`, ends with `.fai.js` */
|
|
21
|
+
entry: string;
|
|
22
|
+
/** display name; a reader MUST NOT use it as an identifier (spec §4) */
|
|
23
|
+
label?: string;
|
|
24
|
+
/** container path of the model's data member; absent = no data member (spec §6.5) */
|
|
25
|
+
data?: string;
|
|
26
|
+
}
|
|
27
|
+
/** `manifest.json` schema (unified `.fai.zip` format v3, spec §4). */
|
|
28
|
+
export interface ContainerManifest {
|
|
29
|
+
/** container format identifier — MUST be 3 in this revision (spec §11) */
|
|
30
|
+
format: 3;
|
|
31
|
+
/** unit of every coordinate in the container; always "mm" */
|
|
32
|
+
units: 'mm';
|
|
33
|
+
/** the complete model list (length ≥ 1) */
|
|
34
|
+
models: ContainerModel[];
|
|
35
|
+
/** id of the initially active model; absent = `models[0]` */
|
|
36
|
+
active?: string;
|
|
37
|
+
/** ISO 8601 timestamp. Display only */
|
|
38
|
+
createdAt?: string;
|
|
39
|
+
/** version of the producing tool. Display only */
|
|
40
|
+
appVersion?: string;
|
|
41
|
+
/** container display name. Display only */
|
|
42
|
+
label?: string;
|
|
43
|
+
/** conversion provenance (spec §8.2). Display only */
|
|
44
|
+
source?: {
|
|
45
|
+
/** original source document file name (not a full path) */
|
|
46
|
+
file: string;
|
|
47
|
+
programVersion: string;
|
|
48
|
+
schemaVersion: number;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Asset payloads of a container: bytes keyed by asset key (spec §7).
|
|
53
|
+
* The key of a member is its base name with the final extension removed.
|
|
54
|
+
*/
|
|
55
|
+
export interface ContainerAssetEntries {
|
|
56
|
+
/** `files/**` members — key = fileId (member path under `files/` with the final extension removed) */
|
|
57
|
+
files: Record<string, Uint8Array>;
|
|
58
|
+
/** `assets/**` members — key = base name with the final extension removed */
|
|
59
|
+
assets: Record<string, Uint8Array>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Asset key of a member path: base name with the final extension removed
|
|
63
|
+
* (spec §7). `assets/bracket.brp` → `bracket`; `files/deep/9f1c2a.bin` →
|
|
64
|
+
* `9f1c2a`. The rule is by base name, so nesting does not change the key.
|
|
65
|
+
*
|
|
66
|
+
* @param path the container member path (including its namespace prefix)
|
|
67
|
+
* @param prefix the namespace prefix the path was matched against
|
|
68
|
+
* @returns the asset key
|
|
69
|
+
*/
|
|
70
|
+
export declare function assetKeyOf(path: string, prefix: string): string;
|
|
71
|
+
/**
|
|
72
|
+
* Decode a text member. UTF-8, matching the spec's "UTF-8 JSON object" wording.
|
|
73
|
+
* @param bytes the member bytes
|
|
74
|
+
* @returns the decoded text
|
|
75
|
+
*/
|
|
76
|
+
export declare function decodeMemberText(bytes: Uint8Array): string;
|
|
77
|
+
/**
|
|
78
|
+
* Encode a text member to UTF-8 bytes.
|
|
79
|
+
* @param text the member text
|
|
80
|
+
* @returns the encoded bytes
|
|
81
|
+
*/
|
|
82
|
+
export declare function encodeMemberText(text: string): Uint8Array;
|
|
83
|
+
/**
|
|
84
|
+
* Validate a member path against the spec §2 naming rules: relative, forward
|
|
85
|
+
* slashes only, no `..`, no drive letter, no leading `/`.
|
|
86
|
+
* @param path the member path to check
|
|
87
|
+
* @param what description of the field being checked, used in the error
|
|
88
|
+
* @throws when the path is not a safe relative member path
|
|
89
|
+
*/
|
|
90
|
+
export declare function assertSafeMemberPath(path: string, what: string): void;
|
|
91
|
+
/**
|
|
92
|
+
* Validate that a path is a model entry/script member: under `model/` and
|
|
93
|
+
* ending with `.fai.js` (spec §5.1).
|
|
94
|
+
* @param path the member path to check
|
|
95
|
+
* @param what description of the field being checked, used in the error
|
|
96
|
+
* @throws when the path is not a model member path
|
|
97
|
+
*/
|
|
98
|
+
export declare function assertModelMemberPath(path: string, what: string): void;
|
|
99
|
+
/**
|
|
100
|
+
* Validate that a path is a data member path: under `data/` and ending with
|
|
101
|
+
* `.json` (spec §6.1).
|
|
102
|
+
* @param path the member path to check
|
|
103
|
+
* @param what description of the field being checked, used in the error
|
|
104
|
+
* @throws when the path is not a data member path
|
|
105
|
+
*/
|
|
106
|
+
export declare function assertDataMemberPath(path: string, what: string): void;
|
|
107
|
+
//# sourceMappingURL=container.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../src/io/fai-zip/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,yFAAyF;IACzF,EAAE,EAAE,MAAM,CAAA;IACV,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAA;IACb,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,MAAM,EAAE,CAAC,CAAA;IACT,6DAA6D;IAC7D,KAAK,EAAE,IAAI,CAAA;IACX,2CAA2C;IAC3C,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,MAAM,CAAC,EAAE;QACP,2DAA2D;QAC3D,IAAI,EAAE,MAAM,CAAA;QACZ,cAAc,EAAE,MAAM,CAAA;QACtB,aAAa,EAAE,MAAM,CAAA;KACtB,CAAA;CACF;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,sGAAsG;IACtG,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACjC,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM/D;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEzD;AAKD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAIrE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAKrE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.fai.zip` container schemas (docs/fai-zip-format.md §4, §7).
|
|
3
|
+
*
|
|
4
|
+
* `.fai.zip` is faijs' own container format, so this module carries the format
|
|
5
|
+
* itself and nothing producer-specific: `source` is a §4 manifest field
|
|
6
|
+
* (described in §8.2 as conversion provenance), not an FCStd leak. Producer
|
|
7
|
+
* members such as `mapping.json` and `freecad/**` are passed through opaquely
|
|
8
|
+
* (spec §3, "Optional, producer-defined"). `requiresBrep` was removed in
|
|
9
|
+
* 2026-10-03 (fai-zip-third-party-sdk-and-viewer-plan): BREP is always the
|
|
10
|
+
* default-required execution chain, so no per-container flag exists.
|
|
11
|
+
*
|
|
12
|
+
* Environment-independent by construction: no `node:*`, no DOM, no fflate.
|
|
13
|
+
* Text members go through the UTF-8 codec below, ZIP bytes go through
|
|
14
|
+
* `io/zip.ts` — the container layer never touches a ZIP library directly.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Asset key of a member path: base name with the final extension removed
|
|
18
|
+
* (spec §7). `assets/bracket.brp` → `bracket`; `files/deep/9f1c2a.bin` →
|
|
19
|
+
* `9f1c2a`. The rule is by base name, so nesting does not change the key.
|
|
20
|
+
*
|
|
21
|
+
* @param path the container member path (including its namespace prefix)
|
|
22
|
+
* @param prefix the namespace prefix the path was matched against
|
|
23
|
+
* @returns the asset key
|
|
24
|
+
*/
|
|
25
|
+
export function assetKeyOf(path, prefix) {
|
|
26
|
+
const rel = path.slice(prefix.length);
|
|
27
|
+
const slash = rel.lastIndexOf('/');
|
|
28
|
+
const base = slash >= 0 ? rel.slice(slash + 1) : rel;
|
|
29
|
+
const dot = base.lastIndexOf('.');
|
|
30
|
+
return dot > 0 ? base.slice(0, dot) : base;
|
|
31
|
+
}
|
|
32
|
+
const UTF8_DECODER = new TextDecoder('utf-8');
|
|
33
|
+
/**
|
|
34
|
+
* Decode a text member. UTF-8, matching the spec's "UTF-8 JSON object" wording.
|
|
35
|
+
* @param bytes the member bytes
|
|
36
|
+
* @returns the decoded text
|
|
37
|
+
*/
|
|
38
|
+
export function decodeMemberText(bytes) {
|
|
39
|
+
return UTF8_DECODER.decode(bytes);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Encode a text member to UTF-8 bytes.
|
|
43
|
+
* @param text the member text
|
|
44
|
+
* @returns the encoded bytes
|
|
45
|
+
*/
|
|
46
|
+
export function encodeMemberText(text) {
|
|
47
|
+
return new TextEncoder().encode(text);
|
|
48
|
+
}
|
|
49
|
+
const MODEL_PREFIX = 'model/';
|
|
50
|
+
const DATA_PREFIX = 'data/';
|
|
51
|
+
/**
|
|
52
|
+
* Validate a member path against the spec §2 naming rules: relative, forward
|
|
53
|
+
* slashes only, no `..`, no drive letter, no leading `/`.
|
|
54
|
+
* @param path the member path to check
|
|
55
|
+
* @param what description of the field being checked, used in the error
|
|
56
|
+
* @throws when the path is not a safe relative member path
|
|
57
|
+
*/
|
|
58
|
+
export function assertSafeMemberPath(path, what) {
|
|
59
|
+
if (path === '' || path.startsWith('/') || path.includes('\\') || path.includes('..') || /^[A-Za-z]:/.test(path)) {
|
|
60
|
+
throw new Error(`[fai-zip] unsafe member path in ${what}: "${path}"`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate that a path is a model entry/script member: under `model/` and
|
|
65
|
+
* ending with `.fai.js` (spec §5.1).
|
|
66
|
+
* @param path the member path to check
|
|
67
|
+
* @param what description of the field being checked, used in the error
|
|
68
|
+
* @throws when the path is not a model member path
|
|
69
|
+
*/
|
|
70
|
+
export function assertModelMemberPath(path, what) {
|
|
71
|
+
assertSafeMemberPath(path, what);
|
|
72
|
+
if (!path.startsWith(MODEL_PREFIX) || !path.endsWith('.fai.js')) {
|
|
73
|
+
throw new Error(`[fai-zip] ${what} must be under model/ and end with .fai.js: "${path}"`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validate that a path is a data member path: under `data/` and ending with
|
|
78
|
+
* `.json` (spec §6.1).
|
|
79
|
+
* @param path the member path to check
|
|
80
|
+
* @param what description of the field being checked, used in the error
|
|
81
|
+
* @throws when the path is not a data member path
|
|
82
|
+
*/
|
|
83
|
+
export function assertDataMemberPath(path, what) {
|
|
84
|
+
assertSafeMemberPath(path, what);
|
|
85
|
+
if (!path.startsWith(DATA_PREFIX) || !path.endsWith('.json')) {
|
|
86
|
+
throw new Error(`[fai-zip] ${what} must be under data/ and end with .json: "${path}"`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../../src/io/fai-zip/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAkDH;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,MAAc;IACrD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAClC,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACjC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAC5C,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,CAAA;AAE7C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,YAAY,GAAG,QAAQ,CAAA;AAC7B,MAAM,WAAW,GAAG,OAAO,CAAA;AAE3B;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,IAAY;IAC7D,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjH,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,MAAM,IAAI,GAAG,CAAC,CAAA;IACvE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY,EAAE,IAAY;IAC9D,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAChC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,gDAAgD,IAAI,GAAG,CAAC,CAAA;IAC3F,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,IAAY;IAC7D,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAChC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,6CAA6C,IAAI,GAAG,CAAC,CAAA;IACxF,CAAC;AACH,CAAC","sourcesContent":["/**\n * `.fai.zip` container schemas (docs/fai-zip-format.md §4, §7).\n *\n * `.fai.zip` is faijs' own container format, so this module carries the format\n * itself and nothing producer-specific: `source` is a §4 manifest field\n * (described in §8.2 as conversion provenance), not an FCStd leak. Producer\n * members such as `mapping.json` and `freecad/**` are passed through opaquely\n * (spec §3, \"Optional, producer-defined\"). `requiresBrep` was removed in\n * 2026-10-03 (fai-zip-third-party-sdk-and-viewer-plan): BREP is always the\n * default-required execution chain, so no per-container flag exists.\n *\n * Environment-independent by construction: no `node:*`, no DOM, no fflate.\n * Text members go through the UTF-8 codec below, ZIP bytes go through\n * `io/zip.ts` — the container layer never touches a ZIP library directly.\n */\n\n/** One model in the container: entry script, plus an optional data member. */\nexport interface ContainerModel {\n /** model identifier: unique in the container, stable (switch/data key), no `/` or `\\` */\n id: string\n /** container path of the model's entry script, inside `model/`, ends with `.fai.js` */\n entry: string\n /** display name; a reader MUST NOT use it as an identifier (spec §4) */\n label?: string\n /** container path of the model's data member; absent = no data member (spec §6.5) */\n data?: string\n}\n\n/** `manifest.json` schema (unified `.fai.zip` format v3, spec §4). */\nexport interface ContainerManifest {\n /** container format identifier — MUST be 3 in this revision (spec §11) */\n format: 3\n /** unit of every coordinate in the container; always \"mm\" */\n units: 'mm'\n /** the complete model list (length ≥ 1) */\n models: ContainerModel[]\n /** id of the initially active model; absent = `models[0]` */\n active?: string\n /** ISO 8601 timestamp. Display only */\n createdAt?: string\n /** version of the producing tool. Display only */\n appVersion?: string\n /** container display name. Display only */\n label?: string\n /** conversion provenance (spec §8.2). Display only */\n source?: {\n /** original source document file name (not a full path) */\n file: string\n programVersion: string\n schemaVersion: number\n }\n}\n\n/**\n * Asset payloads of a container: bytes keyed by asset key (spec §7).\n * The key of a member is its base name with the final extension removed.\n */\nexport interface ContainerAssetEntries {\n /** `files/**` members — key = fileId (member path under `files/` with the final extension removed) */\n files: Record<string, Uint8Array>\n /** `assets/**` members — key = base name with the final extension removed */\n assets: Record<string, Uint8Array>\n}\n\n/**\n * Asset key of a member path: base name with the final extension removed\n * (spec §7). `assets/bracket.brp` → `bracket`; `files/deep/9f1c2a.bin` →\n * `9f1c2a`. The rule is by base name, so nesting does not change the key.\n *\n * @param path the container member path (including its namespace prefix)\n * @param prefix the namespace prefix the path was matched against\n * @returns the asset key\n */\nexport function assetKeyOf(path: string, prefix: string): string {\n const rel = path.slice(prefix.length)\n const slash = rel.lastIndexOf('/')\n const base = slash >= 0 ? rel.slice(slash + 1) : rel\n const dot = base.lastIndexOf('.')\n return dot > 0 ? base.slice(0, dot) : base\n}\n\nconst UTF8_DECODER = new TextDecoder('utf-8')\n\n/**\n * Decode a text member. UTF-8, matching the spec's \"UTF-8 JSON object\" wording.\n * @param bytes the member bytes\n * @returns the decoded text\n */\nexport function decodeMemberText(bytes: Uint8Array): string {\n return UTF8_DECODER.decode(bytes)\n}\n\n/**\n * Encode a text member to UTF-8 bytes.\n * @param text the member text\n * @returns the encoded bytes\n */\nexport function encodeMemberText(text: string): Uint8Array {\n return new TextEncoder().encode(text)\n}\n\nconst MODEL_PREFIX = 'model/'\nconst DATA_PREFIX = 'data/'\n\n/**\n * Validate a member path against the spec §2 naming rules: relative, forward\n * slashes only, no `..`, no drive letter, no leading `/`.\n * @param path the member path to check\n * @param what description of the field being checked, used in the error\n * @throws when the path is not a safe relative member path\n */\nexport function assertSafeMemberPath(path: string, what: string): void {\n if (path === '' || path.startsWith('/') || path.includes('\\\\') || path.includes('..') || /^[A-Za-z]:/.test(path)) {\n throw new Error(`[fai-zip] unsafe member path in ${what}: \"${path}\"`)\n }\n}\n\n/**\n * Validate that a path is a model entry/script member: under `model/` and\n * ending with `.fai.js` (spec §5.1).\n * @param path the member path to check\n * @param what description of the field being checked, used in the error\n * @throws when the path is not a model member path\n */\nexport function assertModelMemberPath(path: string, what: string): void {\n assertSafeMemberPath(path, what)\n if (!path.startsWith(MODEL_PREFIX) || !path.endsWith('.fai.js')) {\n throw new Error(`[fai-zip] ${what} must be under model/ and end with .fai.js: \"${path}\"`)\n }\n}\n\n/**\n * Validate that a path is a data member path: under `data/` and ending with\n * `.json` (spec §6.1).\n * @param path the member path to check\n * @param what description of the field being checked, used in the error\n * @throws when the path is not a data member path\n */\nexport function assertDataMemberPath(path: string, what: string): void {\n assertSafeMemberPath(path, what)\n if (!path.startsWith(DATA_PREFIX) || !path.endsWith('.json')) {\n throw new Error(`[fai-zip] ${what} must be under data/ and end with .json: \"${path}\"`)\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@faicad/faijs/io/fai-zip` — the `.fai.zip` container layer.
|
|
3
|
+
*
|
|
4
|
+
* `.fai.zip` is faijs' own container format (docs/fai-zip-format.md). Reading,
|
|
5
|
+
* writing and the manifest schema live here, in core, because every host that
|
|
6
|
+
* loads or saves a faijs project needs them and none of them needs a
|
|
7
|
+
* producer-specific converter to get at them.
|
|
8
|
+
*
|
|
9
|
+
* The layer is a peer of `@faicad/faijs/io`, not a child of it: `io` owns ZIP
|
|
10
|
+
* bytes, this owns the container format built on top. `io/index.ts` therefore
|
|
11
|
+
* does not re-export anything from here — a base layer never depends on a
|
|
12
|
+
* format layer.
|
|
13
|
+
*/
|
|
14
|
+
export type { ContainerAssetEntries, ContainerManifest, ContainerModel } from './container.js';
|
|
15
|
+
export { decodeMemberText, encodeMemberText } from './container.js';
|
|
16
|
+
export { listModels, listModules, openContainer, readAssetEntries, readDataMember, readManifest, readModule, type OpenContainerOptions, type OpenContainerResult, } from './container-read.js';
|
|
17
|
+
export { createManifest, writeContainer, type ContainerAssembly, type WriteContainerResult, } from './container-write.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/io/fai-zip/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC3F,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,UAAU,EACV,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,cAAc,EACd,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { decodeMemberText, encodeMemberText } from './container.js';
|
|
2
|
+
export { listModels, listModules, openContainer, readAssetEntries, readDataMember, readManifest, readModule, } from './container-read.js';
|
|
3
|
+
export { createManifest, writeContainer, } from './container-write.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/io/fai-zip/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,UAAU,GAGX,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,cAAc,EACd,cAAc,GAGf,MAAM,mBAAmB,CAAA","sourcesContent":["/**\n * `@faicad/faijs/io/fai-zip` — the `.fai.zip` container layer.\n *\n * `.fai.zip` is faijs' own container format (docs/fai-zip-format.md). Reading,\n * writing and the manifest schema live here, in core, because every host that\n * loads or saves a faijs project needs them and none of them needs a\n * producer-specific converter to get at them.\n *\n * The layer is a peer of `@faicad/faijs/io`, not a child of it: `io` owns ZIP\n * bytes, this owns the container format built on top. `io/index.ts` therefore\n * does not re-export anything from here — a base layer never depends on a\n * format layer.\n */\nexport type { ContainerAssetEntries, ContainerManifest, ContainerModel } from './container'\nexport { decodeMemberText, encodeMemberText } from './container'\nexport {\n listModels,\n listModules,\n openContainer,\n readAssetEntries,\n readDataMember,\n readManifest,\n readModule,\n type OpenContainerOptions,\n type OpenContainerResult,\n} from './container-read'\nexport {\n createManifest,\n writeContainer,\n type ContainerAssembly,\n type WriteContainerResult,\n} from './container-write'\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* io — unified ZIP container IO for faijs (and the host).
|
|
3
|
+
*
|
|
4
|
+
* Single read/write entry for ZIP bytes; every downstream consumer (3MF loader,
|
|
5
|
+
* export-model writer, fcstd, demo) should use these rather than fflate
|
|
6
|
+
* directly. See `io/zip.ts` for the behaviour contract.
|
|
7
|
+
*/
|
|
8
|
+
export { readZipEntries, readZipEntriesAsync, writeZipEntries, writeZipEntriesAsync, DEFAULT_MAX_ENTRIES, DEFAULT_MAX_TOTAL_BYTES, type ZipReadOptions, } from './zip.js';
|
|
9
|
+
export { toArrayBuffer } from './bytes.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,OAAO,CAAA;AAId,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/io/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* io — unified ZIP container IO for faijs (and the host).
|
|
3
|
+
*
|
|
4
|
+
* Single read/write entry for ZIP bytes; every downstream consumer (3MF loader,
|
|
5
|
+
* export-model writer, fcstd, demo) should use these rather than fflate
|
|
6
|
+
* directly. See `io/zip.ts` for the behaviour contract.
|
|
7
|
+
*/
|
|
8
|
+
export { readZipEntries, readZipEntriesAsync, writeZipEntries, writeZipEntriesAsync, DEFAULT_MAX_ENTRIES, DEFAULT_MAX_TOTAL_BYTES, } from './zip.js';
|
|
9
|
+
// toArrayBuffer is browser-safe; readFileArrayBuffer is Node-only and lives in
|
|
10
|
+
// bytes-node.ts — exporting it here would pull node:fs into browser bundles
|
|
11
|
+
// (seen as a hard rollup error in the 3d_editor web build).
|
|
12
|
+
export { toArrayBuffer } from './bytes.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,GAExB,MAAM,OAAO,CAAA;AACd,+EAA+E;AAC/E,4EAA4E;AAC5E,4DAA4D;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA","sourcesContent":["/**\n * io — unified ZIP container IO for faijs (and the host).\n *\n * Single read/write entry for ZIP bytes; every downstream consumer (3MF loader,\n * export-model writer, fcstd, demo) should use these rather than fflate\n * directly. See `io/zip.ts` for the behaviour contract.\n */\nexport {\n readZipEntries,\n readZipEntriesAsync,\n writeZipEntries,\n writeZipEntriesAsync,\n DEFAULT_MAX_ENTRIES,\n DEFAULT_MAX_TOTAL_BYTES,\n type ZipReadOptions,\n} from './zip'\n// toArrayBuffer is browser-safe; readFileArrayBuffer is Node-only and lives in\n// bytes-node.ts — exporting it here would pull node:fs into browser bundles\n// (seen as a hard rollup error in the 3d_editor web build).\nexport { toArrayBuffer } from './bytes'\n"]}
|
package/dist/io/zip.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** fflate's valid compression levels. */
|
|
2
|
+
export type ZipLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
3
|
+
/** Default compression level used by the sync/async writers. */
|
|
4
|
+
export declare const DEFAULT_ZIP_LEVEL: ZipLevel;
|
|
5
|
+
/** Read-side caps bounding what a single read materialises. */
|
|
6
|
+
export interface ZipReadOptions {
|
|
7
|
+
/** Max entry count; default `DEFAULT_MAX_ENTRIES` (9999). */
|
|
8
|
+
maxEntries?: number;
|
|
9
|
+
/** Max total uncompressed bytes; default `DEFAULT_MAX_TOTAL_BYTES` (512 MiB). */
|
|
10
|
+
maxTotalBytes?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Default cap on the number of entries a single read materialises. Deliberately
|
|
14
|
+
* generous: loading a project container is not the same magnitude as a user
|
|
15
|
+
* picking an arbitrary file, and container members (byte-exact source shadows,
|
|
16
|
+
* baked `.brp` payloads) scale with the source document.
|
|
17
|
+
*
|
|
18
|
+
* NOTE these caps are *post-decompression* checks — `unzipSync` has already
|
|
19
|
+
* materialised the archive when they run, so they bound what a caller keeps
|
|
20
|
+
* and walks, not peak allocation. They are a resource budget, NOT a
|
|
21
|
+
* zip-bomb defence. Pre-decompression rejection would need fflate's
|
|
22
|
+
* `filter` (per-entry `originalSize` accounting) and is tracked separately.
|
|
23
|
+
*/
|
|
24
|
+
export declare const DEFAULT_MAX_ENTRIES = 9999;
|
|
25
|
+
/** Default cap on total uncompressed bytes; same post-decompression caveat as {@link DEFAULT_MAX_ENTRIES}. */
|
|
26
|
+
export declare const DEFAULT_MAX_TOTAL_BYTES: number;
|
|
27
|
+
/**
|
|
28
|
+
* Unzip bytes to an entry table (directory entries filtered).
|
|
29
|
+
*
|
|
30
|
+
* @param data - the ZIP bytes to read (Uint8Array or ArrayBuffer).
|
|
31
|
+
* @param opts - optional read caps (maxEntries / maxTotalBytes).
|
|
32
|
+
* @returns a map of archive path -> decompressed bytes.
|
|
33
|
+
* @throws on non-ZIP bytes or when caps are exceeded.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readZipEntries(data: Uint8Array | ArrayBuffer, opts?: ZipReadOptions): Map<string, Uint8Array>;
|
|
36
|
+
type EntryTable = Record<string, Uint8Array>;
|
|
37
|
+
/** Write-side options (compression level + advisory ZIP comment). */
|
|
38
|
+
export interface ZipWriteOptions {
|
|
39
|
+
/** Compression level; default `DEFAULT_ZIP_LEVEL` (6). */
|
|
40
|
+
level?: ZipLevel;
|
|
41
|
+
/** Optional ZIP comment (advisory — consumers read it via the EOCD record). */
|
|
42
|
+
comment?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Zip an entry table into bytes.
|
|
46
|
+
*
|
|
47
|
+
* @param entries - archive path -> bytes to store.
|
|
48
|
+
* @param opts - optional compression level / ZIP comment.
|
|
49
|
+
* @returns the ZIP bytes.
|
|
50
|
+
* @throws on an empty entry table.
|
|
51
|
+
*/
|
|
52
|
+
export declare function writeZipEntries(entries: EntryTable, opts?: ZipWriteOptions): Uint8Array;
|
|
53
|
+
/** Async read: yields to the event loop between chunks (see plan §D8).
|
|
54
|
+
*
|
|
55
|
+
* @param data - the ZIP bytes to read (Uint8Array or ArrayBuffer).
|
|
56
|
+
* @param opts - optional read caps (maxEntries / maxTotalBytes).
|
|
57
|
+
* @returns a promise of the entry map.
|
|
58
|
+
*/
|
|
59
|
+
export declare function readZipEntriesAsync(data: Uint8Array | ArrayBuffer, opts?: ZipReadOptions): Promise<Map<string, Uint8Array>>;
|
|
60
|
+
/** Zip an entry table into bytes, yielding between chunks.
|
|
61
|
+
*
|
|
62
|
+
* @param entries - archive path -> entry to store.
|
|
63
|
+
* @param opts - optional compression level / ZIP comment.
|
|
64
|
+
* @returns a promise of the ZIP bytes.
|
|
65
|
+
*/
|
|
66
|
+
export declare function writeZipEntriesAsync(entries: EntryTable, opts?: ZipWriteOptions): Promise<Uint8Array>;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=zip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../src/io/zip.ts"],"names":[],"mappings":"AAsBA,yCAAyC;AACzC,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAE5D,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,EAAE,QAAY,CAAA;AAE5C,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAID;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,8GAA8G;AAC9G,eAAO,MAAM,uBAAuB,QAAoB,CAAA;AA4CxD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,GAAG,WAAW,EAC9B,IAAI,GAAE,cAAmB,GACxB,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAQzB;AAED,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAE5C,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,UAAU,CAKvF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,GAAG,WAAW,EAC9B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAclC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,UAAU,EACnB,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,UAAU,CAAC,CAarB"}
|
package/dist/io/zip.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* io/zip — the single ZIP read/write entry for every faijs consumer.
|
|
3
|
+
*
|
|
4
|
+
* This is the one place faijs (and the host) reads and writes ZIP bytes. The
|
|
5
|
+
* plan unifies two previously-divergent behaviours: reading uses fflate's
|
|
6
|
+
* `unzipSync`, writing uses `zipSync`. Both surface as a plain entry map so
|
|
7
|
+
* no caller ever touches fflate's `Unzlib` / `Zip` objects directly.
|
|
8
|
+
*
|
|
9
|
+
* Contract:
|
|
10
|
+
* - Entries are keyed by the archive path (fflate normalises to forward
|
|
11
|
+
* slashes). Directory entries (keys ending in `/`) are filtered out — they
|
|
12
|
+
* are produced by fflate and are not data.
|
|
13
|
+
* - Every function throws on failure; there is no degraded return value.
|
|
14
|
+
* - A non-zip buffer throws `new Error('zip read failed: <msg>')`.
|
|
15
|
+
* - `writeZipEntries` rejects an empty entry table (never produces an empty zip).
|
|
16
|
+
*
|
|
17
|
+
* Environment: plain pure functions usable in node, browser, worker and the
|
|
18
|
+
* weapp worker — fflate's sync + async (callback) forms cover all of them
|
|
19
|
+
* (see plan D8: the async forms let the event loop yield between chunks).
|
|
20
|
+
*/
|
|
21
|
+
import { zip, zipSync, unzip, unzipSync } from 'fflate';
|
|
22
|
+
/** Default compression level used by the sync/async writers. */
|
|
23
|
+
export const DEFAULT_ZIP_LEVEL = 6;
|
|
24
|
+
/**
|
|
25
|
+
* Default cap on the number of entries a single read materialises. Deliberately
|
|
26
|
+
* generous: loading a project container is not the same magnitude as a user
|
|
27
|
+
* picking an arbitrary file, and container members (byte-exact source shadows,
|
|
28
|
+
* baked `.brp` payloads) scale with the source document.
|
|
29
|
+
*
|
|
30
|
+
* NOTE these caps are *post-decompression* checks — `unzipSync` has already
|
|
31
|
+
* materialised the archive when they run, so they bound what a caller keeps
|
|
32
|
+
* and walks, not peak allocation. They are a resource budget, NOT a
|
|
33
|
+
* zip-bomb defence. Pre-decompression rejection would need fflate's
|
|
34
|
+
* `filter` (per-entry `originalSize` accounting) and is tracked separately.
|
|
35
|
+
*/
|
|
36
|
+
export const DEFAULT_MAX_ENTRIES = 9999;
|
|
37
|
+
/** Default cap on total uncompressed bytes; same post-decompression caveat as {@link DEFAULT_MAX_ENTRIES}. */
|
|
38
|
+
export const DEFAULT_MAX_TOTAL_BYTES = 512 * 1024 * 1024;
|
|
39
|
+
function toBytes(data) {
|
|
40
|
+
return data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
41
|
+
}
|
|
42
|
+
function resolveReadOptions(opts) {
|
|
43
|
+
return {
|
|
44
|
+
maxEntries: opts.maxEntries ?? DEFAULT_MAX_ENTRIES,
|
|
45
|
+
maxTotalBytes: opts.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Strip directory entries (keys ending in `/`) and enforce size/entry caps. */
|
|
49
|
+
function normalizeEntries(raw, opts) {
|
|
50
|
+
const out = new Map();
|
|
51
|
+
let totalBytes = 0;
|
|
52
|
+
for (const key of Object.keys(raw)) {
|
|
53
|
+
if (key.endsWith('/'))
|
|
54
|
+
continue;
|
|
55
|
+
const body = raw[key];
|
|
56
|
+
totalBytes += body.byteLength;
|
|
57
|
+
if (totalBytes > opts.maxTotalBytes) {
|
|
58
|
+
throw new Error(`zip read failed: content exceeds limit (maxTotalBytes ${opts.maxTotalBytes})`);
|
|
59
|
+
}
|
|
60
|
+
out.set(key, body);
|
|
61
|
+
}
|
|
62
|
+
if (out.size > opts.maxEntries) {
|
|
63
|
+
throw new Error(`zip read failed: content exceeds limit (maxEntries ${opts.maxEntries})`);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
function wrapReadError(err) {
|
|
68
|
+
const inner = err instanceof Error ? err.message : String(err);
|
|
69
|
+
const e = new Error(`zip read failed: ${inner}`);
|
|
70
|
+
e.cause = err;
|
|
71
|
+
throw e;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Unzip bytes to an entry table (directory entries filtered).
|
|
75
|
+
*
|
|
76
|
+
* @param data - the ZIP bytes to read (Uint8Array or ArrayBuffer).
|
|
77
|
+
* @param opts - optional read caps (maxEntries / maxTotalBytes).
|
|
78
|
+
* @returns a map of archive path -> decompressed bytes.
|
|
79
|
+
* @throws on non-ZIP bytes or when caps are exceeded.
|
|
80
|
+
*/
|
|
81
|
+
export function readZipEntries(data, opts = {}) {
|
|
82
|
+
let raw;
|
|
83
|
+
try {
|
|
84
|
+
raw = unzipSync(toBytes(data));
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
wrapReadError(err);
|
|
88
|
+
}
|
|
89
|
+
return normalizeEntries(raw, resolveReadOptions(opts));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Zip an entry table into bytes.
|
|
93
|
+
*
|
|
94
|
+
* @param entries - archive path -> bytes to store.
|
|
95
|
+
* @param opts - optional compression level / ZIP comment.
|
|
96
|
+
* @returns the ZIP bytes.
|
|
97
|
+
* @throws on an empty entry table.
|
|
98
|
+
*/
|
|
99
|
+
export function writeZipEntries(entries, opts) {
|
|
100
|
+
if (Object.keys(entries).length === 0) {
|
|
101
|
+
throw new Error('zip write failed: empty entry table');
|
|
102
|
+
}
|
|
103
|
+
return zipSync(entries, { level: opts?.level ?? DEFAULT_ZIP_LEVEL, comment: opts?.comment });
|
|
104
|
+
}
|
|
105
|
+
/** Async read: yields to the event loop between chunks (see plan §D8).
|
|
106
|
+
*
|
|
107
|
+
* @param data - the ZIP bytes to read (Uint8Array or ArrayBuffer).
|
|
108
|
+
* @param opts - optional read caps (maxEntries / maxTotalBytes).
|
|
109
|
+
* @returns a promise of the entry map.
|
|
110
|
+
*/
|
|
111
|
+
export function readZipEntriesAsync(data, opts = {}) {
|
|
112
|
+
return new Promise((resolve, reject) => {
|
|
113
|
+
unzip(toBytes(data), (err, raw) => {
|
|
114
|
+
if (err) {
|
|
115
|
+
reject(new Error(`zip read failed: ${err.message}`));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
resolve(normalizeEntries(raw, resolveReadOptions(opts)));
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
reject(e);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/** Zip an entry table into bytes, yielding between chunks.
|
|
128
|
+
*
|
|
129
|
+
* @param entries - archive path -> entry to store.
|
|
130
|
+
* @param opts - optional compression level / ZIP comment.
|
|
131
|
+
* @returns a promise of the ZIP bytes.
|
|
132
|
+
*/
|
|
133
|
+
export function writeZipEntriesAsync(entries, opts) {
|
|
134
|
+
if (Object.keys(entries).length === 0) {
|
|
135
|
+
return Promise.reject(new Error('zip write failed: empty entry table'));
|
|
136
|
+
}
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
zip(entries, { level: opts?.level ?? DEFAULT_ZIP_LEVEL, comment: opts?.comment }, (err, out) => {
|
|
139
|
+
if (err) {
|
|
140
|
+
reject(new Error(`zip write failed: ${err.message}`));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
resolve(out);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=zip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.js","sourceRoot":"","sources":["../../src/io/zip.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * io/zip — the single ZIP read/write entry for every faijs consumer.\n *\n * This is the one place faijs (and the host) reads and writes ZIP bytes. The\n * plan unifies two previously-divergent behaviours: reading uses fflate's\n * `unzipSync`, writing uses `zipSync`. Both surface as a plain entry map so\n * no caller ever touches fflate's `Unzlib` / `Zip` objects directly.\n *\n * Contract:\n * - Entries are keyed by the archive path (fflate normalises to forward\n * slashes). Directory entries (keys ending in `/`) are filtered out — they\n * are produced by fflate and are not data.\n * - Every function throws on failure; there is no degraded return value.\n * - A non-zip buffer throws `new Error('zip read failed: <msg>')`.\n * - `writeZipEntries` rejects an empty entry table (never produces an empty zip).\n *\n * Environment: plain pure functions usable in node, browser, worker and the\n * weapp worker — fflate's sync + async (callback) forms cover all of them\n * (see plan D8: the async forms let the event loop yield between chunks).\n */\nimport { zip, zipSync, unzip, unzipSync } from 'fflate'\n\n/** fflate's valid compression levels. */\nexport type ZipLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\n\n/** Default compression level used by the sync/async writers. */\nexport const DEFAULT_ZIP_LEVEL: ZipLevel = 6\n\n/** Read-side caps bounding what a single read materialises. */\nexport interface ZipReadOptions {\n /** Max entry count; default `DEFAULT_MAX_ENTRIES` (9999). */\n maxEntries?: number\n /** Max total uncompressed bytes; default `DEFAULT_MAX_TOTAL_BYTES` (512 MiB). */\n maxTotalBytes?: number\n}\n\ntype RequiredReadOptions = Required<ZipReadOptions>\n\n/**\n * Default cap on the number of entries a single read materialises. Deliberately\n * generous: loading a project container is not the same magnitude as a user\n * picking an arbitrary file, and container members (byte-exact source shadows,\n * baked `.brp` payloads) scale with the source document.\n *\n * NOTE these caps are *post-decompression* checks — `unzipSync` has already\n * materialised the archive when they run, so they bound what a caller keeps\n * and walks, not peak allocation. They are a resource budget, NOT a\n * zip-bomb defence. Pre-decompression rejection would need fflate's\n * `filter` (per-entry `originalSize` accounting) and is tracked separately.\n */\nexport const DEFAULT_MAX_ENTRIES = 9999\n\n/** Default cap on total uncompressed bytes; same post-decompression caveat as {@link DEFAULT_MAX_ENTRIES}. */\nexport const DEFAULT_MAX_TOTAL_BYTES = 512 * 1024 * 1024\n\nfunction toBytes(data: Uint8Array | ArrayBuffer): Uint8Array {\n return data instanceof Uint8Array ? data : new Uint8Array(data)\n}\n\nfunction resolveReadOptions(opts: ZipReadOptions): RequiredReadOptions {\n return {\n maxEntries: opts.maxEntries ?? DEFAULT_MAX_ENTRIES,\n maxTotalBytes: opts.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES,\n }\n}\n\n/** Strip directory entries (keys ending in `/`) and enforce size/entry caps. */\nfunction normalizeEntries(\n raw: Record<string, Uint8Array>,\n opts: RequiredReadOptions,\n): Map<string, Uint8Array> {\n const out = new Map<string, Uint8Array>()\n let totalBytes = 0\n for (const key of Object.keys(raw)) {\n if (key.endsWith('/')) continue\n const body = raw[key]\n totalBytes += body.byteLength\n if (totalBytes > opts.maxTotalBytes) {\n throw new Error(\n `zip read failed: content exceeds limit (maxTotalBytes ${opts.maxTotalBytes})`,\n )\n }\n out.set(key, body)\n }\n if (out.size > opts.maxEntries) {\n throw new Error(`zip read failed: content exceeds limit (maxEntries ${opts.maxEntries})`)\n }\n return out\n}\n\nfunction wrapReadError(err: unknown): never {\n const inner = err instanceof Error ? err.message : String(err)\n const e = new Error(`zip read failed: ${inner}`)\n ;(e as Error & { cause?: unknown }).cause = err\n throw e\n}\n\n/**\n * Unzip bytes to an entry table (directory entries filtered).\n *\n * @param data - the ZIP bytes to read (Uint8Array or ArrayBuffer).\n * @param opts - optional read caps (maxEntries / maxTotalBytes).\n * @returns a map of archive path -> decompressed bytes.\n * @throws on non-ZIP bytes or when caps are exceeded.\n */\nexport function readZipEntries(\n data: Uint8Array | ArrayBuffer,\n opts: ZipReadOptions = {},\n): Map<string, Uint8Array> {\n let raw: Record<string, Uint8Array>\n try {\n raw = unzipSync(toBytes(data))\n } catch (err) {\n wrapReadError(err)\n }\n return normalizeEntries(raw, resolveReadOptions(opts))\n}\n\ntype EntryTable = Record<string, Uint8Array>\n\n/** Write-side options (compression level + advisory ZIP comment). */\nexport interface ZipWriteOptions {\n /** Compression level; default `DEFAULT_ZIP_LEVEL` (6). */\n level?: ZipLevel\n /** Optional ZIP comment (advisory — consumers read it via the EOCD record). */\n comment?: string\n}\n\n/**\n * Zip an entry table into bytes.\n *\n * @param entries - archive path -> bytes to store.\n * @param opts - optional compression level / ZIP comment.\n * @returns the ZIP bytes.\n * @throws on an empty entry table.\n */\nexport function writeZipEntries(entries: EntryTable, opts?: ZipWriteOptions): Uint8Array {\n if (Object.keys(entries).length === 0) {\n throw new Error('zip write failed: empty entry table')\n }\n return zipSync(entries, { level: opts?.level ?? DEFAULT_ZIP_LEVEL, comment: opts?.comment })\n}\n\n/** Async read: yields to the event loop between chunks (see plan §D8).\n *\n * @param data - the ZIP bytes to read (Uint8Array or ArrayBuffer).\n * @param opts - optional read caps (maxEntries / maxTotalBytes).\n * @returns a promise of the entry map.\n */\nexport function readZipEntriesAsync(\n data: Uint8Array | ArrayBuffer,\n opts: ZipReadOptions = {},\n): Promise<Map<string, Uint8Array>> {\n return new Promise((resolve, reject) => {\n unzip(toBytes(data), (err, raw) => {\n if (err) {\n reject(new Error(`zip read failed: ${err.message}`))\n return\n }\n try {\n resolve(normalizeEntries(raw, resolveReadOptions(opts)))\n } catch (e) {\n reject(e)\n }\n })\n })\n}\n\n/** Zip an entry table into bytes, yielding between chunks.\n *\n * @param entries - archive path -> entry to store.\n * @param opts - optional compression level / ZIP comment.\n * @returns a promise of the ZIP bytes.\n */\nexport function writeZipEntriesAsync(\n entries: EntryTable,\n opts?: ZipWriteOptions,\n): Promise<Uint8Array> {\n if (Object.keys(entries).length === 0) {\n return Promise.reject(new Error('zip write failed: empty entry table'))\n }\n return new Promise((resolve, reject) => {\n zip(entries, { level: opts?.level ?? DEFAULT_ZIP_LEVEL, comment: opts?.comment }, (err, out) => {\n if (err) {\n reject(new Error(`zip write failed: ${err.message}`))\n return\n }\n resolve(out)\n })\n })\n}"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* code-to-args — 单语句行 args 提取(编辑回填配套)
|
|
3
3
|
*
|
|
4
|
-
* See docs/
|
|
4
|
+
* See docs/language-design.md §3 (statement model ↔ StatementSummary mapping) and §6.4 (check).
|
|
5
5
|
*
|
|
6
6
|
* 宿主编辑回填(FeatureEditor.backfill / editStatement)需要从代码行
|
|
7
7
|
* 反提参数对象。此能力由 faijs 标配提供(与 parse 语义一致),
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* 不得把折叠值写回源码(会丢失原表达式)。
|
|
20
20
|
*/
|
|
21
21
|
import type { HostArg } from './host-arg.js';
|
|
22
|
+
import { type OpDimMap } from './metadata-extractor.js';
|
|
23
|
+
import type { DimName, UnitName } from '../units.js';
|
|
22
24
|
/**
|
|
23
25
|
* `codeToArgs` 的返回契约:位置实参槽 + 尾随选项对象(HostArg 形态,纯数据无 IR)。
|
|
24
26
|
*/
|
|
@@ -26,6 +28,16 @@ export interface CodeToArgsResult {
|
|
|
26
28
|
positional: HostArg[];
|
|
27
29
|
args: Record<string, HostArg>;
|
|
28
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* codeToArgs 选项。`opDims` 为 P4/P6 (unit-system D8) 透传:callee → 量纲声明,
|
|
33
|
+
* 供单行回填路径的 dimension pass 消费(P6 落地前声明面透传即可,不影响解析结果)。
|
|
34
|
+
*/
|
|
35
|
+
export interface CodeToArgsOptions {
|
|
36
|
+
/** 该脚本顶层 import 的绑定名(F2)。 */
|
|
37
|
+
namespaces?: string[];
|
|
38
|
+
/** callee → 量纲声明(unit-system D8,P6 消费)。 */
|
|
39
|
+
opDims?: OpDimMap;
|
|
40
|
+
}
|
|
29
41
|
/**
|
|
30
42
|
* 解析单条语句行,提取其位置实参槽与选项对象(序列化形态,无 IR 变体语义)。
|
|
31
43
|
*
|
|
@@ -52,7 +64,21 @@ export interface CodeToArgsResult {
|
|
|
52
64
|
* serialized JSON form).
|
|
53
65
|
* @throws ParseError — 行文本不是合法语句时抛出(含行号)
|
|
54
66
|
*/
|
|
55
|
-
export declare function codeToArgs(codeLine: string, opts?:
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
export declare function codeToArgs(codeLine: string, opts?: CodeToArgsOptions): CodeToArgsResult;
|
|
68
|
+
/**
|
|
69
|
+
* Parse a unit literal text expression (`n * UNIT`) into its base-unit value.
|
|
70
|
+
*
|
|
71
|
+
* P7/D10.3: This is the reverse of `formatUnitLiteral`. Given text like
|
|
72
|
+
* `10 * INCH`, returns `{ base: 254, dim: 'length', unitName: 'inch' }`.
|
|
73
|
+
* Non-unit-literal expressions return `null` (host decides whether to
|
|
74
|
+
* downgrade to read-only).
|
|
75
|
+
*
|
|
76
|
+
* @param text - the expression text (e.g. `10 * INCH` or `0.5 * DEGREE`).
|
|
77
|
+
* @returns the parsed unit literal info, or `null` if not a unit literal.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseUnitLiteral(text: string): {
|
|
80
|
+
base: number;
|
|
81
|
+
dim: DimName;
|
|
82
|
+
unitName: UnitName;
|
|
83
|
+
} | null;
|
|
58
84
|
//# sourceMappingURL=code-to-args.d.ts.map
|