build-data-dictionary.mjs 2.7 KB

123456789101112131415161718192021222324252627282930313233
  1. // Build only the new read-only metadata function; preserve every existing function.
  2. import fs from 'node:fs';
  3. import path from 'node:path';
  4. import crypto from 'node:crypto';
  5. import {fileURLToPath} from 'node:url';
  6. const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
  7. const data=JSON.parse(fs.readFileSync(path.join(root,'references/runtime-data.json'),'utf8'));
  8. const dictionary=JSON.parse(fs.readFileSync(path.join(root,'references/business-data-dictionary.json'),'utf8'));
  9. const common=['postgres.mjs','core.mjs','data-dictionary.mjs'].map(n=>fs.readFileSync(path.join(root,'src',n),'utf8').replace(/^export /gm,'')).join('\n');
  10. const entry=`async function handler(request,response){
  11. response.setHeader('Cache-Control','no-store');
  12. try{
  13. const crypto=await import('node:crypto');const DATA=${JSON.stringify(data)};const DICTIONARY=${JSON.stringify(dictionary)};
  14. if(Parse.applicationId!==DATA.appId)throw Object.assign(Error('APP_MISMATCH'),{code:'CAPABILITY_UNAVAILABLE'});
  15. const module=await import('parse-server/lib/Config.js');const Config=module.default?.default||module.default;
  16. const pg=Config.get(DATA.appId).database?.adapter?._client;
  17. if(typeof pg?.any!=='function')throw Object.assign(Error('METADATA_UNAVAILABLE'),{code:'CAPABILITY_UNAVAILABLE'});
  18. const store=createPostgresStore(pg,DATA.tables,crypto);
  19. const app=createApplication({store,crypto,Parse,data:DATA,settings:{masterKey:Parse.masterKey,parseUrl:'https://kangshifu.fmode.cn/parse'},files:{}});
  20. const p=request.body?.params??{};
  21. const result=await readAuthorizedDataDictionary({app,pg,dictionary:DICTIONARY},request.headers,p);
  22. result.schemaFingerprint=crypto.createHash('sha256').update(JSON.stringify(result.tables)).digest('hex');
  23. return response.json({result:{ok:true,status:'ok',requestId:p.requestId||crypto.randomUUID(),data:result,errors:[]}});
  24. }catch(e){const status=e.code==='AUTH_REQUIRED'?401:e.code==='FORBIDDEN'?403:400;
  25. return response.status(status).json({result:{ok:false,error:{code:['AUTH_REQUIRED','FORBIDDEN','VALIDATION_FAILED','REFERENCE_NOT_FOUND','CAPABILITY_UNAVAILABLE'].includes(e.code)?e.code:'DICTIONARY_READ_FAILED'},readOnly:true,databaseWrites:0}});
  26. }
  27. }`;
  28. const code=common+'\n'+entry;new Function(code);
  29. const out=path.join(root,'dist/data-dictionary');fs.mkdirSync(out,{recursive:true});
  30. fs.writeFileSync(path.join(out,'ksfGetDataDictionary.js'),code);
  31. const manifest={release:'ksf.data-dictionary.20261106.v1',existingFunctionsModified:false,databaseWrites:0,
  32. functions:[{name:'ksfGetDataDictionary',path:'/ksfGetDataDictionary',file:'ksfGetDataDictionary.js',sha256:crypto.createHash('sha256').update(code).digest('hex')}]};
  33. fs.writeFileSync(path.join(out,'manifest.json'),JSON.stringify(manifest,null,2)+'\n');console.log(JSON.stringify(manifest));