@bldrs-ai/conway 0.7.766 → 0.8.782

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 (67) hide show
  1. package/README.md +30 -31
  2. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +1 -1
  3. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +1 -1
  4. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts +19 -0
  5. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
  6. package/compiled/dependencies/conway-geom/interface/conway_geometry.js +31 -0
  7. package/compiled/dependencies/conway-geom/interface/geometry_object.d.ts +4 -0
  8. package/compiled/dependencies/conway-geom/interface/geometry_object.d.ts.map +1 -1
  9. package/compiled/dependencies/conway-geom/interface/parameters/params_get_boolean_result.d.ts +1 -0
  10. package/compiled/dependencies/conway-geom/interface/parameters/params_get_boolean_result.d.ts.map +1 -1
  11. package/compiled/dependencies/conway-geom/interface/parse_buffer.d.ts +11 -0
  12. package/compiled/dependencies/conway-geom/interface/parse_buffer.d.ts.map +1 -0
  13. package/compiled/dependencies/conway-geom/interface/parse_buffer.js +1 -0
  14. package/compiled/src/AP214E3_2010/ap214_command_line_main.js +11 -13
  15. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +0 -1
  16. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +15 -13
  17. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
  18. package/compiled/src/AP214E3_2010/ap214_step_model.test.js +12 -1
  19. package/compiled/src/AP214E3_2010/ap214_step_parser.d.ts.map +1 -1
  20. package/compiled/src/core/canonical_mesh.d.ts +1 -1
  21. package/compiled/src/core/canonical_mesh.d.ts.map +1 -1
  22. package/compiled/src/core/geometry_aggregator.test.js +7 -7
  23. package/compiled/src/core/packed_mesh.test.js +4 -4
  24. package/compiled/src/ifc/ifc_command_line_main.js +17 -16
  25. package/compiled/src/ifc/ifc_geometry_extraction.d.ts +6 -4
  26. package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
  27. package/compiled/src/ifc/ifc_geometry_extraction.js +107 -102
  28. package/compiled/src/ifc/ifc_geometry_extraction.test.js +4 -4
  29. package/compiled/src/ifc/ifc_model_geometry.d.ts +4 -0
  30. package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
  31. package/compiled/src/ifc/ifc_model_geometry.js +13 -0
  32. package/compiled/src/ifc/ifc_property_extraction.test.js +12 -1
  33. package/compiled/src/ifc/ifc_regression_main.js +5 -3
  34. package/compiled/src/ifc/ifc_scene_builder.test.js +11 -8
  35. package/compiled/src/ifc/ifc_step_model.d.ts +1 -0
  36. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  37. package/compiled/src/ifc/ifc_step_model.js +1 -0
  38. package/compiled/src/ifc/ifc_step_model.test.js +12 -1
  39. package/compiled/src/ifc/ifc_step_parser.d.ts +1 -0
  40. package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
  41. package/compiled/src/ifc/ifc_step_parser.js +1 -0
  42. package/compiled/src/step/parsing/step_deserialization_functions.d.ts +1 -1
  43. package/compiled/src/step/parsing/step_deserialization_functions.d.ts.map +1 -1
  44. package/compiled/src/step/parsing/step_deserialization_functions.js +1 -1
  45. package/compiled/src/step/parsing/step_parser.d.ts +1 -1
  46. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  47. package/compiled/src/step/parsing/step_parser.js +3 -3
  48. package/compiled/src/step/parsing/step_vtable_builder.d.ts +4 -3
  49. package/compiled/src/step/parsing/step_vtable_builder.d.ts.map +1 -1
  50. package/compiled/src/step/parsing/step_vtable_builder.js +5 -4
  51. package/compiled/src/step/step_entity_base.d.ts +27 -2
  52. package/compiled/src/step/step_entity_base.d.ts.map +1 -1
  53. package/compiled/src/step/step_entity_base.js +77 -15
  54. package/compiled/src/step/step_entity_internal_reference.d.ts +1 -0
  55. package/compiled/src/step/step_entity_internal_reference.d.ts.map +1 -1
  56. package/compiled/src/step/step_external_mapping.test.js +12 -1
  57. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  58. package/compiled/src/step/step_model_base.js +1 -0
  59. package/compiled/src/version/version.js +1 -1
  60. package/compiled/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +6 -1
  62. package/compiled/src/examples/browser.d.ts +0 -3
  63. package/compiled/src/examples/browser.d.ts.map +0 -1
  64. package/compiled/src/examples/browser.js +0 -388
  65. package/compiled/src/examples/validator.d.ts +0 -8
  66. package/compiled/src/examples/validator.d.ts.map +0 -1
  67. package/compiled/src/examples/validator.js +0 -378
