Skip to main content
Glama
deleonio
by deleonio
hashing.js4.46 kB
#!/usr/bin/env node // https://github.com/deckgo/deckdeckgo/blob/96d33cbd906223b32dd65702f9502c9b90589a72/studio/scripts/config.index.js#L35 /** * Add to npm scripts like * * "build": "stenicl build ... && node hashing.js" */ const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); function genSha(text, methode = 'sha512') { return crypto.createHash(methode).update(text).digest('base64'); } function genShaAsHash(text, methode = 'sha512') { return `${methode}-${genSha(text, methode)}`; } function genShaAsHashAndApostrophe(text, methode = 'sha512') { return `'${genShaAsHash(text, methode)}'`; } function updateCSP(filename) { fs.readFile(`${filename}`, 'utf8', function (err, data) { if (err) { return console.log(err); } data = data.replace(/("default\-src 'self'[^"]+)/, `"default-src 'self' *.jsdelivr.net ${Array.from(CSP_HASHES).join(' ')}`); fs.writeFile(`${filename}`, data, 'utf8', function (err) { if (err) return console.log(err); }); }); } function findSWHash(data) { const sw = /(<.?script data-build.*?>)([\s\S]*?)(<\/script>)/gm; let m; while ((m = sw.exec(data))) { if (m && m.length >= 3 && m[2].indexOf('serviceWorker') > -1) { return `'sha256-${crypto.createHash('sha256').update(m[2]).digest('base64')}'`; } } return undefined; } function findPreloadModuleLinksHash(data) { const preload = /(<.?link (rel=\"modulepreload\"|rel=modulepreload).*?>)/gm; const shas = []; let m; while ((m = preload.exec(data))) { console.log(m[0], `'sha256-${crypto.createHash('sha256').update(m[0]).digest('base64')}'`); shas.push(`'sha256-${crypto.createHash('sha256').update(m[0]).digest('base64')}'`); } return shas && shas.length > 0 ? shas.join(' ') : undefined; } function genHyndradHash(dir) { fs.readdirSync(dir).forEach((file) => { const fullPath = path.join(dir, file); if (fs.lstatSync(fullPath).isDirectory()) { genHyndradHash(fullPath); } else if (/esm.js$/.test(file)) { let code = fs.readFileSync(fullPath, 'utf-8'); let list = null; if (/bootstrapLazy\(/.test(code)) { code = code.replace(/^[\s\S]*?bootstrapLazy\(/, ''); code = code.replace(/, options\)[\s\S]*/, ''); list = JSON.parse(code); if (Array.isArray(list)) { for (let i = 0; i < list.length; i++) { list[i] = list[i][0]; } } } else { code = code.replace(/( |\n)/g, ''); code = code.replace(/.*\((\[\['p\-)/, '$1'); code = code.replace(/[^\]]+$/, ''); code = code.replace(/,\]/g, ']'); list = code.match(/p\-[a-z0-9]+("|'),\[\[1,("|')[^("|')]+/g); if (Array.isArray(list)) { for (let i = 0; i < list.length; i++) { list[i] = list[i].replace(/^([^"]+")+/, ''); } } } if (Array.isArray(list)) { const css = `${list.join(',')}{visibility:hidden}.hydrated{visibility:inherit}`; sha = genShaAsHashAndApostrophe(css); // console.log(css, list, list.length, sha); CSP_HASHES.add(sha); } } }); } function genArtifactHashes(dir) { fs.readdirSync(dir).forEach((file) => { const fullPath = path.join(dir, file); if (fs.lstatSync(fullPath).isDirectory()) { genArtifactHashes(fullPath); } else if (path.extname(fullPath) === '.js') { let code = fs.readFileSync(fullPath, 'utf-8'); let css = null; if (/Css ?= ?"[^"]/.test(code)) { code = code.replace(/^[\s\S]*?Css ?= ?"/, ''); let matches = code.match(/[^\n]+/); if (matches !== null) { css = matches[0]; } // } else if (/\.style='/.test(code)) { // css = code.replace(/.*\.style='/, ''); // css = css.replace(/';export.*/, ''); } if (typeof css === 'string') { css = css .replace(/";$/, '') .replace(/\\"/g, '"') .replace( /\\n/g, ` `, ) .replace(/\\\\/g, `\\`); sha = genShaAsHashAndApostrophe(css); console.log(css, sha); fs.writeFileSync(fullPath.replace(/.js$/, '.css'), css, 'utf-8'); CSP_HASHES.add(`${sha}`); } } }); } let htmlFiles = ['./src/index.html', './www/index.html']; let expects = []; const test = new Set(); expects.forEach((cspHash) => { test.add(`'${cspHash}'`); }); const CSP_HASHES = new Set(); const genCSPHashes = () => { genHyndradHash(path.resolve('./www/build')); genArtifactHashes(path.resolve('./www/build')); console.log(CSP_HASHES); for (const file of htmlFiles) { updateCSP(`./${file}`); } }; genCSPHashes(); module.exports = genCSPHashes;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/deleonio/public-ui-kolibri'

If you have feedback or need assistance with the MCP directory API, please join our Discord server