check-site-modes.mjs 1.3 KB

1234567891011121314151617
  1. import fs from 'node:fs';
  2. import path from 'node:path';
  3. import {fileURLToPath} from 'node:url';
  4. const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
  5. const manifest=JSON.parse(fs.readFileSync(path.join(root,'deploy/industry-ui-files.json')));
  6. const args=process.argv.slice(2);
  7. if(args[0]!=='--target-dir'||!args[1]||args.length>3||args[2]&&args[2]!=='--require-all')throw Error('USAGE');
  8. const target=path.resolve(args[1]),requireAll=args[2]==='--require-all';
  9. if(!path.isAbsolute(args[1])||fs.realpathSync(target)!==target||target===path.parse(target).root)throw Error('UNSAFE_TARGET_DIRECTORY');
  10. const files=['index.html',...manifest.files.map(f=>f.path)].map(name=>{
  11. const file=path.resolve(target,name);if(!file.startsWith(target+path.sep))throw Error('PATH_OUTSIDE_TARGET');
  12. if(!fs.existsSync(file))return {path:name,exists:false,ok:!requireAll&&manifest.files.some(f=>f.path===name&&f.allowMissing)};
  13. const stat=fs.lstatSync(file),mode=stat.mode&0o777;
  14. return {path:name,exists:true,mode:mode.toString(8),ok:stat.isFile()&&!stat.isSymbolicLink()&&mode===0o644};
  15. });
  16. const result={ok:process.platform!=='win32'&&files.every(f=>f.ok),readOnly:true,files,platform:process.platform,networkRequests:0};
  17. console.log(JSON.stringify(result,null,2));if(!result.ok)process.exitCode=1;