create-ifc-lite 1.6.0 → 1.7.0

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.
@@ -0,0 +1,613 @@
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 { mkdirSync, writeFileSync } from 'fs';
5
+ import { join } from 'path';
6
+ import { getLatestVersion } from '../utils/config-fixers.js';
7
+ /**
8
+ * Scaffold a Docker-based IFC processing server with TypeScript client examples.
9
+ */
10
+ export function createServerTemplate(targetDir, projectName) {
11
+ const latestVersion = getLatestVersion();
12
+ // docker-compose.yml - Production configuration
13
+ writeFileSync(join(targetDir, 'docker-compose.yml'), `# IFC-Lite Server - Production Configuration
14
+ # Start with: docker compose up -d
15
+
16
+ services:
17
+ ifc-server:
18
+ image: ghcr.io/louistrue/ifc-lite-server:latest
19
+ container_name: ${projectName}-server
20
+ ports:
21
+ - "\${PORT:-3001}:8080"
22
+ volumes:
23
+ - ifc-cache:/app/cache
24
+ environment:
25
+ - RUST_LOG=\${RUST_LOG:-info}
26
+ - MAX_FILE_SIZE_MB=\${MAX_FILE_SIZE_MB:-500}
27
+ - REQUEST_TIMEOUT_SECS=\${REQUEST_TIMEOUT_SECS:-300}
28
+ - WORKER_THREADS=\${WORKER_THREADS:-4}
29
+ - INITIAL_BATCH_SIZE=\${INITIAL_BATCH_SIZE:-100}
30
+ - MAX_BATCH_SIZE=\${MAX_BATCH_SIZE:-1000}
31
+ - CACHE_MAX_AGE_DAYS=\${CACHE_MAX_AGE_DAYS:-7}
32
+ healthcheck:
33
+ test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/health"]
34
+ interval: 30s
35
+ timeout: 3s
36
+ retries: 3
37
+ start_period: 5s
38
+ restart: unless-stopped
39
+
40
+ volumes:
41
+ ifc-cache:
42
+ name: ${projectName}-cache
43
+ `);
44
+ // docker-compose.dev.yml - Development configuration with live logs
45
+ writeFileSync(join(targetDir, 'docker-compose.dev.yml'), `# IFC-Lite Server - Development Configuration
46
+ # Start with: docker compose -f docker-compose.dev.yml up
47
+
48
+ services:
49
+ ifc-server:
50
+ image: ghcr.io/louistrue/ifc-lite-server:latest
51
+ container_name: ${projectName}-server-dev
52
+ ports:
53
+ - "\${PORT:-3001}:8080"
54
+ volumes:
55
+ - ./cache:/app/cache # Local cache directory for inspection
56
+ environment:
57
+ - RUST_LOG=debug,tower_http=debug,ifc_lite_server=debug
58
+ - MAX_FILE_SIZE_MB=\${MAX_FILE_SIZE_MB:-500}
59
+ - REQUEST_TIMEOUT_SECS=\${REQUEST_TIMEOUT_SECS:-300}
60
+ - WORKER_THREADS=\${WORKER_THREADS:-4}
61
+ - INITIAL_BATCH_SIZE=\${INITIAL_BATCH_SIZE:-100}
62
+ - MAX_BATCH_SIZE=\${MAX_BATCH_SIZE:-1000}
63
+ - CACHE_MAX_AGE_DAYS=\${CACHE_MAX_AGE_DAYS:-30}
64
+ # No restart in dev - easier to debug
65
+ `);
66
+ // .env.example - Documented environment variables
67
+ writeFileSync(join(targetDir, '.env.example'), `# IFC-Lite Server Configuration
68
+ # Copy this file to .env and modify as needed
69
+
70
+ # =============================================================================
71
+ # SERVER SETTINGS
72
+ # =============================================================================
73
+
74
+ # Port to expose the server on (maps to internal port 8080)
75
+ PORT=3001
76
+
77
+ # Log level: error, warn, info, debug, trace
78
+ # Use "debug" for development, "info" for production
79
+ RUST_LOG=info
80
+
81
+ # =============================================================================
82
+ # FILE PROCESSING
83
+ # =============================================================================
84
+
85
+ # Maximum IFC file size in megabytes
86
+ # Larger files need more memory and processing time
87
+ MAX_FILE_SIZE_MB=500
88
+
89
+ # Request timeout in seconds
90
+ # Increase for very large files (500MB+)
91
+ REQUEST_TIMEOUT_SECS=300
92
+
93
+ # Number of worker threads for parallel geometry processing
94
+ # Default: number of CPU cores
95
+ # Reduce if running alongside other services
96
+ WORKER_THREADS=4
97
+
98
+ # =============================================================================
99
+ # STREAMING (Progressive Rendering)
100
+ # =============================================================================
101
+
102
+ # Initial batch size for fast first frame (first 3 batches)
103
+ # Smaller = faster first render, but more HTTP overhead
104
+ INITIAL_BATCH_SIZE=100
105
+
106
+ # Maximum batch size for throughput (batches 11+)
107
+ # Larger = better throughput, but longer waits between updates
108
+ MAX_BATCH_SIZE=1000
109
+
110
+ # =============================================================================
111
+ # CACHING
112
+ # =============================================================================
113
+
114
+ # How long to keep cached results (in days)
115
+ # Cached files are served instantly without reprocessing
116
+ CACHE_MAX_AGE_DAYS=7
117
+ `);
118
+ // Copy .env.example to .env
119
+ writeFileSync(join(targetDir, '.env'), `# IFC-Lite Server Configuration
120
+ # See .env.example for all available options with documentation
121
+
122
+ PORT=3001
123
+ RUST_LOG=info
124
+ MAX_FILE_SIZE_MB=500
125
+ WORKER_THREADS=4
126
+ `);
127
+ // .gitignore
128
+ writeFileSync(join(targetDir, '.gitignore'), `# Dependencies
129
+ node_modules/
130
+
131
+ # Build output
132
+ dist/
133
+
134
+ # Environment files (keep .env.example)
135
+ .env
136
+ .env.local
137
+ .env.*.local
138
+
139
+ # Cache directory (when using dev compose)
140
+ cache/
141
+
142
+ # IDE
143
+ .idea/
144
+ .vscode/
145
+ *.swp
146
+ *.swo
147
+
148
+ # OS
149
+ .DS_Store
150
+ Thumbs.db
151
+
152
+ # Logs
153
+ *.log
154
+ npm-debug.log*
155
+ `);
156
+ // .dockerignore
157
+ writeFileSync(join(targetDir, '.dockerignore'), `node_modules
158
+ dist
159
+ .git
160
+ .gitignore
161
+ *.md
162
+ .env
163
+ .env.*
164
+ cache
165
+ `);
166
+ // package.json
167
+ writeFileSync(join(targetDir, 'package.json'), JSON.stringify({
168
+ name: projectName,
169
+ version: '0.1.0',
170
+ type: 'module',
171
+ description: 'IFC processing server with TypeScript client',
172
+ scripts: {
173
+ 'example': 'npx tsx src/example.ts',
174
+ 'example:stream': 'npx tsx src/example-stream.ts',
175
+ 'server:start': 'docker compose up -d',
176
+ 'server:stop': 'docker compose down',
177
+ 'server:logs': 'docker compose logs -f',
178
+ 'server:dev': 'docker compose -f docker-compose.dev.yml up',
179
+ 'build': 'tsc',
180
+ 'typecheck': 'tsc --noEmit',
181
+ },
182
+ dependencies: {
183
+ '@ifc-lite/server-client': latestVersion,
184
+ },
185
+ devDependencies: {
186
+ 'typescript': '^5.3.0',
187
+ 'tsx': '^4.0.0',
188
+ '@types/node': '^20.0.0',
189
+ },
190
+ optionalDependencies: {
191
+ 'parquet-wasm': '^0.6.0',
192
+ 'apache-arrow': '^17.0.0',
193
+ },
194
+ }, null, 2));
195
+ // tsconfig.json
196
+ writeFileSync(join(targetDir, 'tsconfig.json'), JSON.stringify({
197
+ compilerOptions: {
198
+ target: 'ES2022',
199
+ module: 'ESNext',
200
+ moduleResolution: 'bundler',
201
+ strict: true,
202
+ esModuleInterop: true,
203
+ skipLibCheck: true,
204
+ outDir: 'dist',
205
+ declaration: true,
206
+ lib: ['ES2022'],
207
+ },
208
+ include: ['src'],
209
+ exclude: ['node_modules', 'dist'],
210
+ }, null, 2));
211
+ // Create src directory
212
+ mkdirSync(join(targetDir, 'src'));
213
+ // src/example.ts - Basic client example
214
+ writeFileSync(join(targetDir, 'src', 'example.ts'), `/**
215
+ * IFC-Lite Server Client Example
216
+ *
217
+ * This example demonstrates how to use the IFC-Lite server to parse IFC files.
218
+ * The server handles heavy geometry processing, caching, and streaming.
219
+ *
220
+ * Prerequisites:
221
+ * 1. Start the server: docker compose up -d
222
+ * 2. Run this example: npm run example
223
+ */
224
+
225
+ import { IfcServerClient } from '@ifc-lite/server-client';
226
+ import { readFileSync, existsSync } from 'fs';
227
+
228
+ // Server URL - matches docker-compose.yml port mapping
229
+ const SERVER_URL = process.env.SERVER_URL || 'http://localhost:3001';
230
+
231
+ async function main() {
232
+ // Initialize client
233
+ const client = new IfcServerClient({
234
+ baseUrl: SERVER_URL,
235
+ timeout: 300000, // 5 minutes for large files
236
+ });
237
+
238
+ // Check server health
239
+ console.log('Checking server health...');
240
+ try {
241
+ const health = await client.health();
242
+ console.log(\`Server status: \${health.status}\`);
243
+ console.log(\`Server version: \${health.version || 'unknown'}\`);
244
+ } catch (error) {
245
+ console.error('Failed to connect to server. Is it running?');
246
+ console.error('Start it with: docker compose up -d');
247
+ process.exit(1);
248
+ }
249
+
250
+ // Get IFC file path from command line or use default
251
+ const ifcPath = process.argv[2];
252
+
253
+ if (!ifcPath) {
254
+ console.log(\`
255
+ Usage: npm run example <path-to-ifc-file>
256
+
257
+ Example:
258
+ npm run example ./model.ifc
259
+
260
+ The server will:
261
+ 1. Check if the file is already cached (instant response)
262
+ 2. If not cached, parse and process geometry
263
+ 3. Cache the result for future requests
264
+ 4. Return geometry data ready for rendering
265
+ \`);
266
+ return;
267
+ }
268
+
269
+ if (!existsSync(ifcPath)) {
270
+ console.error(\`File not found: \${ifcPath}\`);
271
+ process.exit(1);
272
+ }
273
+
274
+ // Read IFC file
275
+ console.log(\`\\nParsing: \${ifcPath}\`);
276
+ const buffer = readFileSync(ifcPath);
277
+ console.log(\`File size: \${(buffer.length / 1024 / 1024).toFixed(2)} MB\`);
278
+
279
+ // Parse with Parquet format (most efficient)
280
+ console.log('\\nSending to server...');
281
+ const startTime = performance.now();
282
+
283
+ try {
284
+ // Check if Parquet is available (optional dependency)
285
+ const parquetAvailable = await client.isParquetSupported();
286
+
287
+ if (parquetAvailable) {
288
+ console.log('Using Parquet format (15x smaller than JSON)');
289
+ const result = await client.parseParquet(buffer);
290
+
291
+ const elapsed = performance.now() - startTime;
292
+ console.log(\`\\nParsing complete in \${elapsed.toFixed(0)}ms\`);
293
+ console.log(\` Cache key: \${result.cache_key.substring(0, 16)}...\`);
294
+ console.log(\` Meshes: \${result.meshes.length}\`);
295
+ console.log(\` Payload size: \${(result.parquet_stats.payload_size / 1024).toFixed(1)} KB\`);
296
+ console.log(\` Decode time: \${result.parquet_stats.decode_time_ms}ms\`);
297
+
298
+ if (result.stats) {
299
+ console.log(\`\\nServer stats:\`);
300
+ console.log(\` Parse time: \${result.stats.parse_time_ms}ms\`);
301
+ console.log(\` Geometry time: \${result.stats.geometry_time_ms}ms\`);
302
+ console.log(\` Total triangles: \${result.stats.total_triangles}\`);
303
+ }
304
+
305
+ // Show sample mesh data
306
+ if (result.meshes.length > 0) {
307
+ const mesh = result.meshes[0];
308
+ console.log(\`\\nSample mesh:\`);
309
+ console.log(\` Express ID: \${mesh.express_id}\`);
310
+ console.log(\` Vertices: \${mesh.positions.length / 3}\`);
311
+ console.log(\` Triangles: \${mesh.indices.length / 3}\`);
312
+ console.log(\` Color: rgba(\${mesh.color.join(', ')})\`);
313
+ }
314
+ } else {
315
+ // Fallback to JSON format
316
+ console.log('Parquet not available, using JSON format');
317
+ console.log('Install optional deps for smaller payloads: npm install parquet-wasm apache-arrow');
318
+
319
+ const result = await client.parse(buffer);
320
+
321
+ const elapsed = performance.now() - startTime;
322
+ console.log(\`\\nParsing complete in \${elapsed.toFixed(0)}ms\`);
323
+ console.log(\` Cache key: \${result.cache_key.substring(0, 16)}...\`);
324
+ console.log(\` Meshes: \${result.meshes.length}\`);
325
+ }
326
+ } catch (error) {
327
+ console.error('Parse failed:', error);
328
+ process.exit(1);
329
+ }
330
+ }
331
+
332
+ main().catch(console.error);
333
+ `);
334
+ // src/example-stream.ts - Streaming example for large files
335
+ writeFileSync(join(targetDir, 'src', 'example-stream.ts'), `/**
336
+ * IFC-Lite Server Streaming Example
337
+ *
338
+ * This example demonstrates streaming parsing for large IFC files.
339
+ * Geometry batches are received progressively, enabling immediate rendering
340
+ * while the server continues processing.
341
+ *
342
+ * Best for: Files > 50MB where you want progressive rendering
343
+ *
344
+ * Prerequisites:
345
+ * 1. Start the server: docker compose up -d
346
+ * 2. Install optional deps: npm install parquet-wasm apache-arrow
347
+ * 3. Run: npm run example:stream <path-to-ifc>
348
+ */
349
+
350
+ import { IfcServerClient } from '@ifc-lite/server-client';
351
+ import { readFileSync, existsSync } from 'fs';
352
+
353
+ const SERVER_URL = process.env.SERVER_URL || 'http://localhost:3001';
354
+
355
+ async function main() {
356
+ const client = new IfcServerClient({
357
+ baseUrl: SERVER_URL,
358
+ timeout: 600000, // 10 minutes for very large files
359
+ });
360
+
361
+ // Check server
362
+ try {
363
+ await client.health();
364
+ console.log('Server connected');
365
+ } catch {
366
+ console.error('Server not available. Start with: docker compose up -d');
367
+ process.exit(1);
368
+ }
369
+
370
+ const ifcPath = process.argv[2];
371
+ if (!ifcPath || !existsSync(ifcPath)) {
372
+ console.log('Usage: npm run example:stream <path-to-ifc-file>');
373
+ process.exit(1);
374
+ }
375
+
376
+ const buffer = readFileSync(ifcPath);
377
+ console.log(\`\\nStreaming: \${ifcPath} (\${(buffer.length / 1024 / 1024).toFixed(1)} MB)\`);
378
+
379
+ // Check Parquet support
380
+ const parquetAvailable = await client.isParquetSupported();
381
+ if (!parquetAvailable) {
382
+ console.error('Streaming requires parquet-wasm and apache-arrow.');
383
+ console.error('Install with: npm install parquet-wasm apache-arrow');
384
+ process.exit(1);
385
+ }
386
+
387
+ const startTime = performance.now();
388
+ let totalMeshes = 0;
389
+ let batchCount = 0;
390
+
391
+ try {
392
+ // Stream with batch callback
393
+ const result = await client.parseParquetStream(buffer, (batch) => {
394
+ batchCount++;
395
+ totalMeshes += batch.meshes.length;
396
+
397
+ // In a real app, you would render each batch immediately
398
+ console.log(
399
+ \` Batch #\${batch.batch_number}: +\${batch.meshes.length} meshes \` +
400
+ \`(decode: \${batch.decode_time_ms.toFixed(0)}ms) - Total: \${totalMeshes}\`
401
+ );
402
+ });
403
+
404
+ const elapsed = performance.now() - startTime;
405
+ console.log(\`\\nStreaming complete!\`);
406
+ console.log(\` Total time: \${elapsed.toFixed(0)}ms\`);
407
+ console.log(\` Batches received: \${batchCount}\`);
408
+ console.log(\` Total meshes: \${result.total_meshes}\`);
409
+ console.log(\` Cache key: \${result.cache_key.substring(0, 16)}...\`);
410
+
411
+ if (result.stats) {
412
+ console.log(\`\\nServer processing:\`);
413
+ console.log(\` Parse: \${result.stats.parse_time_ms}ms\`);
414
+ console.log(\` Geometry: \${result.stats.geometry_time_ms}ms\`);
415
+ console.log(\` Triangles: \${result.stats.total_triangles}\`);
416
+ }
417
+
418
+ // Optionally fetch full data model for properties panel
419
+ console.log(\`\\nFetching data model for properties...\`);
420
+ const dataModel = await client.fetchDataModel(result.cache_key);
421
+ if (dataModel) {
422
+ console.log(\` Data model size: \${(dataModel.byteLength / 1024).toFixed(1)} KB\`);
423
+ }
424
+
425
+ } catch (error) {
426
+ console.error('Streaming failed:', error);
427
+ process.exit(1);
428
+ }
429
+ }
430
+
431
+ main().catch(console.error);
432
+ `);
433
+ // src/index.ts - Library re-export for custom integrations
434
+ writeFileSync(join(targetDir, 'src', 'index.ts'), `/**
435
+ * ${projectName} - IFC Processing Server Client
436
+ *
437
+ * Re-exports the IFC-Lite server client for custom integrations.
438
+ * See example.ts and example-stream.ts for usage examples.
439
+ */
440
+
441
+ export { IfcServerClient } from '@ifc-lite/server-client';
442
+ export type {
443
+ ServerConfig,
444
+ ParseResponse,
445
+ ParquetParseResponse,
446
+ StreamEvent,
447
+ HealthResponse,
448
+ MetadataResponse,
449
+ } from '@ifc-lite/server-client';
450
+
451
+ // Default server URL
452
+ export const DEFAULT_SERVER_URL = 'http://localhost:3001';
453
+
454
+ /**
455
+ * Create a pre-configured client for the local Docker server.
456
+ */
457
+ export function createLocalClient(options?: { timeout?: number }) {
458
+ const { IfcServerClient } = require('@ifc-lite/server-client');
459
+ return new IfcServerClient({
460
+ baseUrl: process.env.SERVER_URL || DEFAULT_SERVER_URL,
461
+ timeout: options?.timeout ?? 300000,
462
+ });
463
+ }
464
+ `);
465
+ // README.md
466
+ writeFileSync(join(targetDir, 'README.md'), `# ${projectName}
467
+
468
+ IFC processing server using [IFC-Lite](https://github.com/louistrue/ifc-lite).
469
+
470
+ ## Quick Start
471
+
472
+ \`\`\`bash
473
+ # 1. Start the server
474
+ docker compose up -d
475
+
476
+ # 2. Install client dependencies
477
+ npm install
478
+
479
+ # 3. Run the example (replace with your IFC file)
480
+ npm run example ./your-model.ifc
481
+ \`\`\`
482
+
483
+ ## Features
484
+
485
+ | Feature | Description |
486
+ |---------|-------------|
487
+ | **Content-Addressable Cache** | Same file = instant response (no reprocessing) |
488
+ | **Parquet Format** | 15x smaller payloads than JSON |
489
+ | **Streaming** | Progressive geometry for large files |
490
+ | **Parallel Processing** | Multi-threaded geometry processing |
491
+
492
+ ## Architecture
493
+
494
+ \`\`\`
495
+ ┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
496
+ │ Your App │────▶│ IFC-Lite Server │────▶│ Cache │
497
+ │ (TypeScript) │◀────│ (Docker) │◀────│ (Volume) │
498
+ └─────────────────┘ └──────────────────┘ └─────────────┘
499
+ \`\`\`
500
+
501
+ ## Scripts
502
+
503
+ | Command | Description |
504
+ |---------|-------------|
505
+ | \`npm run example\` | Basic parsing example |
506
+ | \`npm run example:stream\` | Streaming example for large files |
507
+ | \`npm run server:start\` | Start server in background |
508
+ | \`npm run server:stop\` | Stop server |
509
+ | \`npm run server:logs\` | View server logs |
510
+ | \`npm run server:dev\` | Start with debug logging |
511
+
512
+ ## Configuration
513
+
514
+ Copy \`.env.example\` to \`.env\` to customize:
515
+
516
+ | Variable | Default | Description |
517
+ |----------|---------|-------------|
518
+ | \`PORT\` | 3001 | Server port |
519
+ | \`MAX_FILE_SIZE_MB\` | 500 | Max upload size |
520
+ | \`WORKER_THREADS\` | 4 | Parallel processing threads |
521
+ | \`CACHE_MAX_AGE_DAYS\` | 7 | Cache retention |
522
+
523
+ See \`.env.example\` for all options with documentation.
524
+
525
+ ## API Endpoints
526
+
527
+ | Endpoint | Description |
528
+ |----------|-------------|
529
+ | \`GET /api/v1/health\` | Health check |
530
+ | \`POST /api/v1/parse\` | Full parse (JSON response) |
531
+ | \`POST /api/v1/parse/parquet\` | Full parse (Parquet, 15x smaller) |
532
+ | \`POST /api/v1/parse/parquet-stream\` | Streaming parse (SSE + Parquet) |
533
+ | \`GET /api/v1/cache/check/:hash\` | Check if file is cached |
534
+
535
+ ## Client Usage
536
+
537
+ ### Basic Parse
538
+
539
+ \`\`\`typescript
540
+ import { IfcServerClient } from '@ifc-lite/server-client';
541
+
542
+ const client = new IfcServerClient({
543
+ baseUrl: 'http://localhost:3001'
544
+ });
545
+
546
+ const result = await client.parseParquet(ifcBuffer);
547
+ console.log(\`Meshes: \${result.meshes.length}\`);
548
+ \`\`\`
549
+
550
+ ### Streaming (Large Files)
551
+
552
+ \`\`\`typescript
553
+ await client.parseParquetStream(ifcBuffer, (batch) => {
554
+ // Render each batch immediately
555
+ for (const mesh of batch.meshes) {
556
+ scene.addMesh(mesh);
557
+ }
558
+ });
559
+ \`\`\`
560
+
561
+ ### Cache-First Pattern
562
+
563
+ \`\`\`typescript
564
+ // Client automatically:
565
+ // 1. Computes file hash locally
566
+ // 2. Checks server cache
567
+ // 3. Skips upload if cached (instant response!)
568
+ const result = await client.parseParquet(ifcBuffer);
569
+ \`\`\`
570
+
571
+ ## Production Deployment
572
+
573
+ ### Railway / Render / Fly.io
574
+
575
+ The Docker image works on any container platform:
576
+
577
+ \`\`\`bash
578
+ # Pull and run
579
+ docker pull ghcr.io/louistrue/ifc-lite-server:latest
580
+ docker run -p 8080:8080 -v ifc-cache:/app/cache ghcr.io/louistrue/ifc-lite-server
581
+ \`\`\`
582
+
583
+ ### Environment Variables
584
+
585
+ Set these in your deployment platform:
586
+
587
+ \`\`\`
588
+ PORT=8080
589
+ MAX_FILE_SIZE_MB=500
590
+ WORKER_THREADS=4
591
+ CACHE_MAX_AGE_DAYS=30
592
+ RUST_LOG=info
593
+ \`\`\`
594
+
595
+ ## Learn More
596
+
597
+ - [IFC-Lite Documentation](https://louistrue.github.io/ifc-lite/)
598
+ - [Server API Reference](https://louistrue.github.io/ifc-lite/api/server/)
599
+ - [GitHub Repository](https://github.com/louistrue/ifc-lite)
600
+ `);
601
+ console.log(' Created docker-compose.yml');
602
+ console.log(' Created docker-compose.dev.yml');
603
+ console.log(' Created .env.example');
604
+ console.log(' Created .env');
605
+ console.log(' Created package.json');
606
+ console.log(' Created tsconfig.json');
607
+ console.log(' Created src/example.ts');
608
+ console.log(' Created src/example-stream.ts');
609
+ console.log(' Created src/index.ts');
610
+ console.log(' Created README.md');
611
+ console.log(' Created .gitignore');
612
+ console.log(' Created .dockerignore');
613
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Fetch the latest published version of @ifc-lite/parser from npm.
3
+ * Falls back to '^1.0.0' when the registry is unreachable.
4
+ */
5
+ export declare function getLatestVersion(): string;
6
+ /**
7
+ * Rewrite the viewer's package.json so it works as a standalone project:
8
+ * - Set the project name
9
+ * - Replace workspace: protocol versions with the latest npm version
10
+ * - Remove the .git directory if present
11
+ */
12
+ export declare function fixPackageJson(targetDir: string, projectName: string): void;
13
+ /**
14
+ * Write a standalone tsconfig.json without monorepo references.
15
+ */
16
+ export declare function fixTsConfig(targetDir: string): void;
17
+ /**
18
+ * Write a standalone vite.config.ts with WASM support.
19
+ */
20
+ export declare function fixViteConfig(targetDir: string): void;
21
+ /**
22
+ * Apply all viewer-template fixups: package.json, tsconfig, vite config.
23
+ */
24
+ export declare function fixViewerTemplate(targetDir: string, projectName: string): void;