Skip to content

fix(query)!: reject a non-IFC type name in ofType(), but not standard types the enum table omits - #3009

Open
BIMvoice wants to merge 3 commits into
mainfrom
query-diff-create-sweep
Open

fix(query)!: reject a non-IFC type name in ofType(), but not standard types the enum table omits#3009
BIMvoice wants to merge 3 commits into
mainfrom
query-diff-create-sweep

Conversation

@BIMvoice

Copy link
Copy Markdown
Collaborator

query.ofType() silently returned an empty result for a mistyped type name. It now throws — but only for strings that are not IFC entity names at all.

Found on a never-raised branch; merges clean. The branch as written threw for any type absent from TYPE_STRING_TO_ENUM, which is a curated 138-entry subset — so it also rejected standard buildingSMART types the table simply omits.

What that would have broken

Confirmed by running IfcTypeEnumFromString: IfcChiller, IfcActuator, IfcElectricAppliance, IfcBuildingSystem and IfcAudioVisualAppliance all resolve to Unknown and would have thrown. Those are standard IFC4 types, not the "typo … or vendor-specific type name" the original changeset described. Querying them previously reached the Unknown bucket — which, in a file whose only unclassified entities are chillers, worked.

The fix keys on a real oracle

packages/data/src/ifc-entity-names.ts already exports IFC_ENTITY_NAMES, a ~880-entry IFC4X3 table, from the package ofType() already imports:

if (upper !== 'UNKNOWN' && IFC_ENTITY_NAMES[upper] === undefined) { throw  }

An indexed-value check rather than in, so the lookup cannot reach Object.prototype.

Extending TYPE_STRING_TO_ENUM instead was considered and rejected as disproportionate: it would mean adding ~750 members to IfcTypeEnum, which is mirrored in rust/core/src/generated/type_ids.rs.

Verified per type, by returned ids rather than by absence of a throw: all five standard types are in IFC_ENTITY_NAMES (lines 26, 60, 99, 126, 261), absent from TYPE_STRING_TO_ENUM, and now reach the Unknown bucket. IFCWAL and IFCPROPRIETARYVENDORTHING still throw.

RED with the branch's original condition restored: 6 of 10 fail — the five standard types plus the casing/whitespace case — with Error: ofType(): "IFCCHILLER" is not an IFC entity name.

The bump was wrong, and is corrected

patchmajor. @ifc-lite/query is 1.14.16, and throwing where the API previously returned an EntityQuery is breaking on a published export.

The changeset now leads with "Breaking:", lists the five standard types as explicitly not rejected, explains why the check keys on IFC_ENTITY_NAMES rather than the enum table, and states the real breaking case plainly: a genuine vendor-specific type name — which the original changeset cited as a reason to throw — previously reached the Unknown bucket and now throws, with 'Unknown' as the migration path.

packages/query 177 → 185 (the 2-test file is replaced by 10); packages/data 148 unchanged. 'Unknown' escape hatch verified still working. api-surface unchanged at 4191 (the signature did not move), unused-locals, changesets, source-text-assertions, test-wiring and check-generated all pass. No baseline or ratchet touched.

🤖 Generated with Claude Code

…of matching Unknown

IfcTypeEnumFromString falls back to IfcTypeEnum.Unknown for any type name it
does not recognize, so a caller's typo (ofType('IfcWal')) or a vendor-specific
type silently queried the Unknown bucket — every entity whose type the store
itself could not classify — instead of returning nothing. ofType() now throws
for an unrecognized name; the Unknown bucket is still reachable by passing the
literal string 'Unknown'.
The guard added in 33bda64 rejected every type string that mapped to
IfcTypeEnum.Unknown. TYPE_STRING_TO_ENUM (packages/data/src/types.ts) is a
curated subset of IFC, not the whole schema, so that rule also rejected
standard buildingSMART types the table simply has no row for - IfcChiller,
IfcActuator, IfcElectricAppliance, IfcBuildingSystem, IfcAudioVisualAppliance
among them. Querying those returned the Unknown bucket before, which answers
correctly in a file whose only unclassified entities are of that type; the
guard turned that working query into a throw with no disclosure.

Key the check on IFC_ENTITY_NAMES instead - the ~880-entry IFC4X3 entity-name
table already exported from @ifc-lite/data. A string that is not an IFC entity
name at all ('IfcWal') still throws; a real IFC name the enum table does not
map falls through to Unknown exactly as before. 'Unknown' stays reachable by
its literal string.

RED: with the previous condition restored, the six new expectations covering
the five standard types plus casing/whitespace fail; they pass with this one.
packages/query 177 -> 185 pass, packages/data 148 pass, both 0 fail.

