Files
crm/tools/export-models.js
T

56 lines
3.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// Exporteert de standaardmodellen van de configurator (HouseModel.MODELS) als house-design-JSON,
// precies zoals Bestand › Opslaan in de configurator ze wegschrijft.
// Gebruik: node tools/export-models.js [pad-naar-configurator] [uitvoermap]
// Standaard: ../configurator → demo/modellen/
'use strict';
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const root = path.dirname(__dirname);
const SRC = path.resolve(process.argv[2] || path.join(root, '..', 'configurator'));
const OUT = path.resolve(process.argv[3] || path.join(root, 'demo', 'modellen'));
// De rekenmodules in de volgorde van light.html; alleen wat nodig is om een model op te bouwen.
const SCRIPTS = [
'js/vendor/three.min.js', 'js/core/geometry.js', 'js/core/view-layers.js', 'js/wall/kozijn-model.js',
'js/core/ui-kit.js', 'js/wall/wall-model.js', 'js/floor/floor-model.js', 'js/roof/roof-model.js', 'js/roof/post-model.js',
'js/lighting/lighting-model.js', 'js/elektra/elektra-model.js', 'js/sandwich/sandwich-model.js', 'js/wall/wall.js', 'js/floor/floor.js',
'js/unit/unit-model.js', 'js/room/room-model.js', 'js/interior/fixture-model.js',
'js/house/chimney-model.js', 'js/house/house-model.js'
];
// Minimale browseromgeving: de modules raken het DOM alleen bij het tekenen, niet bij het opbouwen.
const noop = () => {};
const el = () => new Proxy(function () {}, { get: (t, k) => (k === Symbol.toPrimitive ? () => '' : el()), apply: () => el(), construct: () => el() });
const ctx = { console, Math, JSON, Date, setTimeout, clearTimeout, URL, Blob: function () {}, Image: function () { return el(); } };
ctx.window = ctx; ctx.self = ctx; ctx.globalThis = ctx;
ctx.document = { createElement: () => el(), getElementById: () => null, querySelector: () => null, querySelectorAll: () => [], addEventListener: noop, head: el(), body: el(), currentScript: null };
ctx.navigator = { userAgent: 'node', platform: 'node', maxTouchPoints: 0 };
ctx.location = { href: 'http://localhost/', search: '' };
ctx.fetch = () => Promise.reject(new Error('geen fetch'));
ctx.addEventListener = noop;
vm.createContext(ctx);
for (const s of SCRIPTS) {
const file = path.join(SRC, s);
// const/let op het hoogste niveau blijven in het script; zet de modulenamen expliciet op het globale object.
let code = fs.readFileSync(file, 'utf8');
const names = [...code.matchAll(/^(?:const|let|var|class)\s+([A-Z][A-Za-z0-9_]*)\s*=?/gm)].map(m => m[1]);
code += '\n' + names.map(n => `try { globalThis.${n} = ${n}; } catch (e) {}`).join('\n');
vm.runInContext(code, ctx, { filename: file });
}
const version = (fs.readFileSync(path.join(SRC, 'js/app.js'), 'utf8').match(/APP_VERSION\s*=\s*['"]([^'"]+)/) || [])[1] || '';
fs.mkdirSync(OUT, { recursive: true });
const index = [];
for (const [key, def] of Object.entries(ctx.HouseModel.MODELS)) {
const state = ctx.HouseModel.normalize(ctx.HouseModel.clone(def.create()));
state.project = Object.assign({}, state.project, { naam: state.project.naam || def.label });
const design = { type: 'house-design', version: 1, exportedAt: new Date().toISOString(), model: key, configurator: version, ...state };
fs.writeFileSync(path.join(OUT, `${key}.json`), JSON.stringify(design));
index.push({ key, label: def.label });
console.log(`${key}.json ${def.label} (${state.units.length} units)`);
}
fs.writeFileSync(path.join(OUT, 'index.json'), JSON.stringify({ configurator: version, models: index }, null, 2) + '\n');