@bldrs-ai/conway 1.413.1255 → 1.417.1262

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.
Files changed (40) hide show
  1. package/compiled/examples/browser-bundled.cjs +1 -1
  2. package/compiled/examples/cli-bundled.cjs +194 -227
  3. package/compiled/examples/cli-step-bundled.cjs +1 -1
  4. package/compiled/examples/validator-bundled.cjs +1 -1
  5. package/compiled/src/compat/web-ifc/ifc_api.d.ts +20 -0
  6. package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
  7. package/compiled/src/compat/web-ifc/ifc_api.js +29 -0
  8. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +16 -0
  9. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
  10. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +29 -0
  11. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +40 -0
  12. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  13. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +106 -0
  14. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts +2 -0
  15. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts.map +1 -0
  16. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.js +100 -0
  17. package/compiled/src/ifc/ifc_demand_extraction.test.d.ts +2 -0
  18. package/compiled/src/ifc/ifc_demand_extraction.test.d.ts.map +1 -0
  19. package/compiled/src/ifc/ifc_demand_extraction.test.js +111 -0
  20. package/compiled/src/ifc/ifc_geometry_extraction.d.ts +47 -0
  21. package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
  22. package/compiled/src/ifc/ifc_geometry_extraction.js +223 -269
  23. package/compiled/src/ifc/ifc_stream_open.d.ts +68 -0
  24. package/compiled/src/ifc/ifc_stream_open.d.ts.map +1 -0
  25. package/compiled/src/ifc/ifc_stream_open.js +46 -0
  26. package/compiled/src/ifc/ifc_stream_open.test.d.ts +2 -0
  27. package/compiled/src/ifc/ifc_stream_open.test.d.ts.map +1 -0
  28. package/compiled/src/ifc/ifc_stream_open.test.js +63 -0
  29. package/compiled/src/ifc/ifc_tile_extractor.d.ts +84 -0
  30. package/compiled/src/ifc/ifc_tile_extractor.d.ts.map +1 -0
  31. package/compiled/src/ifc/ifc_tile_extractor.js +134 -0
  32. package/compiled/src/ifc/ifc_tile_extractor.test.d.ts +2 -0
  33. package/compiled/src/ifc/ifc_tile_extractor.test.d.ts.map +1 -0
  34. package/compiled/src/ifc/ifc_tile_extractor.test.js +118 -0
  35. package/compiled/src/index.d.ts +14 -0
  36. package/compiled/src/index.d.ts.map +1 -1
  37. package/compiled/src/index.js +16 -0
  38. package/compiled/src/version/version.js +1 -1
  39. package/compiled/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +1 -1
