@ifc-lite/ids 1.14.10 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -44
- package/dist/audit/coherence/index.d.ts +12 -0
- package/dist/audit/coherence/index.d.ts.map +1 -0
- package/dist/audit/coherence/index.js +392 -0
- package/dist/audit/coherence/index.js.map +1 -0
- package/dist/audit/coherence/regex.d.ts +57 -0
- package/dist/audit/coherence/regex.d.ts.map +1 -0
- package/dist/audit/coherence/regex.js +111 -0
- package/dist/audit/coherence/regex.js.map +1 -0
- package/dist/audit/ifc-schema/index.d.ts +4 -0
- package/dist/audit/ifc-schema/index.d.ts.map +1 -0
- package/dist/audit/ifc-schema/index.js +637 -0
- package/dist/audit/ifc-schema/index.js.map +1 -0
- package/dist/audit/index.d.ts +37 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +60 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/parser-shim.d.ts +13 -0
- package/dist/audit/parser-shim.d.ts.map +1 -0
- package/dist/audit/parser-shim.js +66 -0
- package/dist/audit/parser-shim.js.map +1 -0
- package/dist/audit/structural/index.d.ts +22 -0
- package/dist/audit/structural/index.d.ts.map +1 -0
- package/dist/audit/structural/index.js +441 -0
- package/dist/audit/structural/index.js.map +1 -0
- package/dist/audit/types.d.ts +91 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +5 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/audit/xsd/index.d.ts +13 -0
- package/dist/audit/xsd/index.d.ts.map +1 -0
- package/dist/audit/xsd/index.js +203 -0
- package/dist/audit/xsd/index.js.map +1 -0
- package/dist/bridge/classifications.d.ts +15 -0
- package/dist/bridge/classifications.d.ts.map +1 -0
- package/dist/bridge/classifications.js +114 -0
- package/dist/bridge/classifications.js.map +1 -0
- package/dist/bridge/data-accessor.d.ts +16 -0
- package/dist/bridge/data-accessor.d.ts.map +1 -0
- package/dist/bridge/data-accessor.js +205 -0
- package/dist/bridge/data-accessor.js.map +1 -0
- package/dist/bridge/data-types.d.ts +11 -0
- package/dist/bridge/data-types.d.ts.map +1 -0
- package/dist/bridge/data-types.js +47 -0
- package/dist/bridge/data-types.js.map +1 -0
- package/dist/bridge/index.d.ts +17 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +20 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/bridge/materials.d.ts +11 -0
- package/dist/bridge/materials.d.ts.map +1 -0
- package/dist/bridge/materials.js +68 -0
- package/dist/bridge/materials.js.map +1 -0
- package/dist/bridge/predefined-types.d.ts +19 -0
- package/dist/bridge/predefined-types.d.ts.map +1 -0
- package/dist/bridge/predefined-types.js +84 -0
- package/dist/bridge/predefined-types.js.map +1 -0
- package/dist/bridge/properties.d.ts +20 -0
- package/dist/bridge/properties.d.ts.map +1 -0
- package/dist/bridge/properties.js +168 -0
- package/dist/bridge/properties.js.map +1 -0
- package/dist/bridge/schema-version.d.ts +10 -0
- package/dist/bridge/schema-version.d.ts.map +1 -0
- package/dist/bridge/schema-version.js +25 -0
- package/dist/bridge/schema-version.js.map +1 -0
- package/dist/bridge/units.d.ts +18 -0
- package/dist/bridge/units.d.ts.map +1 -0
- package/dist/bridge/units.js +55 -0
- package/dist/bridge/units.js.map +1 -0
- package/dist/constraints/comparators.d.ts +32 -0
- package/dist/constraints/comparators.d.ts.map +1 -0
- package/dist/constraints/comparators.js +94 -0
- package/dist/constraints/comparators.js.map +1 -0
- package/dist/constraints/index.d.ts +11 -1
- package/dist/constraints/index.d.ts.map +1 -1
- package/dist/constraints/index.js +74 -58
- package/dist/constraints/index.js.map +1 -1
- package/dist/constraints/xsd-cast.d.ts +20 -0
- package/dist/constraints/xsd-cast.d.ts.map +1 -0
- package/dist/constraints/xsd-cast.js +89 -0
- package/dist/constraints/xsd-cast.js.map +1 -0
- package/dist/facets/attribute-facet.d.ts.map +1 -1
- package/dist/facets/attribute-facet.js +80 -12
- package/dist/facets/attribute-facet.js.map +1 -1
- package/dist/facets/classification-facet.d.ts.map +1 -1
- package/dist/facets/classification-facet.js +21 -2
- package/dist/facets/classification-facet.js.map +1 -1
- package/dist/facets/entity-facet.d.ts.map +1 -1
- package/dist/facets/entity-facet.js +59 -7
- package/dist/facets/entity-facet.js.map +1 -1
- package/dist/facets/partof-facet.d.ts.map +1 -1
- package/dist/facets/partof-facet.js +40 -8
- package/dist/facets/partof-facet.js.map +1 -1
- package/dist/facets/property-facet.d.ts.map +1 -1
- package/dist/facets/property-facet.js +171 -55
- package/dist/facets/property-facet.js.map +1 -1
- package/dist/facets/test-helpers.d.ts +42 -0
- package/dist/facets/test-helpers.d.ts.map +1 -0
- package/dist/facets/test-helpers.js +106 -0
- package/dist/facets/test-helpers.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/parser/xml-parser.d.ts.map +1 -1
- package/dist/parser/xml-parser.js +198 -68
- package/dist/parser/xml-parser.js.map +1 -1
- package/dist/translation/locales/de.d.ts +1 -0
- package/dist/translation/locales/de.d.ts.map +1 -1
- package/dist/translation/locales/de.js +1 -0
- package/dist/translation/locales/de.js.map +1 -1
- package/dist/translation/locales/en.d.ts +1 -0
- package/dist/translation/locales/en.d.ts.map +1 -1
- package/dist/translation/locales/en.js +1 -0
- package/dist/translation/locales/en.js.map +1 -1
- package/dist/translation/locales/fr.d.ts +1 -0
- package/dist/translation/locales/fr.d.ts.map +1 -1
- package/dist/translation/locales/fr.js +1 -0
- package/dist/translation/locales/fr.js.map +1 -1
- package/dist/types.d.ts +116 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/validation/validator.js +49 -3
- package/dist/validation/validator.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { extractPropertiesOnDemand, extractQuantitiesOnDemand, extractTypePropertiesOnDemand, extractTypeEntityOwnProperties, extractAllEntityAttributes, } from '@ifc-lite/parser';
|
|
5
|
+
import { RelationshipType } from '@ifc-lite/data';
|
|
6
|
+
import { idsDataTypeForProperty, idsDataTypeForQuantity } from './data-types.js';
|
|
7
|
+
import { applyUnitConversion } from './units.js';
|
|
8
|
+
/**
|
|
9
|
+
* IDS treats `IfcElementQuantity` (Qto_*) and `IfcPropertySet` (Pset_*)
|
|
10
|
+
* uniformly — both surface as "property sets" with named values. The
|
|
11
|
+
* parser stores them in separate columnar tables, so we merge here.
|
|
12
|
+
*
|
|
13
|
+
* Surfaces three sources:
|
|
14
|
+
* 1. The instance's own property sets (IfcPropertySet via
|
|
15
|
+
* IfcRelDefinesByProperties).
|
|
16
|
+
* 2. Predefined property sets (IfcDoorPanelProperties etc.) where
|
|
17
|
+
* the entity's schema-defined attributes act as property names.
|
|
18
|
+
* 3. Inherited property sets from `IfcRelDefinesByType`.
|
|
19
|
+
*
|
|
20
|
+
* Length-typed properties are converted to base SI units per the
|
|
21
|
+
* project's `lengthUnitScale` so IDS literals (always in metres)
|
|
22
|
+
* compare correctly.
|
|
23
|
+
*/
|
|
24
|
+
export function collectAllPropertySets(store, expressId) {
|
|
25
|
+
const out = [];
|
|
26
|
+
const scale = store.lengthUnitScale;
|
|
27
|
+
appendInstancePropertySets(store, expressId, scale, out);
|
|
28
|
+
appendQuantitySets(store, expressId, out);
|
|
29
|
+
appendPredefinedPropertySets(store, expressId, out);
|
|
30
|
+
appendInheritedPropertySets(store, expressId, scale, out);
|
|
31
|
+
if (out.length === 0) {
|
|
32
|
+
appendTypeEntityOwnProperties(store, expressId, out);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
function appendInstancePropertySets(store, expressId, scale, out) {
|
|
37
|
+
let props = store.properties?.getForEntity?.(expressId);
|
|
38
|
+
if (!props || props.length === 0) {
|
|
39
|
+
props = extractPropertiesOnDemand(store, expressId);
|
|
40
|
+
}
|
|
41
|
+
if (!props || props.length === 0)
|
|
42
|
+
return;
|
|
43
|
+
for (const pset of props) {
|
|
44
|
+
out.push({
|
|
45
|
+
name: pset.name,
|
|
46
|
+
properties: (pset.properties || []).map((p) => projectProperty(p, scale)),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function appendQuantitySets(store, expressId, out) {
|
|
51
|
+
let quantities = store.quantities?.getForEntity?.(expressId);
|
|
52
|
+
if (!quantities || quantities.length === 0) {
|
|
53
|
+
quantities = extractQuantitiesOnDemand(store, expressId);
|
|
54
|
+
}
|
|
55
|
+
if (!quantities || quantities.length === 0)
|
|
56
|
+
return;
|
|
57
|
+
for (const qset of quantities) {
|
|
58
|
+
out.push({
|
|
59
|
+
name: qset.name,
|
|
60
|
+
properties: (qset.quantities || []).map((q) => ({
|
|
61
|
+
name: q.name,
|
|
62
|
+
value: q.value,
|
|
63
|
+
dataType: idsDataTypeForQuantity(q.type),
|
|
64
|
+
})),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Predefined property-set entities (`IfcDoorPanelProperties`, …) are
|
|
70
|
+
* connected to elements via `IfcRelDefinesByProperties` like a normal
|
|
71
|
+
* pset, but their properties live as schema-defined ATTRIBUTES on the
|
|
72
|
+
* entity itself. Surface them as a pset whose name is the entity's
|
|
73
|
+
* `Name` and whose properties are the schema-defined attribute slots
|
|
74
|
+
* beyond Name/Description.
|
|
75
|
+
*/
|
|
76
|
+
function appendPredefinedPropertySets(store, expressId, out) {
|
|
77
|
+
const psetIds = store.relationships?.getRelated?.(expressId, RelationshipType.DefinesByProperties, 'inverse') || [];
|
|
78
|
+
for (const psetId of psetIds) {
|
|
79
|
+
const ref = store.entityIndex?.byId?.get?.(psetId);
|
|
80
|
+
if (!ref)
|
|
81
|
+
continue;
|
|
82
|
+
const tu = String(ref.type).toUpperCase();
|
|
83
|
+
if (tu === 'IFCPROPERTYSET' || tu === 'IFCELEMENTQUANTITY')
|
|
84
|
+
continue;
|
|
85
|
+
if (!tu.endsWith('PROPERTIES'))
|
|
86
|
+
continue;
|
|
87
|
+
const allAttrs = extractAllEntityAttributes(store, psetId);
|
|
88
|
+
const psetNameAttr = allAttrs.find((a) => a.name === 'Name')?.value;
|
|
89
|
+
if (typeof psetNameAttr !== 'string' || !psetNameAttr)
|
|
90
|
+
continue;
|
|
91
|
+
if (out.some((p) => p.name === psetNameAttr))
|
|
92
|
+
continue;
|
|
93
|
+
const properties = allAttrs
|
|
94
|
+
.filter((a) => a.name !== 'GlobalId' &&
|
|
95
|
+
a.name !== 'Name' &&
|
|
96
|
+
a.name !== 'Description' &&
|
|
97
|
+
a.value !== undefined &&
|
|
98
|
+
a.value !== '')
|
|
99
|
+
.map((a) => ({
|
|
100
|
+
name: a.name,
|
|
101
|
+
value: a.value,
|
|
102
|
+
// dataType intentionally left empty: without a per-attribute
|
|
103
|
+
// schema lookup we can't know if PanelOperation is IFCDOORPANELOPERATIONENUM
|
|
104
|
+
// vs anything else. The IDS dataType gate then no-ops for these slots.
|
|
105
|
+
dataType: '',
|
|
106
|
+
}));
|
|
107
|
+
if (properties.length > 0)
|
|
108
|
+
out.push({ name: psetNameAttr, properties });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function appendInheritedPropertySets(store, expressId, scale, out) {
|
|
112
|
+
const inherited = extractTypePropertiesOnDemand(store, expressId);
|
|
113
|
+
if (!inherited || !inherited.properties || inherited.properties.length === 0)
|
|
114
|
+
return;
|
|
115
|
+
const seen = new Set(out.map((p) => p.name));
|
|
116
|
+
for (const pset of inherited.properties) {
|
|
117
|
+
if (seen.has(pset.name))
|
|
118
|
+
continue;
|
|
119
|
+
out.push({
|
|
120
|
+
name: pset.name,
|
|
121
|
+
properties: (pset.properties || []).map((p) => projectProperty(p, scale)),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function appendTypeEntityOwnProperties(store, expressId, out) {
|
|
126
|
+
const typePsets = extractTypeEntityOwnProperties(store, expressId);
|
|
127
|
+
if (typePsets.length === 0)
|
|
128
|
+
return;
|
|
129
|
+
for (const pset of typePsets) {
|
|
130
|
+
out.push({
|
|
131
|
+
name: pset.name,
|
|
132
|
+
properties: (pset.properties || []).map((p) => ({
|
|
133
|
+
name: p.name,
|
|
134
|
+
value: Array.isArray(p.value)
|
|
135
|
+
? JSON.stringify(p.value)
|
|
136
|
+
: p.value,
|
|
137
|
+
dataType: idsDataTypeForProperty(p.type),
|
|
138
|
+
...(Array.isArray(p.values) && p.values.length > 0
|
|
139
|
+
? { values: p.values }
|
|
140
|
+
: {}),
|
|
141
|
+
})),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Project a raw parser property record into the validator's
|
|
147
|
+
* `PropertySetInfo['properties'][number]` shape — applies unit
|
|
148
|
+
* conversion and resolves the IDS dataType. Multi-valued properties
|
|
149
|
+
* (lists, enumerations, table values) suppress dataType so the
|
|
150
|
+
* validator's dataType gate falls through to the value match.
|
|
151
|
+
*/
|
|
152
|
+
function projectProperty(p, scale) {
|
|
153
|
+
const hasMultiValue = Array.isArray(p.values) && p.values.length > 0;
|
|
154
|
+
const dataType = p.dataType ??
|
|
155
|
+
(hasMultiValue ? undefined : idsDataTypeForProperty(p.type));
|
|
156
|
+
const baseValue = Array.isArray(p.value)
|
|
157
|
+
? JSON.stringify(p.value)
|
|
158
|
+
: p.value;
|
|
159
|
+
const baseValues = hasMultiValue ? p.values : undefined;
|
|
160
|
+
const converted = applyUnitConversion(baseValue, baseValues, dataType, scale);
|
|
161
|
+
return {
|
|
162
|
+
name: p.name,
|
|
163
|
+
value: converted.value,
|
|
164
|
+
dataType: dataType ?? '',
|
|
165
|
+
...(converted.values ? { values: converted.values } : {}),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.js","sourceRoot":"","sources":["../../src/bridge/properties.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IfcSchemaVersion } from '@ifc-lite/data';
|
|
2
|
+
/**
|
|
3
|
+
* Narrow a parser schema-version string to the subset
|
|
4
|
+
* `@ifc-lite/data` carries lookup tables for. The parser surfaces a
|
|
5
|
+
* wider union (`'IFC2X3' | 'IFC4' | 'IFC4X3' | 'IFC5'`) than the
|
|
6
|
+
* schema package supports; IFC5 has no published EXPRESS schema yet so
|
|
7
|
+
* we treat it as IFC4X3 for type lookups.
|
|
8
|
+
*/
|
|
9
|
+
export declare function narrowSchemaVersion(raw: string | undefined): IfcSchemaVersion;
|
|
10
|
+
//# sourceMappingURL=schema-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-version.d.ts","sourceRoot":"","sources":["../../src/bridge/schema-version.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAa7E"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Narrow a parser schema-version string to the subset
|
|
6
|
+
* `@ifc-lite/data` carries lookup tables for. The parser surfaces a
|
|
7
|
+
* wider union (`'IFC2X3' | 'IFC4' | 'IFC4X3' | 'IFC5'`) than the
|
|
8
|
+
* schema package supports; IFC5 has no published EXPRESS schema yet so
|
|
9
|
+
* we treat it as IFC4X3 for type lookups.
|
|
10
|
+
*/
|
|
11
|
+
export function narrowSchemaVersion(raw) {
|
|
12
|
+
switch ((raw || '').toUpperCase()) {
|
|
13
|
+
case 'IFC2X3':
|
|
14
|
+
return 'IFC2X3';
|
|
15
|
+
case 'IFC4':
|
|
16
|
+
return 'IFC4';
|
|
17
|
+
case 'IFC4X3':
|
|
18
|
+
case 'IFC4X3_ADD2':
|
|
19
|
+
case 'IFC5':
|
|
20
|
+
return 'IFC4X3';
|
|
21
|
+
default:
|
|
22
|
+
return 'IFC4';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=schema-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-version.js","sourceRoot":"","sources":["../../src/bridge/schema-version.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAI/D;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAuB;IACzD,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAClC,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,QAAQ,CAAC;QACd,KAAK,aAAa,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,QAAQ,CAAC;QAClB;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per IDS spec, IDS literal values for IFC measure types are always in
|
|
3
|
+
* base SI units. The IFC store keeps the raw author value, so when the
|
|
4
|
+
* project's length unit is `MILLI`, a stored `1000` length means
|
|
5
|
+
* `1.0 metre` and the IDS check `1` should match. This helper applies
|
|
6
|
+
* the project's `lengthUnitScale` to numeric values for length
|
|
7
|
+
* measures.
|
|
8
|
+
*
|
|
9
|
+
* Properties without a declared dataType (notably `IfcPropertyTableValue`,
|
|
10
|
+
* where columns mix labels and measures) get a conservative double-up:
|
|
11
|
+
* every numeric candidate is surfaced both raw and scaled, so an IDS
|
|
12
|
+
* check using either unit space matches.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyUnitConversion(rawValue: string | number | boolean | null, rawValues: string[] | undefined, dataType: string | undefined, scale: number | undefined): {
|
|
15
|
+
value: string | number | boolean | null;
|
|
16
|
+
values: string[] | undefined;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=units.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../../src/bridge/units.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAC1C,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,EAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB;IAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CAAE,CAyC3E"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Per IDS spec, IDS literal values for IFC measure types are always in
|
|
6
|
+
* base SI units. The IFC store keeps the raw author value, so when the
|
|
7
|
+
* project's length unit is `MILLI`, a stored `1000` length means
|
|
8
|
+
* `1.0 metre` and the IDS check `1` should match. This helper applies
|
|
9
|
+
* the project's `lengthUnitScale` to numeric values for length
|
|
10
|
+
* measures.
|
|
11
|
+
*
|
|
12
|
+
* Properties without a declared dataType (notably `IfcPropertyTableValue`,
|
|
13
|
+
* where columns mix labels and measures) get a conservative double-up:
|
|
14
|
+
* every numeric candidate is surfaced both raw and scaled, so an IDS
|
|
15
|
+
* check using either unit space matches.
|
|
16
|
+
*/
|
|
17
|
+
export function applyUnitConversion(rawValue, rawValues, dataType, scale) {
|
|
18
|
+
if (!scale || scale === 1) {
|
|
19
|
+
return { value: rawValue, values: rawValues };
|
|
20
|
+
}
|
|
21
|
+
const upper = dataType ? dataType.toUpperCase() : '';
|
|
22
|
+
const isLength = upper === 'IFCLENGTHMEASURE' || upper === 'IFCPOSITIVELENGTHMEASURE';
|
|
23
|
+
const isUntypedTable = !dataType && Array.isArray(rawValues) && rawValues.length > 0;
|
|
24
|
+
if (!isLength && !isUntypedTable) {
|
|
25
|
+
return { value: rawValue, values: rawValues };
|
|
26
|
+
}
|
|
27
|
+
const convertNum = (v) => {
|
|
28
|
+
const n = typeof v === 'number' ? v : parseFloat(String(v));
|
|
29
|
+
return Number.isFinite(n) ? n * scale : null;
|
|
30
|
+
};
|
|
31
|
+
if (isLength) {
|
|
32
|
+
const converted = (() => {
|
|
33
|
+
const c = convertNum(rawValue);
|
|
34
|
+
return c == null ? rawValue : c;
|
|
35
|
+
})();
|
|
36
|
+
const values = Array.isArray(rawValues)
|
|
37
|
+
? rawValues.map((v) => {
|
|
38
|
+
const c = convertNum(v);
|
|
39
|
+
return c == null ? String(v) : String(c);
|
|
40
|
+
})
|
|
41
|
+
: rawValues;
|
|
42
|
+
return { value: converted, values };
|
|
43
|
+
}
|
|
44
|
+
// Untyped table — keep raw values and append scaled copies for every
|
|
45
|
+
// numeric candidate so either unit space matches.
|
|
46
|
+
const expanded = [];
|
|
47
|
+
for (const v of rawValues) {
|
|
48
|
+
expanded.push(String(v));
|
|
49
|
+
const c = convertNum(v);
|
|
50
|
+
if (c != null && String(c) !== String(v))
|
|
51
|
+
expanded.push(String(c));
|
|
52
|
+
}
|
|
53
|
+
return { value: rawValue, values: expanded };
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=units.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/bridge/units.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAA0C,EAC1C,SAA+B,EAC/B,QAA4B,EAC5B,KAAyB;IAEzB,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,MAAM,QAAQ,GACZ,KAAK,KAAK,kBAAkB,IAAI,KAAK,KAAK,0BAA0B,CAAC;IACvE,MAAM,cAAc,GAClB,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAChE,IAAI,CAAC,QAAQ,IAAI,CAAC,cAAc,EAAE,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,CAAU,EAAiB,EAAE;QAC/C,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC,CAAC;IAEF,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE;YACtB,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACrC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAClB,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBACxB,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3C,CAAC,CAAC;YACJ,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;IAED,qEAAqE;IACrE,kDAAkD;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,SAAU,EAAE,CAAC;QAC3B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare function numericEpsilon(castValue: number, actual?: number): number;
|
|
2
|
+
/**
|
|
3
|
+
* Compare an IDS literal `expected` (always a string from the XML) to
|
|
4
|
+
* `actual` as numbers. Returns:
|
|
5
|
+
* - `true` / `false` when both sides parse cleanly as numerics, OR
|
|
6
|
+
* - `undefined` when either side isn't a strict numeric literal,
|
|
7
|
+
* in which case the caller should fall back to other comparators
|
|
8
|
+
* (string equality, regex, etc.).
|
|
9
|
+
*
|
|
10
|
+
* Strictness is the whole point: `parseFloat('2022-01-01')` returns
|
|
11
|
+
* `2022`, which would silently equate dates with their year. Requiring
|
|
12
|
+
* `NUMERIC_RE.test(...)` on both sides keeps date-like strings opaque.
|
|
13
|
+
*/
|
|
14
|
+
export declare function compareNumeric(expected: string, actual: string | number | boolean): boolean | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Compare an IDS boolean literal to a stored value. Per IDS 1.0 spec
|
|
17
|
+
* the literal MUST be lowercase `true` / `false`; uppercase or
|
|
18
|
+
* numeric forms (`1` / `0`) are malformed and never match.
|
|
19
|
+
*
|
|
20
|
+
* Returns:
|
|
21
|
+
* - `true` / `false` when both sides resolve to a boolean, OR
|
|
22
|
+
* - `undefined` when neither side is a recognised boolean — caller
|
|
23
|
+
* should fall through to other comparators.
|
|
24
|
+
*/
|
|
25
|
+
export declare function compareBoolean(expected: string, actual: string | number | boolean): boolean | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Plain string equality with optional case-insensitive shortcut.
|
|
28
|
+
* Returns `undefined` when no decision can be made so callers can
|
|
29
|
+
* try the numeric / boolean comparators next.
|
|
30
|
+
*/
|
|
31
|
+
export declare function compareString(expected: string, actual: string | number | boolean, caseInsensitive: boolean): boolean | undefined;
|
|
32
|
+
//# sourceMappingURL=comparators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparators.d.ts","sourceRoot":"","sources":["../../src/constraints/comparators.ts"],"names":[],"mappings":"AA6BA,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CASzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAChC,OAAO,GAAG,SAAS,CAYrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAChC,OAAO,GAAG,SAAS,CAgBrB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EACjC,eAAe,EAAE,OAAO,GACvB,OAAO,GAAG,SAAS,CAOrB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Shared comparators used by every IDS constraint matcher.
|
|
6
|
+
*
|
|
7
|
+
* These helpers encode IDS 1.0 cast-and-compare semantics in one
|
|
8
|
+
* place so `matchSimpleValue`, `matchEnumeration`, and `matchBounds`
|
|
9
|
+
* agree — the older code had `matchEnumeration` using a looser
|
|
10
|
+
* `parseFloat` path that silently equated date-shaped strings.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A "clean" numeric literal: optional sign, digits, optional decimal,
|
|
14
|
+
* optional scientific exponent. Anchored end-to-end so trailing garbage
|
|
15
|
+
* (`'2022-01-01'`) doesn't smuggle through.
|
|
16
|
+
*/
|
|
17
|
+
const NUMERIC_RE = /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;
|
|
18
|
+
/**
|
|
19
|
+
* Numeric tolerance for floating-point comparisons.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors upstream IfcOpenShell `ifctester`'s `is_x` rules: anchored
|
|
22
|
+
* on the IDS-side cast value with a ULP-scaled fudge to absorb the
|
|
23
|
+
* floating-point noise introduced when each side is decoded from text.
|
|
24
|
+
*/
|
|
25
|
+
const RELATIVE_TOLERANCE = 1e-6;
|
|
26
|
+
export function numericEpsilon(castValue, actual) {
|
|
27
|
+
const relative = RELATIVE_TOLERANCE * (1 + Math.abs(castValue));
|
|
28
|
+
const ulp = 16 * Number.EPSILON *
|
|
29
|
+
Math.max(Math.abs(castValue), typeof actual === 'number' ? Math.abs(actual) : 0);
|
|
30
|
+
return relative + ulp;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compare an IDS literal `expected` (always a string from the XML) to
|
|
34
|
+
* `actual` as numbers. Returns:
|
|
35
|
+
* - `true` / `false` when both sides parse cleanly as numerics, OR
|
|
36
|
+
* - `undefined` when either side isn't a strict numeric literal,
|
|
37
|
+
* in which case the caller should fall back to other comparators
|
|
38
|
+
* (string equality, regex, etc.).
|
|
39
|
+
*
|
|
40
|
+
* Strictness is the whole point: `parseFloat('2022-01-01')` returns
|
|
41
|
+
* `2022`, which would silently equate dates with their year. Requiring
|
|
42
|
+
* `NUMERIC_RE.test(...)` on both sides keeps date-like strings opaque.
|
|
43
|
+
*/
|
|
44
|
+
export function compareNumeric(expected, actual) {
|
|
45
|
+
const actualStr = String(actual);
|
|
46
|
+
const expectedIsNumeric = NUMERIC_RE.test(expected);
|
|
47
|
+
const actualIsNumeric = typeof actual === 'number' || NUMERIC_RE.test(actualStr);
|
|
48
|
+
if (!expectedIsNumeric || !actualIsNumeric)
|
|
49
|
+
return undefined;
|
|
50
|
+
const expectedNum = parseFloat(expected);
|
|
51
|
+
const actualNum = typeof actual === 'number' ? actual : parseFloat(actualStr);
|
|
52
|
+
if (Number.isNaN(expectedNum) || Number.isNaN(actualNum))
|
|
53
|
+
return undefined;
|
|
54
|
+
return Math.abs(expectedNum - actualNum) <= numericEpsilon(expectedNum, actualNum);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Compare an IDS boolean literal to a stored value. Per IDS 1.0 spec
|
|
58
|
+
* the literal MUST be lowercase `true` / `false`; uppercase or
|
|
59
|
+
* numeric forms (`1` / `0`) are malformed and never match.
|
|
60
|
+
*
|
|
61
|
+
* Returns:
|
|
62
|
+
* - `true` / `false` when both sides resolve to a boolean, OR
|
|
63
|
+
* - `undefined` when neither side is a recognised boolean — caller
|
|
64
|
+
* should fall through to other comparators.
|
|
65
|
+
*/
|
|
66
|
+
export function compareBoolean(expected, actual) {
|
|
67
|
+
if (expected !== 'true' && expected !== 'false') {
|
|
68
|
+
// Expected isn't a valid boolean literal — caller falls through.
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
if (typeof actual === 'boolean') {
|
|
72
|
+
return expected === 'true' ? actual === true : actual === false;
|
|
73
|
+
}
|
|
74
|
+
if (actual === 'true' || actual === 'false') {
|
|
75
|
+
return actual === expected;
|
|
76
|
+
}
|
|
77
|
+
// Anything else against a boolean literal: malformed.
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Plain string equality with optional case-insensitive shortcut.
|
|
82
|
+
* Returns `undefined` when no decision can be made so callers can
|
|
83
|
+
* try the numeric / boolean comparators next.
|
|
84
|
+
*/
|
|
85
|
+
export function compareString(expected, actual, caseInsensitive) {
|
|
86
|
+
const actualStr = String(actual);
|
|
87
|
+
if (actualStr === expected)
|
|
88
|
+
return true;
|
|
89
|
+
if (caseInsensitive && actualStr.toUpperCase() === expected.toUpperCase()) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=comparators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comparators.js","sourceRoot":"","sources":["../../src/constraints/comparators.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;GAOG;AAEH;;;;GAIG;AACH,MAAM,UAAU,GAAG,yCAAyC,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,MAAe;IAC/D,MAAM,QAAQ,GAAG,kBAAkB,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IAChE,MAAM,GAAG,GACP,EAAE,GAAG,MAAM,CAAC,OAAO;QACnB,IAAI,CAAC,GAAG,CACN,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EACnB,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;IACJ,OAAO,QAAQ,GAAG,GAAG,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,MAAiC;IAEjC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,eAAe,GACnB,OAAO,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3D,IAAI,CAAC,iBAAiB,IAAI,CAAC,eAAe;QAAE,OAAO,SAAS,CAAC;IAE7D,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC9E,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IAE3E,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,IAAI,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,MAAiC;IAEjC,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChD,iEAAiE;QACjE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC;IAClE,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QAC5C,OAAO,MAAM,KAAK,QAAQ,CAAC;IAC7B,CAAC;IAED,sDAAsD;IACtD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,MAAiC,EACjC,eAAwB;IAExB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,SAAS,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,eAAe,IAAI,SAAS,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -2,10 +2,20 @@
|
|
|
2
2
|
* Constraint matching utilities for IDS validation
|
|
3
3
|
*/
|
|
4
4
|
import type { IDSConstraint } from '../types.js';
|
|
5
|
+
/** Options for constraint matching */
|
|
6
|
+
export interface MatchOptions {
|
|
7
|
+
/**
|
|
8
|
+
* If true, use case-insensitive comparison for string values.
|
|
9
|
+
* Per IDS 1.0 spec, only entity type names and predefined types
|
|
10
|
+
* should be compared case-insensitively. All other values
|
|
11
|
+
* (property values, classification values, etc.) are case-sensitive.
|
|
12
|
+
*/
|
|
13
|
+
caseInsensitive?: boolean;
|
|
14
|
+
}
|
|
5
15
|
/**
|
|
6
16
|
* Check if a value matches a constraint
|
|
7
17
|
*/
|
|
8
|
-
export declare function matchConstraint(constraint: IDSConstraint, actualValue: string | number | boolean | null | undefined): boolean;
|
|
18
|
+
export declare function matchConstraint(constraint: IDSConstraint, actualValue: string | number | boolean | null | undefined, options?: MatchOptions): boolean;
|
|
9
19
|
/**
|
|
10
20
|
* Get a human-readable description of why a constraint match failed
|
|
11
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constraints/index.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,EACV,aAAa,EAKd,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constraints/index.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,EACV,aAAa,EAKd,MAAM,aAAa,CAAC;AAYrB,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,aAAa,EACzB,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EACzD,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAmBT;AAmKD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,aAAa,EACzB,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GACxD,MAAM,CAiBR;AA0CD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM,CAgBlE"}
|