deploy-research-library-bridge.mjs 2.6 KB

1234567891011121314151617181920212223242526
  1. import fs from 'node:fs/promises';
  2. import crypto from 'node:crypto';
  3. import {request,invoke} from '../server/scripts/platform-client.mjs';
  4. const name='ksfResearchLibrary',route='/'+name,work='work/database-enrichment-20261110';
  5. await fs.mkdir(work,{recursive:true});
  6. const source=(await fs.readFile('server/src/research-library-bridge.mjs','utf8')).replace(/^export /gm,'');
  7. const entry=`\nasync function handler(request,response){const crypto=await import('node:crypto');const fs=await import('node:fs/promises');const cp=await import('node:child_process');return createResearchLibraryBridge({Parse,crypto,fs,spawn:cp.spawn,loadDatabase:async()=>{const m=await import('parse-server/lib/Config.js');const C=m.default?.default||m.default;const a=C.get('FKieRbIoGt_main').database?.adapter;if(a?.constructor?.name!=='PostgresStorageAdapter'||typeof a._client?.tx!=='function')throw Error('INCOMPATIBLE_DATABASE');return a._client;}})(request,response);}\n`;
  8. const code=source+entry;new Function(code);
  9. const sha=s=>crypto.createHash('sha256').update(s).digest('hex');
  10. await fs.writeFile(work+'/research-library-bridge.js',code);
  11. const matches=(await request('GET','/classes/Function?'+new URLSearchParams({where:JSON.stringify({$or:[{name},{path:route}]}),limit:'3'}))).results;
  12. if(matches.length>1||matches.some(x=>x.name!==name||x.path!==route))throw Error('FUNCTION_CONFLICT');
  13. if(matches.length&&matches[0].code!==code){const priorFile=work+'/bridge-deployed.json';const prior=JSON.parse(await fs.readFile(priorFile,'utf8'));if(prior.sha256!==sha(matches[0].code))throw Error('UNKNOWN_FUNCTION_BASELINE');}
  14. if(!process.argv.includes('--apply')){
  15. console.log(JSON.stringify({ok:true,function:name,action:matches.length?'update':'create',sha256:sha(code),databaseWrites:0}));
  16. }else{
  17. if(matches.length)await fs.writeFile(work+'/bridge-before-'+Date.now()+'.json',JSON.stringify(matches[0],null,2));
  18. let id=matches[0]?.objectId;
  19. if(!id)id=(await request('POST','/classes/Function',{name,path:route,code,ACL:{}})).objectId;
  20. else if(matches[0].code!==code)await request('PUT','/classes/Function/'+id,{code});
  21. const read=await request('GET','/classes/Function/'+id);if(read.code!==code||read.path!==route)throw Error('FUNCTION_READBACK_FAILED');
  22. const receipt={ok:true,name,objectId:id,sha256:sha(code),updatedAt:new Date().toISOString(),businessDataWrites:0};
  23. await fs.writeFile(work+'/bridge-deployed.json',JSON.stringify(receipt,null,2));
  24. const probe=await invoke(name,{action:'probe'});await fs.writeFile(work+'/bridge-probe.json',JSON.stringify(probe,null,2));
  25. console.log(JSON.stringify({deployment:receipt,probe}));
  26. }