@@ -0,0 +1,63 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // Phase B3: the release-facing streamed open — fixed-memory columnar parse
3
+ // over a ByteSource, model over a windowed store, columns exposed for the
4
+ // revisit sidecar — behaves like a resident open for reads once ranges are
5
+ // resident.
6
+ import * as fs from "fs";
7
+ import { beforeAll, describe, expect, test } from "@jest/globals";
8
+ import ParsingBuffer from "../parsing/parsing_buffer.js";
9
+ import IfcStepParser from "./ifc_step_parser.js";
10
+ import { openStreamedIfcModel } from "./ifc_stream_open.js";
11
+ import { BufferByteSource } from "../step/parsing/byte_source.js";
12
+ import { InMemoryStepByteStore } from "../step/step_buffer_provider.js";
13
+ import { ParseResult } from "../step/parsing/step_parser.js";
14
+ import { hashSource, serializeIndexSidecarFromColumns, deserializeIndexSidecarToColumns, sidecarMatchesSource, } from "../step/parsing/index_sidecar.js";
15
+ import { IfcRoot } from "./ifc4_gen/index.js";
16
+ let bytes;
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ let residentModel;
19
+ beforeAll(() => {
20
+ bytes = new Uint8Array(fs.readFileSync("data/index.ifc"));
21
+ const input = new ParsingBuffer(bytes);
22
+ IfcStepParser.Instance.parseHeader(input);
23
+ residentModel = IfcStepParser.Instance.parseDataToModel(input)[1];
24
+ });
25
+ describe("openStreamedIfcModel (Phase B3)", () => {
26
+ test("opens a model matching the resident parse, with header and columns", () => {
27
+ const open = openStreamedIfcModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes), { pool: 4 * 1024 });
28
+ expect(open.result).toBe(ParseResult.COMPLETE);
29
+ expect(open.model).toBeDefined();
30
+ expect(open.header.headers.size).toBeGreaterThan(0);
31
+ expect(open.columns.firstInlineElement).toBeGreaterThan(0);
32
+ const streamedRoots = new Set(open.model.expressIDsOfTypes(IfcRoot));
33
+ const residentRoots = new Set(residentModel.expressIDsOfTypes(IfcRoot));
34
+ expect(streamedRoots).toEqual(residentRoots);
35
+ });
36
+ test("reads work after ensureResident (the windowed contract)", async () => {
37
+ const open = openStreamedIfcModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes));
38
+ const model = open.model;
39
+ const expressID = [...model.expressIDsOfTypes(IfcRoot)][0];
40
+ await model.ensureResidentByExpressID(expressID);
41
+ const element = model.getElementByExpressID(expressID);
42
+ expect(element?.expressID).toBe(expressID);
43
+ });
44
+ test("record events fire live during the open", () => {
45
+ let events = 0;
46
+ openStreamedIfcModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes), { onRecordIndexed: () => void ++events });
47
+ expect(events).toBe(openStreamedIfcModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes)).columns.firstInlineElement);
48
+ });
49
+ test("the returned columns serialize to a trustable revisit sidecar", () => {
50
+ const open = openStreamedIfcModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes));
51
+ const hash = hashSource(bytes);
52
+ const sidecar = serializeIndexSidecarFromColumns(open.columns, bytes.byteLength, hash);
53
+ const restored = deserializeIndexSidecarToColumns(sidecar);
54
+ expect(sidecarMatchesSource(
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ restored, bytes.byteLength, hash)).toBe(true);
57
+ expect(restored.columns.count).toBe(open.columns.firstInlineElement);
58
+ });
59
+ test("rejects a store whose length disagrees with the source", () => {
60
+ expect(() => openStreamedIfcModel(new BufferByteSource(bytes), new InMemoryStepByteStore(bytes.subarray(0, 100))))
61
+ .toThrow(/does not match/);
62
+ });
63
+ });
@@ -0,0 +1,84 @@
1
+ import { GeometryTilePoolBindings, TileAssetExtractor } from "../core/geometry_tile_bindings.js";
2
+ import { GeometryAsset } from "../core/geometry_tile_pool.js";
3
+ import { IfcGeometryExtraction } from "./ifc_geometry_extraction.js";
4
+ /**
5
+ * The wasm module surface the extractor commits through: the tile pool
6
+ * bindings plus the Geometry-taking commit (embind `commitGeometryTile`,
7
+ * which serialises a reified Geometry's payload straight into pool chunks).
8
+ */
9
+ export interface TileCommitBindings extends GeometryTilePoolBindings {
10
+ /**
11
+ * Commit a reified geometry's payload into the wasm tile pool.
12
+ *
13
+ * @param assetID The tile's asset id.
14
+ * @param geometry The wasm Geometry object (reified on access).
15
+ * @return {boolean} True on success.
16
+ */
17
+ commitGeometryTile(assetID: number, geometry: unknown): boolean;
18
+ }
19
+ /**
20
+ * The production {@link TileAssetExtractor} (Phase B3): drives the
21
+ * per-product demand extraction seam (Phase B2) and commits the resulting
22
+ * meshes into the wasm tile pool.
23
+ *
24
+ * Asset identity: one asset per produced **mesh**, keyed by the mesh's
25
+ * localID (the representation item). Mapped items reuse representation
26
+ * geometry across products, so shared representations become shared assets —
27
+ * the sharing the pools refcount.
28
+ *
29
+ * Contract notes:
30
+ * - `assetsOf` runs the (expensive) per-product extraction on first call and
31
+ * caches the asset list; sizes are exact reified byte costs, so the TS
32
+ * accounting layer admits with real numbers. This front-loads cost into
33
+ * `assetsOf` by design — see `GeometryTilePool.extract`'s pricing pass.
34
+ * - `materialize` commits an already-extracted mesh into the pool;
35
+ * `discard` releases the wasm tile. The CPU-side canonical mesh is left in
36
+ * place in this phase (serving uploads from tiles — and dropping the fat
37
+ * working geometry — is the Phase C flip).
38
+ */
39
+ export declare class IfcTileAssetExtractor implements TileAssetExtractor {
40
+ private readonly extraction_;
41
+ private readonly bindings_;
42
+ /** Product localID → its assets, cached after first extraction. */
43
+ private readonly assetsByProduct_;
44
+ /**
45
+ * @param extraction_ The geometry extraction (its model provides meshes).
46
+ * @param bindings_ The wasm tile pool surface to commit through.
47
+ */
48
+ constructor(extraction_: IfcGeometryExtraction, bindings_: TileCommitBindings);
49
+ /**
50
+ * The assets (meshes) a product references, extracting it on first ask.
51
+ *
52
+ * Attribution walks the product's **representation-item closure**
53
+ * (recursing through mapped items into their shared source
54
+ * representations) and claims every item that has an extracted mesh —
55
+ * NOT a before/after diff of the mesh set. The distinction is the
56
+ * mapped-item case: a shared source's meshes already exist when the
57
+ * second product asks, so a diff would omit them and its tile would not
58
+ * hold references to geometry it renders. Closure attribution is
59
+ * extraction-order independent.
60
+ *
61
+ * @param productLocalID The product's local ID.
62
+ * @return {GeometryAsset<number>[]} One asset per referenced mesh, keyed
63
+ * by the mesh's representation-item localID (shared across products for
64
+ * mapped sources), sized at exact reified cost.
65
+ */
66
+ assetsOf(productLocalID: number): GeometryAsset<number>[];
67
+ /**
68
+ * The localIDs of every representation item in a product's Body /
69
+ * Facetation representations, recursing through mapped items into their
70
+ * (shared) source representations — the key space extraction stores
71
+ * meshes under.
72
+ *
73
+ * @param productLocalID The product's local ID.
74
+ * @return {Set<number>} The representation-item localIDs.
75
+ */
76
+ private representationItemIDs_;
77
+ /**
78
+ * Commit one extracted mesh into the wasm tile pool.
79
+ *
80
+ * @param assetID The mesh (representation item) localID.
81
+ */
82
+ extractIntoTile(assetID: number): void;
83
+ }
84
+ //# sourceMappingURL=ifc_tile_extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ifc_tile_extractor.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_tile_extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AAGjE;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,wBAAwB;IAElE;;;;;;OAMG;IACH,kBAAkB,CAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAI,OAAO,CAAA;CAClE;AAUD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAU5D,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAT5B,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6C;IAE9E;;;OAGG;gBAEgB,WAAW,EAAE,qBAAqB,EAClC,SAAS,EAAE,kBAAkB;IAKhD;;;;;;;;;;;;;;;;OAgBG;IACI,QAAQ,CAAE,cAAc,EAAE,MAAM,GAAI,aAAa,CAAC,MAAM,CAAC,EAAE;IAqClE;;;;;;;;OAQG;IACH,OAAO,CAAC,sBAAsB;IA0C9B;;;;OAIG;IACI,eAAe,CAAE,OAAO,EAAE,MAAM,GAAI,IAAI;CAiBhD"}
@@ -0,0 +1,134 @@
1
+ // Reified payload framing: 8-byte header + float vertex data + u32 indices
2
+ // (tile_pool_api.h layout).
3
+ const TILE_HEADER_BYTES = 8;
4
+ const FLOAT_BYTES = 4;
5
+ const INDEX_BYTES = 4;
6
+ /**
7
+ * The production {@link TileAssetExtractor} (Phase B3): drives the
8
+ * per-product demand extraction seam (Phase B2) and commits the resulting
9
+ * meshes into the wasm tile pool.
10
+ *
11
+ * Asset identity: one asset per produced **mesh**, keyed by the mesh's
12
+ * localID (the representation item). Mapped items reuse representation
13
+ * geometry across products, so shared representations become shared assets —
14
+ * the sharing the pools refcount.
15
+ *
16
+ * Contract notes:
17
+ * - `assetsOf` runs the (expensive) per-product extraction on first call and
18
+ * caches the asset list; sizes are exact reified byte costs, so the TS
19
+ * accounting layer admits with real numbers. This front-loads cost into
20
+ * `assetsOf` by design — see `GeometryTilePool.extract`'s pricing pass.
21
+ * - `materialize` commits an already-extracted mesh into the pool;
22
+ * `discard` releases the wasm tile. The CPU-side canonical mesh is left in
23
+ * place in this phase (serving uploads from tiles — and dropping the fat
24
+ * working geometry — is the Phase C flip).
25
+ */
26
+ export class IfcTileAssetExtractor {
27
+ /**
28
+ * @param extraction_ The geometry extraction (its model provides meshes).
29
+ * @param bindings_ The wasm tile pool surface to commit through.
30
+ */
31
+ constructor(extraction_, bindings_) {
32
+ this.extraction_ = extraction_;
33
+ this.bindings_ = bindings_;
34
+ /** Product localID → its assets, cached after first extraction. */
35
+ this.assetsByProduct_ = new Map();
36
+ this.extraction_.prepareDemandExtraction();
37
+ }
38
+ /**
39
+ * The assets (meshes) a product references, extracting it on first ask.
40
+ *
41
+ * Attribution walks the product's **representation-item closure**
42
+ * (recursing through mapped items into their shared source
43
+ * representations) and claims every item that has an extracted mesh —
44
+ * NOT a before/after diff of the mesh set. The distinction is the
45
+ * mapped-item case: a shared source's meshes already exist when the
46
+ * second product asks, so a diff would omit them and its tile would not
47
+ * hold references to geometry it renders. Closure attribution is
48
+ * extraction-order independent.
49
+ *
50
+ * @param productLocalID The product's local ID.
51
+ * @return {GeometryAsset<number>[]} One asset per referenced mesh, keyed
52
+ * by the mesh's representation-item localID (shared across products for
53
+ * mapped sources), sized at exact reified cost.
54
+ */
55
+ assetsOf(productLocalID) {
56
+ const cached = this.assetsByProduct_.get(productLocalID);
57
+ if (cached !== void 0) {
58
+ return cached;
59
+ }
60
+ this.extraction_.extractProductGeometryByLocalID(productLocalID);
61
+ const geometry = this.extraction_.model.geometry;
62
+ const assets = [];
63
+ for (const itemLocalID of this.representationItemIDs_(productLocalID)) {
64
+ const mesh = geometry.getByLocalID(itemLocalID);
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ const wasmGeometry = mesh?.geometry;
67
+ if (wasmGeometry === void 0 ||
68
+ typeof wasmGeometry.GetVertexDataSize !== 'function') {
69
+ continue;
70
+ }
71
+ const byteSize = TILE_HEADER_BYTES +
72
+ wasmGeometry.GetVertexDataSize() * FLOAT_BYTES +
73
+ wasmGeometry.GetIndexDataSize() * INDEX_BYTES;
74
+ assets.push({ assetID: itemLocalID, byteSize });
75
+ }
76
+ this.assetsByProduct_.set(productLocalID, assets);
77
+ return assets;
78
+ }
79
+ /**
80
+ * The localIDs of every representation item in a product's Body /
81
+ * Facetation representations, recursing through mapped items into their
82
+ * (shared) source representations — the key space extraction stores
83
+ * meshes under.
84
+ *
85
+ * @param productLocalID The product's local ID.
86
+ * @return {Set<number>} The representation-item localIDs.
87
+ */
88
+ representationItemIDs_(productLocalID) {
89
+ const ids = new Set();
90
+ const element = this.extraction_.model.getElementByLocalID(productLocalID);
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ const representations = element?.Representation?.Representations;
93
+ if (representations === void 0 || representations === null) {
94
+ return ids;
95
+ }
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ const addItems = (items) => {
98
+ for (const item of items) {
99
+ ids.add(item.localID);
100
+ // Mapped item: recurse into the shared source representation.
101
+ const source = item.MappingSource?.MappedRepresentation?.Items;
102
+ if (source !== void 0 && source !== null) {
103
+ addItems(source);
104
+ }
105
+ }
106
+ };
107
+ for (const representation of representations) {
108
+ const identifier = representation.RepresentationIdentifier;
109
+ if (identifier !== null && identifier !== 'Body' &&
110
+ identifier !== 'Facetation') {
111
+ continue;
112
+ }
113
+ addItems(representation.Items);
114
+ }
115
+ return ids;
116
+ }
117
+ /**
118
+ * Commit one extracted mesh into the wasm tile pool.
119
+ *
120
+ * @param assetID The mesh (representation item) localID.
121
+ */
122
+ extractIntoTile(assetID) {
123
+ const mesh = this.extraction_.model.geometry.getByLocalID(assetID);
124
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
125
+ const wasmGeometry = mesh?.geometry;
126
+ if (wasmGeometry === void 0) {
127
+ throw new Error(`No extracted mesh for asset ${assetID}`);
128
+ }
129
+ if (!this.bindings_.commitGeometryTile(assetID, wasmGeometry)) {
130
+ throw new Error(`Wasm tile commit failed for asset ${assetID} — ` +
131
+ 'the scheduler budget must not exceed the pool budget');
132
+ }
133
+ }
134
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ifc_tile_extractor.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ifc_tile_extractor.test.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_tile_extractor.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,118 @@
1
+ /* eslint-disable no-magic-numbers, @typescript-eslint/no-explicit-any */
2
+ // Phase B3: the production TileAssetExtractor drives the per-product demand
3
+ // seam (B2) and commits reified meshes through the wasm tile surface —
4
+ // verified with real extraction and recording commit bindings, composed all
5
+ // the way up through the queue + pump.
6
+ import fs from "fs";
7
+ import { beforeAll, describe, expect, test } from "@jest/globals";
8
+ import { IfcGeometryExtraction } from "./ifc_geometry_extraction.js";
9
+ import { IfcTileAssetExtractor } from "./ifc_tile_extractor.js";
10
+ import { ParseResult } from "../step/parsing/step_parser.js";
11
+ import IfcStepParser from "./ifc_step_parser.js";
12
+ import ParsingBuffer from "../parsing/parsing_buffer.js";
13
+ import { ConwayGeometry } from "../../dependencies/conway-geom/index.js";
14
+ import { createWasmTileBackend } from "../core/geometry_tile_bindings.js";
15
+ import { DemandGeometryQueue } from "../core/demand_geometry_queue.js";
16
+ import { DemandResidencyPump } from "../core/demand_residency_pump.js";
17
+ import { IfcProduct } from "./ifc4_gen/index.js";
18
+ let conwayGeometry;
19
+ /**
20
+ * @return {IfcStepModel} A fresh parsed model of index.ifc.
21
+ */
22
+ function freshModel() {
23
+ const bytes = fs.readFileSync("data/index.ifc");
24
+ const input = new ParsingBuffer(bytes);
25
+ expect(IfcStepParser.Instance.parseHeader(input)[1]).toBe(ParseResult.COMPLETE);
26
+ const [, model] = IfcStepParser.Instance.parseDataToModel(input);
27
+ return model;
28
+ }
29
+ /**
30
+ * Recording fake of the commit surface: accepts every init/commit/release,
31
+ * records ids, verifies commit receives a live reified geometry.
32
+ *
33
+ * @return {object} `{ bindings, committed, released }`.
34
+ */
35
+ function recordingBindings() {
36
+ const committed = [];
37
+ const released = [];
38
+ const bindings = {
39
+ initGeometryTilePool: () => true,
40
+ geometryTilePoolInitialized: () => true,
41
+ commitGeometryTile: (assetID, geometry) => {
42
+ // A real reified geometry must be handed over.
43
+ expect(typeof geometry.GetVertexDataSize).toBe("function");
44
+ expect(geometry.GetVertexDataSize()).toBeGreaterThan(0);
45
+ committed.push(assetID);
46
+ return true;
47
+ },
48
+ commitGeometryTileBytes: () => true,
49
+ retainGeometryTile: () => true,
50
+ releaseGeometryTile: (assetID) => {
51
+ released.push(assetID);
52
+ return true;
53
+ },
54
+ geometryTileResident: (assetID) => committed.includes(assetID) && !released.includes(assetID),
55
+ geometryTileRefCount: () => 1,
56
+ geometryTileByteSize: () => 0,
57
+ geometryTileSegmentCount: () => 0,
58
+ geometryTileSegmentAddress: () => 0,
59
+ geometryTileSegmentByteLength: () => 0,
60
+ geometryTileVertexByteLength: () => 0,
61
+ geometryTileIndexByteLength: () => 0,
62
+ geometryTilePoolBytesInUse: () => 0,
63
+ geometryTilePoolTotalBytes: () => 0,
64
+ geometryTilePoolFreeChunks: () => 0,
65
+ geometryTilePoolFailedCommits: () => 0,
66
+ };
67
+ return { bindings, committed, released };
68
+ }
69
+ beforeAll(async () => {
70
+ conwayGeometry = new ConwayGeometry();
71
+ expect(await conwayGeometry.initialize()).toBe(true);
72
+ });
73
+ describe("IfcTileAssetExtractor (Phase B3)", () => {
74
+ test("assetsOf extracts on first ask, caches, and sizes at reified cost", () => {
75
+ const model = freshModel();
76
+ const extraction = new IfcGeometryExtraction(conwayGeometry, model);
77
+ const { bindings } = recordingBindings();
78
+ const extractor = new IfcTileAssetExtractor(extraction, bindings);
79
+ // Find a product with geometry.
80
+ let assets = [];
81
+ let productID = -1;
82
+ for (const product of model.types(IfcProduct)) {
83
+ assets = extractor.assetsOf(product.localID);
84
+ if (assets.length > 0) {
85
+ productID = product.localID;
86
+ break;
87
+ }
88
+ }
89
+ expect(assets.length).toBeGreaterThan(0);
90
+ for (const asset of assets) {
91
+ expect(asset.byteSize).toBeGreaterThan(8); // header + payload
92
+ }
93
+ // Cached: second ask returns the same array without re-extraction.
94
+ expect(extractor.assetsOf(productID)).toBe(assets);
95
+ });
96
+ test("full composition: pump \u2192 queue \u2192 tiles \u2192 extractor \u2192 wasm commit", async () => {
97
+ const model = freshModel();
98
+ const extraction = new IfcGeometryExtraction(conwayGeometry, model);
99
+ const { bindings, committed, released } = recordingBindings();
100
+ const extractor = new IfcTileAssetExtractor(extraction, bindings);
101
+ const backend = createWasmTileBackend(bindings, extractor, 64 * 1024 * 1024, 4096);
102
+ const queue = new DemandGeometryQueue(backend.tiles, 64 * 1024 * 1024);
103
+ const pump = new DemandResidencyPump(queue, model);
104
+ for (const product of model.types(IfcProduct)) {
105
+ pump.request(product.localID, 1);
106
+ }
107
+ // Drain admission in batches.
108
+ while (pump.pendingCount > 0) {
109
+ const result = await pump.pump();
110
+ expect(result.prefetchFailures).toBe(0);
111
+ }
112
+ expect(committed.length).toBeGreaterThan(0);
113
+ expect(queue.stats.residentCount).toBeGreaterThan(0);
114
+ // Evicting everything releases every committed wasm tile.
115
+ queue.evictAll();
116
+ expect(new Set(released)).toEqual(new Set(committed));
117
+ });
118
+ });
@@ -11,4 +11,18 @@ export { ExtractResult } from "./core/shared_constants.js";
11
11
  export { ProgressEvent, ProgressCallback, ProgressPhase, ProgressUnit, ProgressTracker, CountProgressCallback, yieldToEventLoop, } from "./core/progress.js";
12
12
  export { ModelLoadOptions } from "./loaders/conway_model_loader.js";
13
13
  export { LoadLogAccumulator, ModelInfo, ProgressEventLike, formatBar, formatMb, formatModelLine, formatSeconds, stageLabel, } from "./core/progress_log.js";
14
+ export { openStreamedIfcModel, StreamedIfcOpen, StreamedIfcOpenOptions } from "./ifc/ifc_stream_open.js";
15
+ export { ByteSource, BufferByteSource } from "./step/parsing/byte_source.js";
16
+ export { StepExternalByteStore, InMemoryStepByteStore, StepBufferProvider, WindowedStepBufferProvider, } from "./step/step_buffer_provider.js";
17
+ export { StepIndexColumns } from "./step/parsing/columnar_index.js";
18
+ export { serializeIndexSidecarFromColumns, deserializeIndexSidecarToColumns, sidecarMatchesSource, hashSource, } from "./step/parsing/index_sidecar.js";
19
+ export { StreamingRecordDispatcher, RecordHandler } from "./step/parsing/streaming_record_dispatcher.js";
20
+ export { IncrementalTypeIndex } from "./step/parsing/incremental_type_index.js";
21
+ export { DemandGeometryQueue, GeometryTiles, DemandQueueStats } from "./core/demand_geometry_queue.js";
22
+ export { DemandResidencyPump, ResidencyPrefetcher, PumpResult } from "./core/demand_residency_pump.js";
23
+ export { GeometryTilePoolBindings, TileAssetExtractor, WasmTileBackend, createWasmTileBackend, readGeometryTilePayload, GeometryTilePayload, } from "./core/geometry_tile_bindings.js";
24
+ export { IfcTileAssetExtractor, TileCommitBindings } from "./ifc/ifc_tile_extractor.js";
25
+ export { ChunkedPool, ChunkSpan } from "./core/mem/chunked_pool.js";
26
+ export { SharedAssetPool } from "./core/mem/shared_asset_pool.js";
27
+ export { GeometryTilePool, InstanceAssetSource, GeometryAsset } from "./core/geometry_tile_pool.js";
14
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAC,MAAM,6BAA6B,CAAA;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE/F,OAAO,EAAE,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAA;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,QAAQ,EACR,eAAe,EACf,aAAa,EACb,UAAU,GACX,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAC,MAAM,6BAA6B,CAAA;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAE/F,OAAO,EAAE,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAA;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EACL,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,SAAS,EACT,QAAQ,EACR,eAAe,EACf,aAAa,EACb,UAAU,GACX,MAAM,qBAAqB,CAAA;AAK5B,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AACrG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AACzE,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,oBAAoB,EACpB,UAAU,GACX,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAA;AACrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAA;AAC5E,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACnG,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACnG,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AACpF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA"}
@@ -10,3 +10,19 @@ export { CanonicalMeshType } from "./core/canonical_mesh.js";
10
10
  export { ExtractResult } from "./core/shared_constants.js";
11
11
  export { ProgressTracker, yieldToEventLoop, } from "./core/progress.js";
12
12
  export { LoadLogAccumulator, formatBar, formatMb, formatModelLine, formatSeconds, stageLabel, } from "./core/progress_log.js";
13
+ // --- Streaming / demand-geometry surface (epic #390; design doc
14
+ // design/new/streaming-federated-loader.md). The release-facing API for
15
+ // fixed-memory opens and demand-driven residency.
16
+ export { openStreamedIfcModel } from "./ifc/ifc_stream_open.js";
17
+ export { BufferByteSource } from "./step/parsing/byte_source.js";
18
+ export { InMemoryStepByteStore, WindowedStepBufferProvider, } from "./step/step_buffer_provider.js";
19
+ export { serializeIndexSidecarFromColumns, deserializeIndexSidecarToColumns, sidecarMatchesSource, hashSource, } from "./step/parsing/index_sidecar.js";
20
+ export { StreamingRecordDispatcher } from "./step/parsing/streaming_record_dispatcher.js";
21
+ export { IncrementalTypeIndex } from "./step/parsing/incremental_type_index.js";
22
+ export { DemandGeometryQueue } from "./core/demand_geometry_queue.js";
23
+ export { DemandResidencyPump } from "./core/demand_residency_pump.js";
24
+ export { createWasmTileBackend, readGeometryTilePayload, } from "./core/geometry_tile_bindings.js";
25
+ export { IfcTileAssetExtractor } from "./ifc/ifc_tile_extractor.js";
26
+ export { ChunkedPool } from "./core/mem/chunked_pool.js";
27
+ export { SharedAssetPool } from "./core/mem/shared_asset_pool.js";
28
+ export { GeometryTilePool } from "./core/geometry_tile_pool.js";
@@ -5,5 +5,5 @@
5
5
  // only the first segment (major) is meaningful and is the one CI carries forward.
6
6
  // Must stay in `vN.N.N` shape: the CI stamp regex, scripts/updateVersion.mjs, and
7
7
  // statistics.ts all match `v\d+\.\d+\.\d+`.
8
- const versionString = 'Conway v1.413.1255';
8
+ const versionString = 'Conway v1.417.1262';
9
9
  export { versionString };