@@ -1,378 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * IFC Model Validator
4
- *
5
- * See the project README or the validator.md for details.
6
- */
7
- import { exit } from 'process';
8
- import fs from 'fs';
9
- import IfcStepParser from '../ifc/ifc_step_parser';
10
- import ParsingBuffer from '../parsing/parsing_buffer';
11
- import { ParseResult } from '../step/parsing/step_parser';
12
- import EntityTypesIfc from '../ifc/ifc4_gen/entity_types_ifc.gen';
13
- import Logger from '../logging/logger';
14
- import Environment from '../utilities/environment';
15
- // ---------------------------------------------------------------------
16
- // 1. Parse Command-Line Args
17
- // ---------------------------------------------------------------------
18
- Environment.checkEnvironment();
19
- Logger.initializeWasmCallbacks();
20
- const maxCommandArgs = 4;
21
- if (process.argv.length < maxCommandArgs) {
22
- // eslint-disable-next-line max-len
23
- console.error(`Usage: validator <path_to_model>.ifc "IFCCLASS[#OptionalID].property <operator> value"`);
24
- exit(1);
25
- }
26
- const modelPath = process.argv[2];
27
- const query = process.argv[3];
28
- // ---------------------------------------------------------------------
29
- // 2. Load & Parse the IFC
30
- // ---------------------------------------------------------------------
31
- let ifcBuffer;
32
- try {
33
- ifcBuffer = fs.readFileSync(modelPath);
34
- }
35
- catch (err) {
36
- Logger.error(`Error reading "${modelPath}": ${err}`);
37
- exit(1);
38
- }
39
- Logger.createStatistics(0);
40
- const parser = IfcStepParser.Instance;
41
- const bufferInput = new ParsingBuffer(ifcBuffer);
42
- // eslint-disable-next-line no-unused-vars
43
- const [stepHeader, resultHeader] = parser.parseHeader(bufferInput);
44
- const [parseResult, model] = parser.parseDataToModel(bufferInput);
45
- switch (parseResult) {
46
- case ParseResult.COMPLETE:
47
- break;
48
- case ParseResult.INCOMPLETE:
49
- Logger.warning('Parse incomplete but no errors reported.');
50
- break;
51
- case ParseResult.INVALID_STEP:
52
- Logger.error('Invalid STEP detected.');
53
- exit(1);
54
- break;
55
- case ParseResult.MISSING_TYPE:
56
- Logger.error('Missing STEP type.');
57
- exit(1);
58
- break;
59
- case ParseResult.SYNTAX_ERROR:
60
- Logger.error(`Syntax error at line ${bufferInput.lineCount}.`);
61
- exit(1);
62
- break;
63
- default:
64
- }
65
- if (!model) {
66
- Logger.error('Failed to load model.');
67
- exit(1);
68
- }
69
- // ---------------------------------------------------------------------
70
- // 3. Build arrays for IFC classes & entity types
71
- // ---------------------------------------------------------------------
72
- const nonEmptyTypeIDNoSubtypes = model.nonEmptyTypeIDs();
73
- const ifcClasses = Array.from(nonEmptyTypeIDNoSubtypes || []).map((item) => String(EntityTypesIfc[item]));
74
- const entityTypes = Array.from(nonEmptyTypeIDNoSubtypes || []);
75
- /**
76
- * Parses a query string used for querying IFC classes, properties, and values.
77
- *
78
- * @param {string} query_ - The query string to be parsed.
79
- * @return {ParsedQuery} An object containing:
80
- * @throws {Error} If the query string contains multiple operators or has an invalid format.
81
- */
82
- function parseQueryString(query_) {
83
- // This pattern finds any of these operators: <= >= < > == != === !==
84
- const operatorPatternGlobal = /(<=|>=|<|>|==|!=|===|!==)/g;
85
- const matches = [...query_.matchAll(operatorPatternGlobal)];
86
- if (matches.length > 1) {
87
- // If we detect more than 1 operator, we stop and notify the user
88
- const found = matches.map((m) => m[0]).join(' ');
89
- throw new Error(`Multiple operators found in query: ${found}`);
90
- }
91
- // Now handle the single operator (or none) with your existing logic
92
- if (matches.length === 1) {
93
- // e.g. "IFCWINDOW.OverallHeight <= 5"
94
- // operator = "<="
95
- // we can split around that operator or do a single match pattern
96
- const operatorPattern = /\s(<=|>=|<|>|==|!=|===|!==)\s/;
97
- const opMatch = query_.match(operatorPattern);
98
- if (!opMatch) {
99
- throw new Error(`Could not split query around operator.`);
100
- }
101
- const operator = opMatch[1];
102
- // Split out the left and right sides
103
- const parts = query_.split(operatorPattern).map((s) => s.trim()).filter(Boolean);
104
- // e.g. ["IFCWINDOW.OverallHeight", "<=", "5"]
105
- // eslint-disable-next-line no-magic-numbers
106
- if (parts.length < 3) {
107
- throw new Error(`Invalid query format around operator "${operator}"`);
108
- }
109
- const classAndPropPart = parts[0];
110
- // eslint-disable-next-line no-magic-numbers
111
- const valueStr = parts.slice(2).join(' '); // e.g. "5" (or "myStringValue")
112
- // parse left side => "IFCWINDOW.OverallHeight"
113
- const match = classAndPropPart.match(/^([A-Za-z0-9_]+)(\[#(\d+)\])?(?:\.(.+))?$/);
114
- if (!match) {
115
- throw new Error(`Invalid left side: "${classAndPropPart}"`);
116
- }
117
- const classNameRaw = match[1].toUpperCase();
118
- const expressIDStr = match[3];
119
- const propertyName = match[4];
120
- let expressID;
121
- if (expressIDStr !== undefined) {
122
- expressID = parseInt(expressIDStr, 10);
123
- }
124
- return {
125
- className: classNameRaw,
126
- expressID,
127
- property: propertyName,
128
- operator,
129
- value: valueStr,
130
- };
131
- }
132
- else {
133
- // No operator => user might just be checking for "IFCWINDOW" or "IFCWINDOW[#15].Height"
134
- // We'll parse that similarly:
135
- const match = query_.match(/^([A-Za-z0-9_]+)(\[#(\d+)\])?(?:\.(.+))?$/);
136
- if (!match) {
137
- throw new Error(`Invalid query format (no operator, unable to parse): "${query_}"`);
138
- }
139
- const classNameRaw = match[1].toUpperCase();
140
- const expressIDStr = match[3];
141
- const propertyName = match[4];
142
- let expressID;
143
- if (expressIDStr !== undefined) {
144
- expressID = parseInt(expressIDStr, 10);
145
- }
146
- // Return with no operator or value
147
- return {
148
- className: classNameRaw,
149
- expressID,
150
- property: propertyName,
151
- operator: undefined,
152
- value: undefined,
153
- };
154
- }
155
- }
156
- // ---------------------------------------------------------------------
157
- // 5. Utility to read a property from an IFC entity
158
- // We want "entity[propertyName]" or entity.orderedFields, but ignoring case
159
- // ---------------------------------------------------------------------
160
- /**
161
- * Retrieves an array of local fields from the given IFC entity along with
162
- * their descriptions and associated data.
163
- *
164
- * @param {StepEntityBase<EntityTypesIfc>} entity - The IFC entity from which
165
- * to extract fields and their data.
166
- * @return {[string, EntityFieldDescription<EntityTypesIfc>, unknown][]}
167
- * An array of tuples, where each tuple contains:
168
- * - The field name as a string.
169
- * - The field description object.
170
- * - The associated data for the field.
171
- */
172
- function getLocalFieldsWithData(entity) {
173
- return entity.orderedFields.reduce((acc, [fieldName, fieldDesc]) => {
174
- try {
175
- // Attempt to access the field
176
- const data = entity[fieldName];
177
- acc.push([fieldName, fieldDesc, data]);
178
- }
179
- catch (err) {
180
- // If an error occurs while accessing the field, skip it
181
- // Optionally, log or handle the error:
182
- // console.warn(`Skipping field ${fieldName}: ${err}`);
183
- }
184
- return acc;
185
- }, []);
186
- }
187
- /**
188
- * Retrieves the value of a specified property from the given IFC entity.
189
- *
190
- * @param {StepEntityBase<EntityTypesIfc>} entity - The IFC entity containing the property.
191
- * @param {string} propertyName - The name of the property to retrieve
192
- * @return {any} The value of the specified property, or `undefined`
193
- * if the property is not found.
194
- */
195
- function getPropertyValue(entity, propertyName) {
196
- // We do a case-insensitive match on the name
197
- const fields = getLocalFieldsWithData(entity);
198
- const found = fields.find(([fName]) => fName.toLowerCase() === propertyName.toLowerCase());
199
- if (!found) {
200
- return undefined;
201
- }
202
- // eslint-disable-next-line no-unused-vars
203
- const [_, _desc, data] = found;
204
- // If it's an array, you might want to handle it specifically.
205
- // For example, returning the first element or the entire array.
206
- // For now, let's just return the raw data.
207
- return data;
208
- }
209
- // ---------------------------------------------------------------------
210
- // 6. Perform Validation
211
- // ---------------------------------------------------------------------
212
- /**
213
- * Validates an IFC model against a parsed query to check class existence,
214
- * property values, or specific conditions.
215
- *
216
- * @param {IfcStepModel} model_ - The IFC model to validate.
217
- * @param {ParsedQuery} query_ - The parsed query containing class, property,
218
- * and condition details.
219
- * @return {void} Outputs validation results directly to the console.
220
- *
221
- * - Checks if the specified class and instance(s) exist in the model.
222
- * - Validates property existence or evaluates conditions using operators and values.
223
- * - Provides a summary of passing and failing entities.
224
- */
225
- function validateModel(model_, query_) {
226
- const { className, expressID, property, operator, value } = query_;
227
- // 1) Check if the class exists in the model
228
- const clsIndex = ifcClasses.indexOf(className);
229
- if (clsIndex < 0) {
230
- console.error(`❌ IFC class "${className}" does not exist in this model.`);
231
- return;
232
- }
233
- // Get the type + constructor
234
- const elementTypeID = entityTypes[clsIndex];
235
- const ctor = model_.schema.constructors[elementTypeID];
236
- if (!ctor) {
237
- console.error(`❌ IFC class "${className}" not recognized in schema (missing constructor).`);
238
- return;
239
- }
240
- // 2) Gather relevant entities
241
- let entities = [];
242
- if (expressID !== undefined) {
243
- // Single entity check
244
- const all = Array.from(model_.types(ctor));
245
- const found = all.find((e) => e.expressID === expressID);
246
- if (!found) {
247
- console.error(`❌ No instance with Express ID #${expressID} found for class ${className}`);
248
- return;
249
- }
250
- entities.push(found);
251
- }
252
- else {
253
- // Convert the iterator to an array explicitly
254
- const allEntities = Array.from(model_.types(ctor));
255
- if (!allEntities.length) {
256
- console.error(`❌ No instances of class "${className}" found in model.`);
257
- return;
258
- }
259
- entities = allEntities;
260
- }
261
- // If user only specified className (and possibly ID), with no property or operator =>
262
- // That might mean "check existence" or do nothing but list them.
263
- if (!property && !operator && !value) {
264
- console.log(`✅ Found ${entities.length} instance(s) of ${className}:`);
265
- for (const e of entities) {
266
- const id = e.expressID;
267
- console.log(` - ${className}[#${id}]`);
268
- }
269
- return;
270
- }
271
- if (property && !operator) {
272
- console.log(`Checking if property "${property}" exists on ${className}`);
273
- let passCount = 0;
274
- for (const e of entities) {
275
- const id = e.expressID;
276
- const val = getPropertyValue(e, property);
277
- if (val !== undefined) {
278
- passCount++;
279
- console.log(` ✔️ ${className}[#${id}] has .${property} = ${JSON.stringify(val)}`);
280
- }
281
- else {
282
- console.log(` ❌ ${className}[#${id}] has no .${property}`);
283
- }
284
- }
285
- console.log(`\nProperty existence check: ${passCount} / ${entities.length} have property "${property}"`);
286
- return;
287
- }
288
- // Otherwise, user specified property + operator + value => do a pass/fail
289
- if (!property || !operator || value === undefined) {
290
- console.error(`❌ Invalid query format. Please provide "Class.Property <operator> <value>"`);
291
- return;
292
- }
293
- const numericValue = tryParseNumber(value);
294
- // eslint-disable-next-line no-unused-vars
295
- const isNumeric = numericValue !== null;
296
- let passCount = 0;
297
- let failCount = 0;
298
- const passes = [];
299
- const fails = [];
300
- console.log(`\nValidation Report for Query: ${className}${expressID !==
301
- undefined ? `[#${expressID}]` : ''}.${property} ${operator} ${value}`);
302
- for (const e of entities) {
303
- const id = e.expressID;
304
- const propVal = getPropertyValue(e, property);
305
- // If property is undefined => automatically fail
306
- if (propVal === undefined || propVal === null) {
307
- fails.push({ id, propVal, reason: `no "${property}" property` });
308
- failCount++;
309
- continue;
310
- }
311
- const leftSide = JSON.stringify(propVal);
312
- const rightSide = value;
313
- let pass;
314
- try {
315
- const expression = `${leftSide} ${operator} ${rightSide}`;
316
- // eslint-disable-next-line no-eval
317
- pass = eval(expression);
318
- }
319
- catch (err) {
320
- fails.push({ id, propVal, reason: `eval error: ${err}` });
321
- failCount++;
322
- continue;
323
- }
324
- if (pass) {
325
- passes.push({ id, propVal });
326
- passCount++;
327
- }
328
- else {
329
- fails.push({ id, propVal,
330
- reason: `failed comparison (${property}: ${JSON.stringify(propVal)})` });
331
- failCount++;
332
- }
333
- }
334
- // Sort by expressID
335
- passes.sort((a, b) => a.id - b.id);
336
- fails.sort((a, b) => a.id - b.id);
337
- // Print passes
338
- console.log(`\n✔️ Passing Entries:`);
339
- for (const { id, propVal } of passes) {
340
- console.log(`✔️ ${className}[#${id}] => PASSED (${property}: ${JSON.stringify(propVal)})`);
341
- }
342
- // Print fails
343
- console.log(`\n❌ Failing Entries:`);
344
- // eslint-disable-next-line no-unused-vars
345
- for (const { id, propVal, reason } of fails) {
346
- console.log(`❌ ${className}[#${id}] => FAILED (${reason})`);
347
- }
348
- // Summary
349
- console.log(`\n✅ Total Passing: ${passCount}`);
350
- console.log(`❌ Total Failing: ${failCount}`);
351
- }
352
- /**
353
- * Attempts to parse a given string as a number, returning `null` if the parsing fails.
354
- *
355
- * @param {string} text - The input string to be parsed.
356
- * @return {number | null} The parsed number, or `null` if the input is not a valid number.
357
- */
358
- function tryParseNumber(text) {
359
- // e.g. "3.14" => 3.14
360
- // e.g. "5" => 5
361
- // e.g. "abc" => null
362
- // We also want to ignore quotes like "3.14" => might become NaN if we don't strip them
363
- const cleaned = text.trim().replace(/^['"]+|['"]+$/g, ''); // remove surrounding quotes
364
- const val = parseFloat(cleaned);
365
- return Number.isNaN(val) ? null : val;
366
- }
367
- // ---------------------------------------------------------------------
368
- // 7. Run the validator
369
- // ---------------------------------------------------------------------
370
- let parsedQuery;
371
- try {
372
- parsedQuery = parseQueryString(query);
373
- }
374
- catch (err) {
375
- console.error(`❌ Error parsing query: ${err.message}`);
376
- exit(1);
377
- }
378
- validateModel(model, parsedQuery);