@ifc-lite/codegen 1.15.3 → 1.15.4

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.
@@ -6,317 +6,46 @@
6
6
  * IFC Serialization Support
7
7
  * Generated from EXPRESS schema: IFC4_ADD2_TC1
8
8
  *
9
- * Utilities for serializing IFC entities to STEP format.
9
+ * Thin binding over the shared, schema-agnostic STEP serializer in
10
+ * `@ifc-lite/data`. All serialization logic lives there (single source of
11
+ * truth); only this bundle's `SCHEMA_REGISTRY` is bound to the registry-coupled
12
+ * helpers below.
10
13
  *
11
14
  * DO NOT EDIT - This file is auto-generated
12
15
  */
13
16
 
14
17
  import { SCHEMA_REGISTRY } from './schema-registry.js';
15
-
16
- /**
17
- * STEP value types
18
- */
19
- export type StepValue =
20
- | string
21
- | number
22
- | boolean
23
- | null
24
- | undefined
25
- | StepValue[]
26
- | EntityRef
27
- | EnumValue;
28
-
29
- /**
30
- * Entity reference (#123)
31
- */
32
- export interface EntityRef {
33
- ref: number;
34
- }
35
-
36
- /**
37
- * Enum value (.VALUE.)
38
- */
39
- export interface EnumValue {
40
- enum: string;
41
- }
42
-
43
- /**
44
- * Check if value is an entity reference
45
- */
46
- export function isEntityRef(value: unknown): value is EntityRef {
47
- return typeof value === 'object' && value !== null && 'ref' in value;
48
- }
49
-
50
- /**
51
- * Check if value is an enum value
52
- */
53
- export function isEnumValue(value: unknown): value is EnumValue {
54
- return typeof value === 'object' && value !== null && 'enum' in value;
55
- }
56
-
57
- /**
58
- * Create an entity reference
59
- */
60
- export function ref(id: number): EntityRef {
61
- return { ref: id };
62
- }
63
-
64
- /**
65
- * Create an enum value
66
- */
67
- export function enumVal(value: string): EnumValue {
68
- return { enum: value };
69
- }
70
-
71
- /**
72
- * Base interface for serializable entities
73
- */
74
- export interface StepEntity {
75
- /** Express ID (#123) */
76
- expressId: number;
77
- /** IFC type name */
78
- type: string;
79
- /** Attribute values */
80
- [key: string]: unknown;
81
- }
82
-
83
- /**
84
- * Serialize a single value to STEP format
85
- */
86
- export function serializeValue(value: StepValue): string {
87
- // Null/undefined -> $
88
- if (value === null || value === undefined) {
89
- return '$';
90
- }
91
-
92
- // Derived value -> *
93
- if (value === '*') {
94
- return '*';
95
- }
96
-
97
- // Boolean
98
- if (typeof value === 'boolean') {
99
- return value ? '.T.' : '.F.';
100
- }
101
-
102
- // Number
103
- if (typeof value === 'number') {
104
- if (!Number.isFinite(value)) {
105
- return '$';
106
- }
107
- // Use exponential notation for large/small numbers
108
- if (Math.abs(value) > 1e10 || (Math.abs(value) < 1e-10 && value !== 0)) {
109
- return value.toExponential(10).toUpperCase().replace('E+', 'E');
110
- }
111
- // Otherwise use fixed notation
112
- const str = value.toString();
113
- // Ensure there's a decimal point for REAL values
114
- return str.includes('.') ? str : str + '.';
115
- }
116
-
117
- // String
118
- if (typeof value === 'string') {
119
- return "'" + escapeStepString(value) + "'";
120
- }
121
-
122
- // Entity reference
123
- if (isEntityRef(value)) {
124
- return '#' + value.ref;
125
- }
126
-
127
- // Enum value
128
- if (isEnumValue(value)) {
129
- return '.' + value.enum + '.';
130
- }
131
-
132
- // Array/List
133
- if (Array.isArray(value)) {
134
- if (value.length === 0) {
135
- return '()';
136
- }
137
- return '(' + value.map(v => serializeValue(v as StepValue)).join(',') + ')';
138
- }
139
-
140
- // Object (shouldn't happen for valid STEP values)
141
- return '$';
142
- }
143
-
144
- /**
145
- * Escape a string for STEP format
146
- */
147
- function escapeStepString(str: string): string {
148
- return str
149
- .replace(/\\/g, '\\\\') // Backslash
150
- .replace(/'/g, "''"); // Single quote
151
- }
152
-
153
- /**
154
- * Serialize an entity to a STEP line
18
+ import {
19
+ generateHeader,
20
+ generateStepFileWithRegistry,
21
+ toStepLineWithRegistry,
22
+ type StepEntity,
23
+ } from '@ifc-lite/data';
24
+
25
+ export {
26
+ isEntityRef,
27
+ isEnumValue,
28
+ ref,
29
+ enumVal,
30
+ serializeValue,
31
+ generateHeader,
32
+ parseStepValue,
33
+ } from '@ifc-lite/data';
34
+ export type { StepValue, EntityRef, EnumValue, StepEntity } from '@ifc-lite/data';
35
+
36
+ /**
37
+ * Serialize an entity to a STEP line (bound to this bundle's schema).
155
38
  */
156
39
  export function toStepLine(entity: StepEntity): string {
157
- const schema = SCHEMA_REGISTRY.entities[entity.type];
158
- if (!schema) {
159
- throw new Error(`Unknown entity type: ${entity.type}`);
160
- }
161
-
162
- // Get all attributes in order
163
- const values: string[] = [];
164
- for (const attr of schema.allAttributes) {
165
- const value = entity[attr.name];
166
- values.push(serializeValue(value as StepValue));
167
- }
168
-
169
- return `#${entity.expressId}=${entity.type.toUpperCase()}(${values.join(',')});`;
40
+ return toStepLineWithRegistry(SCHEMA_REGISTRY, entity);
170
41
  }
171
42
 
172
43
  /**
173
- * Generate STEP file header
174
- */
175
- export function generateHeader(options: {
176
- description?: string;
177
- author?: string;
178
- organization?: string;
179
- application?: string;
180
- schema: 'IFC2X3' | 'IFC4' | 'IFC4X3' | 'IFC5';
181
- filename?: string;
182
- }): string {
183
- const now = new Date().toISOString().replace(/[-:]/g, '').split('.')[0];
184
- const desc = options.description || 'ViewDefinition [CoordinationView]';
185
- const author = options.author || '';
186
- const org = options.organization || '';
187
- const app = options.application || 'ifc-lite';
188
- const filename = options.filename || 'output.ifc';
189
-
190
- return `ISO-10303-21;
191
- HEADER;
192
- FILE_DESCRIPTION('${desc}','2;1');
193
- FILE_NAME('${filename}','${now}',('${author}'),('${org}'),'${app}','${app}','');
194
- FILE_SCHEMA(('${options.schema}'));
195
- ENDSEC;
196
- `;
197
- }
198
-
199
- /**
200
- * Generate complete STEP file content
44
+ * Generate complete STEP file content (bound to this bundle's schema).
201
45
  */
202
46
  export function generateStepFile(
203
47
  entities: StepEntity[],
204
48
  options: Parameters<typeof generateHeader>[0]
205
49
  ): string {
206
- const header = generateHeader(options);
207
-
208
- // Sort entities by ID for deterministic output
209
- const sorted = [...entities].sort((a, b) => a.expressId - b.expressId);
210
-
211
- const data = sorted.map(e => toStepLine(e)).join('\n');
212
-
213
- return `${header}DATA;
214
- ${data}
215
- ENDSEC;
216
- END-ISO-10303-21;
217
- `;
218
- }
219
-
220
- /**
221
- * Parse a STEP value from string
222
- */
223
- export function parseStepValue(str: string): StepValue {
224
- str = str.trim();
225
-
226
- // Null
227
- if (str === '$') {
228
- return null;
229
- }
230
-
231
- // Derived
232
- if (str === '*') {
233
- return '*' as unknown as StepValue;
234
- }
235
-
236
- // Boolean
237
- if (str === '.T.') {
238
- return true;
239
- }
240
- if (str === '.F.') {
241
- return false;
242
- }
243
- if (str === '.U.') {
244
- return null; // Unknown/indeterminate
245
- }
246
-
247
- // Entity reference
248
- if (str.startsWith('#')) {
249
- return { ref: parseInt(str.substring(1), 10) };
250
- }
251
-
252
- // Enum
253
- if (str.startsWith('.') && str.endsWith('.')) {
254
- return { enum: str.substring(1, str.length - 1) };
255
- }
256
-
257
- // String
258
- if (str.startsWith("'") && str.endsWith("'")) {
259
- return unescapeStepString(str.substring(1, str.length - 1));
260
- }
261
-
262
- // List
263
- if (str.startsWith('(') && str.endsWith(')')) {
264
- return parseStepList(str);
265
- }
266
-
267
- // Number
268
- const num = parseFloat(str);
269
- if (!isNaN(num)) {
270
- return num;
271
- }
272
-
273
- // Unknown
274
- return str;
275
- }
276
-
277
- /**
278
- * Parse a STEP list
279
- */
280
- function parseStepList(str: string): StepValue[] {
281
- // Remove outer parentheses
282
- const inner = str.substring(1, str.length - 1).trim();
283
- if (inner === '') {
284
- return [];
285
- }
286
-
287
- const values: StepValue[] = [];
288
- let depth = 0;
289
- let current = '';
290
-
291
- for (let i = 0; i < inner.length; i++) {
292
- const char = inner[i];
293
-
294
- if (char === '(' || char === '[') {
295
- depth++;
296
- current += char;
297
- } else if (char === ')' || char === ']') {
298
- depth--;
299
- current += char;
300
- } else if (char === ',' && depth === 0) {
301
- values.push(parseStepValue(current));
302
- current = '';
303
- } else {
304
- current += char;
305
- }
306
- }
307
-
308
- if (current.trim()) {
309
- values.push(parseStepValue(current));
310
- }
311
-
312
- return values;
313
- }
314
-
315
- /**
316
- * Unescape a STEP string
317
- */
318
- function unescapeStepString(str: string): string {
319
- return str
320
- .replace(/''/g, "'")
321
- .replace(/\\\\/g, '\\');
50
+ return generateStepFileWithRegistry(SCHEMA_REGISTRY, entities, options);
322
51
  }
@@ -6,317 +6,46 @@
6
6
  * IFC Serialization Support
7
7
  * Generated from EXPRESS schema: IFC4X3_DEV_923b0514
8
8
  *
9
- * Utilities for serializing IFC entities to STEP format.
9
+ * Thin binding over the shared, schema-agnostic STEP serializer in
10
+ * `@ifc-lite/data`. All serialization logic lives there (single source of
11
+ * truth); only this bundle's `SCHEMA_REGISTRY` is bound to the registry-coupled
12
+ * helpers below.
10
13
  *
11
14
  * DO NOT EDIT - This file is auto-generated
12
15
  */
13
16
 
14
17
  import { SCHEMA_REGISTRY } from './schema-registry.js';
15
-
16
- /**
17
- * STEP value types
18
- */
19
- export type StepValue =
20
- | string
21
- | number
22
- | boolean
23
- | null
24
- | undefined
25
- | StepValue[]
26
- | EntityRef
27
- | EnumValue;
28
-
29
- /**
30
- * Entity reference (#123)
31
- */
32
- export interface EntityRef {
33
- ref: number;
34
- }
35
-
36
- /**
37
- * Enum value (.VALUE.)
38
- */
39
- export interface EnumValue {
40
- enum: string;
41
- }
42
-
43
- /**
44
- * Check if value is an entity reference
45
- */
46
- export function isEntityRef(value: unknown): value is EntityRef {
47
- return typeof value === 'object' && value !== null && 'ref' in value;
48
- }
49
-
50
- /**
51
- * Check if value is an enum value
52
- */
53
- export function isEnumValue(value: unknown): value is EnumValue {
54
- return typeof value === 'object' && value !== null && 'enum' in value;
55
- }
56
-
57
- /**
58
- * Create an entity reference
59
- */
60
- export function ref(id: number): EntityRef {
61
- return { ref: id };
62
- }
63
-
64
- /**
65
- * Create an enum value
66
- */
67
- export function enumVal(value: string): EnumValue {
68
- return { enum: value };
69
- }
70
-
71
- /**
72
- * Base interface for serializable entities
73
- */
74
- export interface StepEntity {
75
- /** Express ID (#123) */
76
- expressId: number;
77
- /** IFC type name */
78
- type: string;
79
- /** Attribute values */
80
- [key: string]: unknown;
81
- }
82
-
83
- /**
84
- * Serialize a single value to STEP format
85
- */
86
- export function serializeValue(value: StepValue): string {
87
- // Null/undefined -> $
88
- if (value === null || value === undefined) {
89
- return '$';
90
- }
91
-
92
- // Derived value -> *
93
- if (value === '*') {
94
- return '*';
95
- }
96
-
97
- // Boolean
98
- if (typeof value === 'boolean') {
99
- return value ? '.T.' : '.F.';
100
- }
101
-
102
- // Number
103
- if (typeof value === 'number') {
104
- if (!Number.isFinite(value)) {
105
- return '$';
106
- }
107
- // Use exponential notation for large/small numbers
108
- if (Math.abs(value) > 1e10 || (Math.abs(value) < 1e-10 && value !== 0)) {
109
- return value.toExponential(10).toUpperCase().replace('E+', 'E');
110
- }
111
- // Otherwise use fixed notation
112
- const str = value.toString();
113
- // Ensure there's a decimal point for REAL values
114
- return str.includes('.') ? str : str + '.';
115
- }
116
-
117
- // String
118
- if (typeof value === 'string') {
119
- return "'" + escapeStepString(value) + "'";
120
- }
121
-
122
- // Entity reference
123
- if (isEntityRef(value)) {
124
- return '#' + value.ref;
125
- }
126
-
127
- // Enum value
128
- if (isEnumValue(value)) {
129
- return '.' + value.enum + '.';
130
- }
131
-
132
- // Array/List
133
- if (Array.isArray(value)) {
134
- if (value.length === 0) {
135
- return '()';
136
- }
137
- return '(' + value.map(v => serializeValue(v as StepValue)).join(',') + ')';
138
- }
139
-
140
- // Object (shouldn't happen for valid STEP values)
141
- return '$';
142
- }
143
-
144
- /**
145
- * Escape a string for STEP format
146
- */
147
- function escapeStepString(str: string): string {
148
- return str
149
- .replace(/\\/g, '\\\\') // Backslash
150
- .replace(/'/g, "''"); // Single quote
151
- }
152
-
153
- /**
154
- * Serialize an entity to a STEP line
18
+ import {
19
+ generateHeader,
20
+ generateStepFileWithRegistry,
21
+ toStepLineWithRegistry,
22
+ type StepEntity,
23
+ } from '@ifc-lite/data';
24
+
25
+ export {
26
+ isEntityRef,
27
+ isEnumValue,
28
+ ref,
29
+ enumVal,
30
+ serializeValue,
31
+ generateHeader,
32
+ parseStepValue,
33
+ } from '@ifc-lite/data';
34
+ export type { StepValue, EntityRef, EnumValue, StepEntity } from '@ifc-lite/data';
35
+
36
+ /**
37
+ * Serialize an entity to a STEP line (bound to this bundle's schema).
155
38
  */
156
39
  export function toStepLine(entity: StepEntity): string {
157
- const schema = SCHEMA_REGISTRY.entities[entity.type];
158
- if (!schema) {
159
- throw new Error(`Unknown entity type: ${entity.type}`);
160
- }
161
-
162
- // Get all attributes in order
163
- const values: string[] = [];
164
- for (const attr of schema.allAttributes) {
165
- const value = entity[attr.name];
166
- values.push(serializeValue(value as StepValue));
167
- }
168
-
169
- return `#${entity.expressId}=${entity.type.toUpperCase()}(${values.join(',')});`;
40
+ return toStepLineWithRegistry(SCHEMA_REGISTRY, entity);
170
41
  }
171
42
 
172
43
  /**
173
- * Generate STEP file header
174
- */
175
- export function generateHeader(options: {
176
- description?: string;
177
- author?: string;
178
- organization?: string;
179
- application?: string;
180
- schema: 'IFC2X3' | 'IFC4' | 'IFC4X3' | 'IFC5';
181
- filename?: string;
182
- }): string {
183
- const now = new Date().toISOString().replace(/[-:]/g, '').split('.')[0];
184
- const desc = options.description || 'ViewDefinition [CoordinationView]';
185
- const author = options.author || '';
186
- const org = options.organization || '';
187
- const app = options.application || 'ifc-lite';
188
- const filename = options.filename || 'output.ifc';
189
-
190
- return `ISO-10303-21;
191
- HEADER;
192
- FILE_DESCRIPTION('${desc}','2;1');
193
- FILE_NAME('${filename}','${now}',('${author}'),('${org}'),'${app}','${app}','');
194
- FILE_SCHEMA(('${options.schema}'));
195
- ENDSEC;
196
- `;
197
- }
198
-
199
- /**
200
- * Generate complete STEP file content
44
+ * Generate complete STEP file content (bound to this bundle's schema).
201
45
  */
202
46
  export function generateStepFile(
203
47
  entities: StepEntity[],
204
48
  options: Parameters<typeof generateHeader>[0]
205
49
  ): string {
206
- const header = generateHeader(options);
207
-
208
- // Sort entities by ID for deterministic output
209
- const sorted = [...entities].sort((a, b) => a.expressId - b.expressId);
210
-
211
- const data = sorted.map(e => toStepLine(e)).join('\n');
212
-
213
- return `${header}DATA;
214
- ${data}
215
- ENDSEC;
216
- END-ISO-10303-21;
217
- `;
218
- }
219
-
220
- /**
221
- * Parse a STEP value from string
222
- */
223
- export function parseStepValue(str: string): StepValue {
224
- str = str.trim();
225
-
226
- // Null
227
- if (str === '$') {
228
- return null;
229
- }
230
-
231
- // Derived
232
- if (str === '*') {
233
- return '*' as unknown as StepValue;
234
- }
235
-
236
- // Boolean
237
- if (str === '.T.') {
238
- return true;
239
- }
240
- if (str === '.F.') {
241
- return false;
242
- }
243
- if (str === '.U.') {
244
- return null; // Unknown/indeterminate
245
- }
246
-
247
- // Entity reference
248
- if (str.startsWith('#')) {
249
- return { ref: parseInt(str.substring(1), 10) };
250
- }
251
-
252
- // Enum
253
- if (str.startsWith('.') && str.endsWith('.')) {
254
- return { enum: str.substring(1, str.length - 1) };
255
- }
256
-
257
- // String
258
- if (str.startsWith("'") && str.endsWith("'")) {
259
- return unescapeStepString(str.substring(1, str.length - 1));
260
- }
261
-
262
- // List
263
- if (str.startsWith('(') && str.endsWith(')')) {
264
- return parseStepList(str);
265
- }
266
-
267
- // Number
268
- const num = parseFloat(str);
269
- if (!isNaN(num)) {
270
- return num;
271
- }
272
-
273
- // Unknown
274
- return str;
275
- }
276
-
277
- /**
278
- * Parse a STEP list
279
- */
280
- function parseStepList(str: string): StepValue[] {
281
- // Remove outer parentheses
282
- const inner = str.substring(1, str.length - 1).trim();
283
- if (inner === '') {
284
- return [];
285
- }
286
-
287
- const values: StepValue[] = [];
288
- let depth = 0;
289
- let current = '';
290
-
291
- for (let i = 0; i < inner.length; i++) {
292
- const char = inner[i];
293
-
294
- if (char === '(' || char === '[') {
295
- depth++;
296
- current += char;
297
- } else if (char === ')' || char === ']') {
298
- depth--;
299
- current += char;
300
- } else if (char === ',' && depth === 0) {
301
- values.push(parseStepValue(current));
302
- current = '';
303
- } else {
304
- current += char;
305
- }
306
- }
307
-
308
- if (current.trim()) {
309
- values.push(parseStepValue(current));
310
- }
311
-
312
- return values;
313
- }
314
-
315
- /**
316
- * Unescape a STEP string
317
- */
318
- function unescapeStepString(str: string): string {
319
- return str
320
- .replace(/''/g, "'")
321
- .replace(/\\\\/g, '\\');
50
+ return generateStepFileWithRegistry(SCHEMA_REGISTRY, entities, options);
322
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/codegen",
3
- "version": "1.15.3",
3
+ "version": "1.15.4",
4
4
  "description": "TypeScript code generator from IFC EXPRESS schemas",
5
5
  "type": "module",
6
6
  "repository": {
@@ -19,10 +19,11 @@
19
19
  "author": "",
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "commander": "^15.0.0"
22
+ "commander": "^15.0.0",
23
+ "@ifc-lite/data": "^2.1.0"
23
24
  },
24
25
  "devDependencies": {
25
- "@types/node": "^25.9.1",
26
+ "@types/node": "^25.9.3",
26
27
  "typescript": "^6.0.3",
27
28
  "vitest": "^4.1.0"
28
29
  },
@@ -31,7 +32,7 @@
31
32
  "dev": "pnpm exec tsc --watch",
32
33
  "test": "vitest run",
33
34
  "generate": "node dist/cli.js",
34
- "generate:ifc4": "node dist/cli.js schemas/IFC4.exp -o generated/ifc4",
35
+ "generate:ifc4": "node dist/cli.js schemas/IFC4_ADD2_TC1.exp -o generated/ifc4",
35
36
  "generate:ifc4x3": "node dist/cli.js schemas/IFC4X3.exp -o generated/ifc4x3"
36
37
  }
37
38
  }