// Separate development database/role/app: regression resets cannot erase it. import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import {spawnSync} from 'node:child_process'; const pointer='C:/laragon/data/sgf-tempo/run/modular-regression-current.json'; const state=JSON.parse(fs.readFileSync(pointer,'utf8')); if(!/^[a-f0-9]{12}$/.test(state.id)||path.basename(state.root)!=='modular-regression-'+state.id||state.port!==55439)throw Error('Unexpected isolated host'); if(state.development)throw Error('Development host already configured; preserve it.'); const database='sgf_modules_dev_'+state.id,role='sgf_modules_qa_'+state.id,password=crypto.randomBytes(30).toString('hex'); const app=path.join(state.root,'development-app'),pg='C:/Program Files/PostgreSQL/17/bin'; const admin=fs.readFileSync(path.join(state.root,'private/admin-password.txt'),'utf8'); function run(exe,args,options={}){const r=spawnSync(exe,args,{encoding:'utf8',windowsHide:true,maxBuffer:8*1024*1024,...options});if(r.status!==0)throw Error((r.stdout||'')+(r.stderr||''));return r.stdout;} const identity=run(path.join(pg,'psql.exe'),['-h','127.0.0.1','-p',String(state.port),'-U','sgf_regression_owner','-d','postgres','-At','-c',"SELECT current_setting('cluster_name')"],{env:{...process.env,PGPASSWORD:admin}}).trim(); if(identity!=='sgf_modular_regression_'+state.id)throw Error('Unexpected database cluster'); fs.cpSync(state.app,app,{recursive:true,filter:p=>!['storage','.env','.env.testing','.env.browser-testing'].includes(path.relative(state.app,p).split(path.sep)[0])&&!p.includes(path.join('bootstrap','cache')+path.sep)}); for(const dir of ['storage/framework/cache/data','storage/framework/sessions','storage/framework/views','storage/logs','bootstrap/cache'])fs.mkdirSync(path.join(app,dir),{recursive:true}); if(fs.existsSync(path.join(app,'public/hot')))fs.unlinkSync(path.join(app,'public/hot')); function files(dir){return fs.readdirSync(dir,{withFileTypes:true}).flatMap(e=>e.isDirectory()?files(path.join(dir,e.name)):[path.join(dir,e.name)]);} const adaptations=[]; for(const dir of ['app','database','config','tests','scripts'])for(const p of files(path.join(app,dir)).filter(p=>/\.(php|sql|mjs)$/.test(p))){ const text=fs.readFileSync(p,'utf8'),next=text.replaceAll('sgf_tempo_test',database).replaceAll('sgf_test_runner',role); if(next!==text){fs.writeFileSync(p,next);adaptations.push(path.relative(app,p));} } fs.writeFileSync(path.join(state.root,'development-identity-adaptations.json'),JSON.stringify(adaptations,null,2)); run(path.join(pg,'psql.exe'),['-h','127.0.0.1','-p',String(state.port),'-U','sgf_regression_owner','-d','postgres','-v','ON_ERROR_STOP=1'],{env:{...process.env,PGPASSWORD:admin},input:`CREATE ROLE ${role} LOGIN PASSWORD '${password}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;\nCREATE DATABASE ${database} OWNER ${role};\nREVOKE ALL ON DATABASE ${database} FROM PUBLIC;\n`}); const env=`APP_NAME=SGF-Modular-Development\nAPP_KEY=base64:${crypto.randomBytes(32).toString('base64')}\nAPP_DEBUG=false\nAPP_URL=http://127.0.0.1:${state.web_port}\nAPP_ENV=testing\nDB_CONNECTION=pgsql\nDB_HOST=127.0.0.1\nDB_PORT=${state.port}\nDB_DATABASE=${database}\nDB_USERNAME=${role}\nDB_PASSWORD=${password}\nDB_URL=\nSESSION_DRIVER=array\nCACHE_STORE=array\nBCRYPT_ROUNDS=4\n`; fs.writeFileSync(path.join(app,'.env.testing'),env); fs.writeFileSync(path.join(app,'.env'),env.replace('APP_ENV=testing','APP_ENV=local')); run('php',['artisan','migrate','--env=testing','--force','--no-interaction'],{cwd:app}); const provision=run('php',['scripts/modular-development-profiles.php',path.join(state.root,'private/development.json')],{cwd:app}); state.development={app,database,role,port:state.port,url:`http://127.0.0.1:${state.web_port}`}; fs.writeFileSync(pointer,JSON.stringify(state,null,2));fs.writeFileSync(path.join(state.root,'development-provision.json'),provision); console.log(JSON.stringify({configured:true,...state.development,credentials_printed:false}));