Something went wrong. Try again.
Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104import { createHash } from "node:crypto";import { copyFileSync, existsSync, readFileSync, realpathSync, writeFileSync } from "node:fs";import { createRequire } from "node:module";import { basename, dirname, join } from "node:path";
const [appDir, themePath, fontPath] = process.argv.slice(2);
function packageDir(from, name) { for (const dir of createRequire(join(from, "/")).resolve.paths(name)) { const candidate = join(dir, name); if (existsSync(candidate)) return realpathSync(candidate); } throw new Error(`${name} not resolvable from ${from}`);}
const pdsDir = packageDir(appDir, "@atproto/pds");const providerDir = join(packageDir(pdsDir, "@atproto/oauth-provider"), "dist");const uiManifestPath = createRequire(join(providerDir, "router/assets/assets.js")).resolve( "@atproto/oauth-provider-ui/bundle-manifest.json",);
const sha256 = (data) => createHash("sha256").update(data).digest("base64");
function patch(path, replacements, { all = false, append = "" } = {}) { let text = readFileSync(path, "utf8"); for (const [from, to] of replacements) { const count = text.split(from).length - 1; if (all ? count === 0 : count !== 1) throw new Error(`${path}: expected ${all ? "some" : "one"} ${from}, found ${count}`); text = text.replaceAll(from, () => to); } text += append; writeFileSync(path, text); return text;}
patch(join(pdsDir, "dist/mailer/index.js"), [ ["logoUrl: branding.logo ?? DEFAULT_LOGO_URL,", "logoUrl: process.env.PDS_EMAIL_LOGO_URL ?? branding.logo ?? DEFAULT_LOGO_URL,"], ["markUrl: branding.logo ?? DEFAULT_MARK_URL,", "markUrl: process.env.PDS_EMAIL_LOGO_URL ?? branding.logo ?? DEFAULT_MARK_URL,"],]);
patch(join(providerDir, "oauth-provider.js"), [["ttl: 600e3", "ttl: 1e3"]], { all: true });
patch(join(providerDir, "lib/csp/index.js"), [[" 'default-src',\n", " 'default-src',\n 'font-src',\n"]]);patch(join(providerDir, "router/assets/assets.js"), [ [`'connect-src': ["'self'"],`, `'connect-src': ["'self'"],\n 'font-src': ["'self'"],`],]);patch(join(providerDir, "router/assets/assets.js"), [["'img-src': ['https:'],", "'img-src': ['https:', 'data:'],"]]);patch(join(providerDir, "router/assets/assets-manifest.js"), [ ["[null, 'document', 'style', 'script']", "[null, 'document', 'style', 'script', 'font']"], ["'public, max-age=31536000, immutable'", "'no-cache'"],]);
const uiDir = dirname(uiManifestPath);const manifest = JSON.parse(readFileSync(uiManifestPath, "utf8"));const styles = Object.entries(manifest).filter(([, asset]) => asset.mime === "text/css");if (styles.length === 0) throw new Error(`${uiManifestPath}: no stylesheet in manifest`);
const theme = readFileSync(themePath, "utf8");for (const [filename, asset] of styles) { if (asset.data) throw new Error(`${filename}: inlined in manifest`); const css = patch( join(uiDir, filename), [ ["--radius:.625rem", "--radius:.5rem"], ["calc(var(--radius) + 4px)", "var(--radius)"], ["calc(var(--radius) - 2px)", "var(--radius)"], ["calc(var(--radius) - 4px)", "var(--radius)"], ], { all: true, append: theme }, ); asset.sha256 = sha256(css);}
const scripts = [ [/flag:`[\u{1F1E6}-\u{1F1FF}]{2}`/gu, "flag:``"], [ /(side:\w+=`bottom`,sideOffset:\w+=)4(,align:\w+=)`center`(,alignOffset:\w+=0,alignItemWithTrigger:\w+=)!0/g, "$18$2`start`$3!1", ],];const hits = scripts.map(() => 0);for (const [filename, asset] of Object.entries(manifest)) { if (asset.type !== "chunk") continue; const path = join(uiDir, filename); let js = readFileSync(path, "utf8"); scripts.forEach(([pattern, replacement], i) => { js = js.replace(pattern, (...match) => { hits[i]++; return replacement.replace(/\$(\d)/g, (_, n) => match[n]); }); }); writeFileSync(path, js); asset.sha256 = sha256(js);}scripts.forEach(([pattern], i) => { if (hits[i] === 0) throw new Error(`${uiDir}: ${pattern} not found`);});
const font = basename(fontPath);copyFileSync(fontPath, join(uiDir, font));manifest[font] = { type: "asset", mime: "font/woff2", sha256: sha256(readFileSync(fontPath)) };
writeFileSync(uiManifestPath, JSON.stringify(manifest));