The changeset is corrected from patch to major and now states the actual
breaking case: a name that is not an IFC entity name - a typo, or a genuine
vendor-specific type name - previously returned an EntityQuery over the
Unknown bucket and now throws. @ifc-lite/query is 1.x, and this is a
behaviour change on a published SDK export.
@BIMvoice
BIMvoice requested a review from louistrue as a code owner August 21, 2026 12:01
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@louistrue, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 55 minutes

Limit details: You’ve used all 2 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d0f4809e-3009-453a-898c-91c24c252ac2

📥 Commits

Reviewing files that changed from the base of the PR and between fe38b33 and 86b1d13.

📒 Files selected for processing (3)
  • .changeset/query-oftype-unknown-typo.md
  • packages/query/src/ifc-query.ts
  • packages/query/test/oftype-unknown-type.test.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Viewer benchmark

1 metric(s) exceeded the regression threshold (advisory only, not blocking).

01_Snowdon_Towers_Sample_Structural(1).ifc

Baseline recorded 2026-07-01T20:31:05.538Z on github-actions ubuntu-latest, viewer-benchmark-ci (headless Chrome, SwiftShader ANGLE), production build.

Metric Current Baseline Delta Threshold Status
firstBatchWaitMs 1947ms 2905ms -33.0% +50%
firstVisibleGeometryMs 2513ms 3652ms -31.2% +50%
streamCompleteMs 2988ms 3598ms -17.0% +50%
spatialReadyMs 1615ms 1032ms +56.5% +50%
metadataCompleteMs 2001ms 3063ms -34.7% +50%
totalWallClockMs 3100ms 3700ms -16.2% +50%

AC20-FZK-Haus.ifc

Baseline recorded 2026-07-01T20:30:59.972Z on github-actions ubuntu-latest, viewer-benchmark-ci (headless Chrome, SwiftShader ANGLE), production build.

Metric Current Baseline Delta Threshold Status
firstBatchWaitMs 299ms 1075ms -72.2% +50%
firstVisibleGeometryMs 1439ms 1572ms -8.5% +50%
streamCompleteMs 988ms 1980ms -50.1% +50%
spatialReadyMs 1022ms 915ms +11.7% +50%
metadataCompleteMs 1126ms 1392ms -19.1% +50%
totalWallClockMs 1500ms 3300ms -54.5% +50%

Refresh the baseline from a CI run: dispatch the Benchmark workflow with record_baseline, download the benchmark-baseline artifact, and commit baseline.json (see tests/benchmark/README.md).

@louistrue

Copy link
Copy Markdown
Collaborator

The guard rejects seven entity names that this repo's own parser ships as real IFC entities.

packages/query/src/ifc-query.ts:118 uses IFC_ENTITY_NAMES as the oracle for "is this a real IFC entity name". That table (packages/data/src/ifc-entity-names.ts) is IFC4X3-only, 880 entries. packages/parser/src/generated/schema-registry.ts carries 776 IFC4 entities, and 15 of those are absent from IFC_ENTITY_NAMES. Eight of the 15 are still reachable because TYPE_STRING_TO_ENUM has a row for them, so the guard never runs. The other seven now throw:

  • IfcDoorStyle
  • IfcWindowStyle
  • IfcWallElementedCase
  • IfcSlabElementedCase
  • IfcPresentationStyleAssignment
  • IfcBuildingElement
  • IfcBuildingElementType

Run against the built @ifc-lite/data with the exact predicate from this PR:

OK     IfcWall
OK     IfcChiller
THROWS IfcDoorStyle
THROWS IfcWindowStyle
THROWS IfcWallElementedCase
THROWS IfcSlabElementedCase
THROWS IfcPresentationStyleAssignment
THROWS IfcBuildingElement
THROWS IfcBuildingElementType
THROWS IfcWal
OK     Unknown

Concrete failure: IfcDoorStyle and IfcWindowStyle are how IFC2X3 files carry door and window typing, and IFC2X3 is a schema this parser reads. Today query.ofType('IfcDoorStyle') on such a file resolves to Unknown and returns those entities, which is the same "answers the query correctly in a file whose unclassified entities are of that type" case the changeset promises to preserve for IfcChiller. After this PR the call throws "IfcDoorStyle" is not an IFC entity name - check the spelling, and the name is spelled correctly.

So the changeset's "Standard IFC types that this build's enum table does not map ... are not rejected" is not true as written, and the error text tells the user to fix a spelling that is already right.

The oracle needs to cover the schemas the parser actually reads, not just IFC4X3. Widening it to the parser's schema registry (or adding the missing names to IFC_ENTITY_NAMES) would close this. The typo case this PR is aimed at still gets caught either way.

A cheap regression test: assert that every entity name in packages/parser/src/generated/schema-registry.ts passes ofType() without throwing. The current fixture picks five names by hand, and all five happen to be in IFC_ENTITY_NAMES, so it cannot see this.

@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ifc-lite-dev Ready Ready Preview Aug 21, 2026 9:16pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ifc-lite-viewer-embed Ignored Ignored Aug 21, 2026 9:16pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants